Compare commits

..

11 Commits

Author SHA1 Message Date
sami7777 2e19ec350d Fix unit tests: FormatMoney 6-digit precision, exclude Bitcoin tx tests
Build All Platforms / test-linux-unit (push) Waiting to run
Build All Platforms / build-windows-qt (push) Waiting to run
Build All Platforms / build-windows-daemon (push) Waiting to run
Build All Platforms / build-linux-qt (push) Waiting to run
Build All Platforms / build-linux-daemon (push) Waiting to run
Build All Platforms / build-macos (push) Waiting to run
Build All Platforms / release (push) Blocked by required conditions
- FormatMoney used %08 (8 decimal digits) but Triangles COIN=1000000
  (6 digits); changed to %06
- Removed util_tests for 7th/8th decimal places (don't exist in Triangles)
- Excluded tx_valid/tx_invalid tests that deserialize Bitcoin-format
  transactions lacking Triangles' nTime field
- Replaced basic_transaction_tests with programmatic tx construction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:22:06 -07:00
sami7777 18db764cf5 Regenerate base58 and key test data for Triangles version bytes
- base58_keys_valid.json: re-encode all entries with Triangles version
  bytes (PUBKEY=65, SCRIPT=28, SECRET=193) instead of Bitcoin's (0/5/128)
- key_tests.cpp: generate correct WIF keys and addresses from known
  private keys using Triangles version bytes
- Re-include base58_tests and key_tests in build (no longer excluded)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:08:01 -07:00
sami7777 ca156a3c59 Port unit tests to Triangles: fix runtime failures, exclude Bitcoin-specific tests
- wallet_tests: use max nSpendTime so coin time filter never applies
  (CTransaction::SetNull sets nTime=GetAdjustedTime, not 0)
- script_combineSigs: update prevout hash after modifying txFrom via
  scriptPubKey reference, fixing SignSignature assertion failure
- script_P2SH switchover: Triangles always enforces P2SH, remove
  old-rules-pass check
- Exclude base58_tests and key_tests from build (Bitcoin address
  version bytes 0/5/128 vs Triangles 65/28/193)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:00:36 -07:00
sami7777 35bf69ec94 Fix test linker errors: add missing global stubs, update orphan tx API
- test_triangles.cpp: add globals excluded with init.o (fEnforceCanonical,
  nNodeLifespan, fConfChange, CheckpointsMode, nDerivationMethodIndex,
  fUseFastIndex)
- DoS_tests.cpp: update AddOrphanTx and mapOrphanTransactions to match
  current CTransaction-based API (was old CDataStream-based)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:49:07 -07:00
sami7777 bd4a6b7cc3 Fix wallet_tests: add missing nSpendTime param to SelectCoinsMinConf calls
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:40:51 -07:00
sami7777 870fc0896d Fix all remaining unit test compilation errors
- uint256_tests: uint64 -> uint64_t
- multisig_tests, script_P2SH_tests, script_tests: fix extern
  VerifyScript declarations and remove fStrictEncodings arg from
  all call sites to match 5-param function signature

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:31:53 -07:00
sami7777 cce120bd81 Fix remaining unit test compilation errors
- uint160_tests: uint64 -> uint64_t (modern C++ type)
- transaction_tests: remove extra fStrictEncodings arg from VerifyScript calls

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:24:51 -07:00
sami7777 b12fda0e3f Fix VerifySignature call in P2SH tests, add header sync diagnostics
Remove extra fStrictEncodings arg from VerifySignature call in
script_P2SH_tests.cpp to match 4-param function signature.
Add IBD-DIAG logging to AddHeaderSyncNode for all rejection reasons.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:16:27 -07:00
sami7777 fc79a744ab Add startup performance logging and wallet sync progress UI
Instrument AppInit2 with StartupPerfLog timing for each startup phase
(block index, wallet load, rescan, tor, peers, etc). Show queued
transaction count in the progress bar during wallet history sync.
Emit transactionSyncProgressChanged for real-time pending counts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 19:06:05 -07:00
sami7777 7597ad10c3 Bump version to v5.3.8
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 18:54:57 -07:00
sami7777 20151a2248 Batch transaction notifications, add RPC console filtering, macOS autostart
Prevent UI freezes during sync by batching wallet transaction notifications
with a 250ms debounce timer and full-refresh fallback for large batches.
Disable dynamic sorting and view updates on overview/transaction pages while
syncing. Add request/reply/error filter checkboxes to the RPC console with
in-memory message store. Implement macOS LaunchAgents-based autostart.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 17:51:13 -07:00
30 changed files with 987 additions and 543 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
// These need to be macros, as version.cpp's and triangles-qt.rc's voodoo requires it
#define CLIENT_VERSION_MAJOR 5
#define CLIENT_VERSION_MINOR 3
#define CLIENT_VERSION_REVISION 7
#define CLIENT_VERSION_REVISION 8
#define CLIENT_VERSION_BUILD 0
// Converts the parameter X to a string after macro replacement on X has been performed.
+51
View File
@@ -51,6 +51,21 @@ enum Checkpoints::CPMode CheckpointsMode;
static CCriticalSection cs_DeferredStartup;
static bool fDeferredStartupRunning = false;
static void StartupPerfLog(const char* phase, int64_t elapsedMs)
{
printf("STARTUP-PERF: %s %" PRId64 "ms\n", phase, elapsedMs);
}
static void StartupPerfLog(const char* phase, int64_t elapsedMs, const std::string& detail)
{
if (detail.empty())
{
StartupPerfLog(phase, elapsedMs);
return;
}
printf("STARTUP-PERF: %s %" PRId64 "ms %s\n", phase, elapsedMs, detail.c_str());
}
//////////////////////////////////////////////////////////////////////////////
//
// Shutdown
@@ -96,6 +111,7 @@ void ThreadDeferredStartup(void* parg)
int64_t nStart = GetTimeMillis();
SecureMsgStart(fNoSmsg, GetBoolArg("-smsgscanchain"));
printf(" securemsg %15" PRId64 "ms\n", GetTimeMillis() - nStart);
StartupPerfLog("deferred.securemsg", GetTimeMillis() - nStart);
}
if (!fShutdown && pwalletMain)
@@ -103,9 +119,11 @@ void ThreadDeferredStartup(void* parg)
int64_t nStart = GetTimeMillis();
pwalletMain->ReacceptWalletTransactions();
printf(" reaccept %15" PRId64 "ms\n", GetTimeMillis() - nStart);
StartupPerfLog("deferred.reaccept_wallet_transactions", GetTimeMillis() - nStart);
}
printf("Deferred startup tasks finished %" PRId64 "ms\n", GetTimeMillis() - nTotalStart);
StartupPerfLog("deferred.total", GetTimeMillis() - nTotalStart);
}
catch (std::exception& e)
{
@@ -449,6 +467,7 @@ bool InitSanityCheck(void)
*/
bool AppInit2()
{
const int64_t nAppInitStart = GetTimeMillis();
// ********************************************************* Step 1: setup
#ifdef _MSC_VER
// Turn off Microsoft heap dump noise
@@ -672,6 +691,7 @@ bool AppInit2()
// ********************************************************* Step 5: verify database integrity
uiInterface.InitMessage(_("Verifying database integrity..."));
nStart = GetTimeMillis();
if (!bitdb.Open(GetDataDir()))
{
@@ -702,8 +722,10 @@ bool AppInit2()
if (r == CDBEnv::RECOVER_FAIL)
return InitError(_("wallet.dat corrupt, salvage failed"));
}
StartupPerfLog("verify_db", GetTimeMillis() - nStart, strprintf("wallet=%s", strWalletFileName.c_str()));
// ********************************************************* Step 6: network initialization
nStart = GetTimeMillis();
//int nSocksVersion = GetArg("-socks", 5);
//
@@ -797,11 +819,13 @@ bool AppInit2()
for (string strDest : mapMultiArgs["-seednode"])
AddOneShot(strDest);
StartupPerfLog("network_init", GetTimeMillis() - nStart, strprintf("listen=%d seednodes=%" PRIszu, !fNoListen, mapMultiArgs["-seednode"].size()));
// ********************************************************* Step 6b: bootstrap download (daemon)
#ifndef QT_GUI
if (GetBoolArg("-bootstrap", false))
{
int64_t nBootstrapStart = GetTimeMillis();
fs::path dataPath = GetDataDir();
std::string host = Bootstrap::DEFAULT_HOST;
std::string strError;
@@ -832,6 +856,8 @@ bool AppInit2()
} else {
printf("\nBootstrap: done.\n");
}
StartupPerfLog("bootstrap_download", GetTimeMillis() - nBootstrapStart,
strprintf("host=%s success=%d", host.c_str(), success));
}
#endif
@@ -867,7 +893,9 @@ bool AppInit2()
{
uiInterface.InitMessage(_("Importing bootstrap blocks..."));
printf("Block index empty but blk0001.dat exists - running fast import...\n");
int64_t nFastImportStart = GetTimeMillis();
FastImportBlockFile();
StartupPerfLog("bootstrap_fast_import", GetTimeMillis() - nFastImportStart, strprintf("bestheight=%d", nBestHeight));
}
// as LoadBlockIndex can take several minutes, it's possible the user
@@ -879,6 +907,7 @@ bool AppInit2()
return false;
}
printf(" block index %15" PRId64 "ms\n", GetTimeMillis() - nStart);
StartupPerfLog("block_index", GetTimeMillis() - nStart, strprintf("bestheight=%d indexsize=%" PRIszu, nBestHeight, mapBlockIndex.size()));
// Diagnostic: check for blocks in mapBlockIndex above pindexBest
{
@@ -989,6 +1018,7 @@ bool AppInit2()
printf("%s", strErrors.str().c_str());
printf(" wallet %15" PRId64 "ms\n", GetTimeMillis() - nStart);
StartupPerfLog("wallet_load", GetTimeMillis() - nStart, strprintf("firstrun=%d", fFirstRun));
RegisterWallet(pwalletMain);
@@ -997,10 +1027,12 @@ bool AppInit2()
pindexRescan = pindexGenesisBlock;
else
{
int64_t nWalletLocatorStart = GetTimeMillis();
CWalletDB walletdb(strWalletFileName);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
pindexRescan = locator.GetBlockIndex();
StartupPerfLog("wallet_bestblock_locator", GetTimeMillis() - nWalletLocatorStart);
}
if (pindexBest != pindexRescan && pindexBest && pindexRescan && pindexBest->nHeight > pindexRescan->nHeight)
{
@@ -1033,6 +1065,12 @@ bool AppInit2()
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
printf(" rescan %15" PRId64 "ms\n", GetTimeMillis() - nStart);
StartupPerfLog("wallet_rescan", GetTimeMillis() - nStart,
strprintf("from=%d to=%d indexed=%d", pindexRescan->nHeight, pindexBest->nHeight, fScannedWithIndex));
}
else
{
StartupPerfLog("wallet_rescan", 0, "skipped");
}
// ********************************************************* Step 8.5: start Tor and initialize V3 identity
@@ -1040,7 +1078,9 @@ bool AppInit2()
uiInterface.InitMessage(_("Starting Tor..."));
printf("Starting Tor process...\n");
int64_t nTorStart = GetTimeMillis();
bool torStarted = StartEmbeddedTor();
StartupPerfLog("tor_start", GetTimeMillis() - nTorStart, strprintf("started=%d", torStarted));
std::string torDataPath = CTorEmbedded::GetInstance()->GetDataDir();
if (torDataPath.empty())
torDataPath = (GetDataDir() / "tor_data").string();
@@ -1057,6 +1097,7 @@ bool AppInit2()
uiInterface.InitMessage(_("Initializing Tor V3 identity..."));
printf("Initializing Tor V3 onion identity...\n");
int64_t nTorIdentityStart = GetTimeMillis();
LoadTorV3Config();
TorV3Config& torConfig = GetTorV3Config();
torConfig.enableTor = true;
@@ -1085,6 +1126,7 @@ bool AppInit2()
} else {
printf("WARNING: Failed to initialize Tor V3 identity\n");
}
StartupPerfLog("tor_v3_identity", GetTimeMillis() - nTorIdentityStart);
// Also check if Tor gave us a hidden service hostname
if (torStarted) {
@@ -1103,6 +1145,7 @@ bool AppInit2()
}
}
}
StartupPerfLog("tor_setup_total", GetTimeMillis() - nTorStart);
}
// ********************************************************* Step 9: import blocks
@@ -1113,9 +1156,11 @@ bool AppInit2()
for (string strFile : mapMultiArgs["-loadblock"])
{
int64_t nLoadBlockStart = GetTimeMillis();
FILE *file = fopen(strFile.c_str(), "rb");
if (file)
LoadExternalBlockFile(file);
StartupPerfLog("loadblock_import", GetTimeMillis() - nLoadBlockStart, strprintf("file=%s", strFile.c_str()));
}
exit(0);
}
@@ -1124,12 +1169,14 @@ bool AppInit2()
if (fs::exists(pathBootstrap)) {
uiInterface.InitMessage(_("Importing bootstrap blockchain data file."));
int64_t nBootstrapImportStart = GetTimeMillis();
FILE *file = fopen(pathBootstrap.string().c_str(), "rb");
if (file) {
fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old";
LoadExternalBlockFile(file);
RenameOver(pathBootstrap, pathBootstrapOld);
}
StartupPerfLog("bootstrap_dat_import", GetTimeMillis() - nBootstrapImportStart, strprintf("file=%s", pathBootstrap.string().c_str()));
}
// ********************************************************* Step 10: load peers
@@ -1146,9 +1193,11 @@ bool AppInit2()
printf("Loaded %i addresses from peers.dat %" PRId64 "ms\n",
addrman.size(), GetTimeMillis() - nStart);
StartupPerfLog("peers_load", GetTimeMillis() - nStart, strprintf("count=%d", addrman.size()));
// ********************************************************* Step 11: start node
nStart = GetTimeMillis();
if (!CheckDiskSpace())
return false;
@@ -1177,6 +1226,7 @@ bool AppInit2()
printf("Warning: deferred startup thread could not be started, running inline\n");
ThreadDeferredStartup(NULL);
}
StartupPerfLog("start_services", GetTimeMillis() - nStart);
// ********************************************************* Step 11.5: ZMQ notifications
#ifdef ENABLE_ZMQ
@@ -1215,6 +1265,7 @@ bool AppInit2()
uiInterface.InitMessage(_("Done loading"));
printf("Done loading\n");
StartupPerfLog("appinit_total", GetTimeMillis() - nAppInitStart);
if (!strErrors.str().empty())
return InitError(strErrors.str());
+17
View File
@@ -197,19 +197,36 @@ static bool AddHeaderSyncNode(const CBlock& header, const uint256& hashHeader)
return true;
if (!header.vtx.empty())
{
printf("IBD-DIAG: header rejected (has vtx) hash=%s\n", hashHeader.ToString().substr(0,20).c_str());
return false;
}
if (header.GetBlockTime() > FutureDrift(GetAdjustedTime()))
{
printf("IBD-DIAG: header rejected (future time) hash=%s time=%u\n",
hashHeader.ToString().substr(0,20).c_str(), header.nTime);
return false;
}
int nPrevHeight = -1;
uint256 nPrevChainTrust = 0;
if (!GetKnownHeaderState(header.hashPrevBlock, nPrevHeight, nPrevChainTrust))
{
printf("IBD-DIAG: header rejected (prev unknown) hash=%s prevHash=%s\n",
hashHeader.ToString().substr(0,20).c_str(),
header.hashPrevBlock.ToString().substr(0,20).c_str());
return false;
}
const int nHeight = nPrevHeight + 1;
if (nHeight <= CUTOFF_POW_BLOCK && !CheckProofOfWork(hashHeader, header.nBits))
{
printf("IBD-DIAG: header PoW FAILED at height %d hash=%s nBits=%08x prevHash=%s\n",
nHeight, hashHeader.ToString().substr(0,20).c_str(), header.nBits,
header.hashPrevBlock.ToString().substr(0,20).c_str());
return false;
}
CHeaderSyncNode node;
node.header = header;
+57
View File
@@ -1085,6 +1085,63 @@ QPushButton:!enabled {
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="filterLayout">
<property name="spacing">
<number>12</number>
</property>
<item>
<widget class="QLabel" name="showLabel">
<property name="text">
<string>Show:</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showRequestsCheckBox">
<property name="text">
<string>Requests</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showRepliesCheckBox">
<property name="text">
<string>Replies</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="showErrorsCheckBox">
<property name="text">
<string>Errors</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacerFilters">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
+90
View File
@@ -405,6 +405,96 @@ bool SetStartOnSystemStartup(bool fAutoStart)
}
return true;
}
#elif defined(Q_OS_MAC) || defined(MAC_OSX) || defined(__APPLE__)
boost::filesystem::path static GetLaunchAgentsDir()
{
const QString homeDir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
if (homeDir.isEmpty())
return boost::filesystem::path();
return boost::filesystem::path(homeDir.toStdString()) / "Library" / "LaunchAgents";
}
boost::filesystem::path static GetAutostartFilePath()
{
return GetLaunchAgentsDir() / "org.triangles.triangles-qt.plist";
}
static std::string PlistEscape(const std::string& value)
{
std::string escaped;
escaped.reserve(value.size());
for (std::string::const_iterator it = value.begin(); it != value.end(); ++it)
{
switch (*it)
{
case '&': escaped += "&amp;"; break;
case '<': escaped += "&lt;"; break;
case '>': escaped += "&gt;"; break;
case '"': escaped += "&quot;"; break;
case '\'': escaped += "&apos;"; break;
default: escaped += *it; break;
}
}
return escaped;
}
bool GetStartOnSystemStartup()
{
boost::filesystem::ifstream optionFile(GetAutostartFilePath());
if (!optionFile.good())
return false;
std::string contents;
std::string line;
while (getline(optionFile, line))
contents += line;
optionFile.close();
return contents.find("<key>RunAtLoad</key>") != std::string::npos &&
contents.find("<true/>") != std::string::npos &&
contents.find("<string>-min</string>") != std::string::npos;
}
bool SetStartOnSystemStartup(bool fAutoStart)
{
if (!fAutoStart)
return !boost::filesystem::exists(GetAutostartFilePath()) || boost::filesystem::remove(GetAutostartFilePath());
const QString exePath = QApplication::applicationFilePath();
if (exePath.isEmpty())
return false;
const QString workingDir = QFileInfo(exePath).absolutePath();
boost::filesystem::create_directories(GetLaunchAgentsDir());
boost::filesystem::ofstream optionFile(GetAutostartFilePath(), std::ios_base::out|std::ios_base::trunc);
if (!optionFile.good())
return false;
optionFile
<< "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
<< "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" "
<< "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
<< "<plist version=\"1.0\">\n"
<< "<dict>\n"
<< " <key>Label</key>\n"
<< " <string>org.triangles.triangles-qt</string>\n"
<< " <key>ProgramArguments</key>\n"
<< " <array>\n"
<< " <string>" << PlistEscape(exePath.toStdString()) << "</string>\n"
<< " <string>-min</string>\n"
<< " </array>\n"
<< " <key>RunAtLoad</key>\n"
<< " <true/>\n"
<< " <key>WorkingDirectory</key>\n"
<< " <string>" << PlistEscape(workingDir.toStdString()) << "</string>\n"
<< "</dict>\n"
<< "</plist>\n";
optionFile.close();
return optionFile.good();
}
#else
// TODO: OSX startup stuff; see:
+20
View File
@@ -92,6 +92,7 @@ OverviewPage::OverviewPage(QWidget *parent) :
currentStake(0),
currentUnconfirmedBalance(-1),
currentImmatureBalance(-1),
walletTransactionSyncing(false),
txdelegate(new TxViewDelegate()),
filter(0)
{
@@ -166,8 +167,10 @@ void OverviewPage::setModel(WalletModel *model)
// Keep up to date with wallet
setBalance(model->getBalance(), model->getStake(), model->getUnconfirmedBalance(), model->getImmatureBalance());
connect(model, SIGNAL(balanceChanged(qint64, qint64, qint64, qint64)), this, SLOT(setBalance(qint64, qint64, qint64, qint64)));
connect(model, SIGNAL(transactionSyncStateChanged(bool)), this, SLOT(setTransactionSyncState(bool)));
connect(model->getOptionsModel(), SIGNAL(displayUnitChanged(int)), this, SLOT(updateDisplayUnit()));
setTransactionSyncState(model->isTransactionSyncing());
}
// update the display unit, to not use the default ("TRI")
@@ -188,6 +191,23 @@ void OverviewPage::updateDisplayUnit()
}
}
void OverviewPage::setTransactionSyncState(bool syncing)
{
walletTransactionSyncing = syncing;
if (!filter)
return;
filter->setDynamicSortFilter(!syncing);
ui->listTransactions->setUpdatesEnabled(!syncing);
if (!syncing)
{
filter->invalidate();
filter->sort(TransactionTableModel::Status, Qt::DescendingOrder);
ui->listTransactions->viewport()->update();
}
}
void OverviewPage::showOutOfSyncWarning(bool fShow)
{
ui->labelWalletStatus->setVisible(fShow);
+2
View File
@@ -30,6 +30,7 @@ public:
public slots:
void setBalance(qint64 balance, qint64 stake, qint64 unconfirmedBalance, qint64 immatureBalance);
void setTransactionSyncState(bool syncing);
signals:
void transactionClicked(const QModelIndex &index);
@@ -42,6 +43,7 @@ private:
qint64 currentStake;
qint64 currentUnconfirmedBalance;
qint64 currentImmatureBalance;
bool walletTransactionSyncing;
TxViewDelegate *txdelegate;
TransactionFilterProxy *filter;
+93 -17
View File
@@ -17,9 +17,6 @@
#include <openssl/crypto.h>
// TODO: make it possible to filter out categories (esp debug messages when implemented)
// TODO: receive errors and debug messages through ClientModel
const int CONSOLE_SCROLLBACK = 50;
const int CONSOLE_HISTORY = 50;
@@ -190,6 +187,7 @@ void RPCExecutor::request(const QString &command)
RPCConsole::RPCConsole(QWidget *parent) :
QDialog(parent),
ui(new Ui::RPCConsole),
clientModel(0),
historyPtr(0)
{
ui->setupUi(this);
@@ -259,12 +257,16 @@ bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
void RPCConsole::setClientModel(ClientModel *model)
{
if (clientModel)
disconnect(clientModel, 0, this, 0);
this->clientModel = model;
if(model)
{
// Subscribe to information, replies, messages, errors
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
connect(model, SIGNAL(numBlocksChanged(int,int)), this, SLOT(setNumBlocks(int,int)));
connect(model, SIGNAL(error(QString,QString,bool)), this, SLOT(showClientError(QString,QString,bool)));
// Provide initial values
ui->clientVersion->setText(model->formatFullVersion());
@@ -285,14 +287,16 @@ static QString categoryClass(int category)
{
case RPCConsole::CMD_REQUEST: return "cmd-request"; break;
case RPCConsole::CMD_REPLY: return "cmd-reply"; break;
case RPCConsole::CMD_ERROR: return "cmd-error"; break;
case RPCConsole::CMD_ERROR:
case RPCConsole::MC_ERROR: return "cmd-error"; break;
default: return "misc";
}
}
void RPCConsole::clear()
{
ui->messagesWidget->clear();
consoleEntries.clear();
refreshMessages();
ui->lineEdit->clear();
ui->lineEdit->setFocus();
@@ -323,18 +327,21 @@ void RPCConsole::clear()
void RPCConsole::message(int category, const QString &message, bool html)
{
QTime time = QTime::currentTime();
QString timeString = time.toString();
QString out;
out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) + "\"></td>";
out += "<td class=\"message " + categoryClass(category) + "\" valign=\"middle\">";
if(html)
out += message;
else
out += GUIUtil::HtmlEscape(message, true);
out += "</td></tr></table>";
ui->messagesWidget->append(out);
ConsoleEntry entry;
entry.category = category;
entry.text = message;
entry.time = QTime::currentTime().toString();
entry.html = html;
consoleEntries.append(entry);
while (consoleEntries.size() > CONSOLE_SCROLLBACK)
consoleEntries.removeFirst();
if (categoryVisible(category))
{
ui->messagesWidget->append(formatEntry(entry));
scrollToEnd();
}
}
void RPCConsole::setNumConnections(int count)
@@ -439,3 +446,72 @@ void RPCConsole::on_showCLOptionsButton_clicked()
GUIUtil::HelpMessageBox help;
help.exec();
}
bool RPCConsole::categoryVisible(int category) const
{
switch (category)
{
case CMD_REQUEST:
return ui->showRequestsCheckBox->isChecked();
case CMD_ERROR:
case MC_ERROR:
return ui->showErrorsCheckBox->isChecked();
case CMD_REPLY:
case MC_DEBUG:
default:
return ui->showRepliesCheckBox->isChecked();
}
}
QString RPCConsole::formatEntry(const ConsoleEntry &entry) const
{
QString out;
out += "<table><tr><td class=\"time\" width=\"65\">" + entry.time + "</td>";
out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(entry.category) + "\"></td>";
out += "<td class=\"message " + categoryClass(entry.category) + "\" valign=\"middle\">";
if (entry.html)
out += entry.text;
else
out += GUIUtil::HtmlEscape(entry.text, true);
out += "</td></tr></table>";
return out;
}
void RPCConsole::refreshMessages()
{
ui->messagesWidget->clear();
for (QList<ConsoleEntry>::const_iterator it = consoleEntries.begin(); it != consoleEntries.end(); ++it)
{
if (categoryVisible(it->category))
ui->messagesWidget->append(formatEntry(*it));
}
scrollToEnd();
}
void RPCConsole::on_showRequestsCheckBox_toggled(bool checked)
{
Q_UNUSED(checked);
refreshMessages();
}
void RPCConsole::on_showRepliesCheckBox_toggled(bool checked)
{
Q_UNUSED(checked);
refreshMessages();
}
void RPCConsole::on_showErrorsCheckBox_toggled(bool checked)
{
Q_UNUSED(checked);
refreshMessages();
}
void RPCConsole::showClientError(const QString &title, const QString &message, bool modal)
{
Q_UNUSED(modal);
if (title.isEmpty())
this->message(MC_ERROR, message);
else
this->message(MC_ERROR, title + ": " + message);
}
+16
View File
@@ -37,6 +37,10 @@ private slots:
void on_openDebugLogfileButton_clicked();
/** display messagebox with program parameters (same as triangles-qt --help) */
void on_showCLOptionsButton_clicked();
void on_showRequestsCheckBox_toggled(bool checked);
void on_showRepliesCheckBox_toggled(bool checked);
void on_showErrorsCheckBox_toggled(bool checked);
void showClientError(const QString &title, const QString &message, bool modal);
public slots:
void clear();
@@ -55,11 +59,23 @@ signals:
void cmdRequest(const QString &command);
private:
struct ConsoleEntry
{
int category;
QString text;
QString time;
bool html;
};
Ui::RPCConsole *ui;
ClientModel *clientModel;
QStringList history;
QList<ConsoleEntry> consoleEntries;
int historyPtr;
bool categoryVisible(int category) const;
QString formatEntry(const ConsoleEntry &entry) const;
void refreshMessages();
void startExecutor();
};
+32 -2
View File
@@ -34,7 +34,10 @@ TransactionView::TransactionView(QWidget *parent) :
QWidget(parent), model(0), transactionProxyModel(0),
ui(new Ui::TransactionsPage),
transactionView(0),
transactionsSortOrderDown(true)
transactionsSortOrderDown(true),
walletTransactionSyncing(false),
transactionSortColumn(TransactionTableModel::Status),
transactionSortOrder(Qt::DescendingOrder)
{
ui->setupUi(this);
setWindowFlags(Qt::CustomizeWindowHint | Qt::FramelessWindowHint | Qt::Window);
@@ -150,7 +153,7 @@ void TransactionView::setModel(WalletModel *model)
transactionView->setSelectionBehavior(QAbstractItemView::SelectRows);
transactionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
transactionView->setSortingEnabled(true);
transactionView->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
transactionView->sortByColumn(transactionSortColumn, transactionSortOrder);
transactionView->verticalHeader()->hide();
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Status, 23);
@@ -162,6 +165,9 @@ void TransactionView::setModel(WalletModel *model)
transactionView->horizontalHeader()->setSectionResizeMode(TransactionTableModel::ToAddress, QHeaderView::Stretch);
#endif
transactionView->horizontalHeader()->resizeSection(TransactionTableModel::Amount, 100);
connect(model, SIGNAL(transactionSyncStateChanged(bool)), this, SLOT(setTransactionSyncState(bool)));
setTransactionSyncState(model->isTransactionSyncing());
}
}
@@ -272,6 +278,30 @@ void TransactionView::exportClicked()
}
}
void TransactionView::setTransactionSyncState(bool syncing)
{
walletTransactionSyncing = syncing;
if (!transactionProxyModel || !transactionView)
return;
if (syncing)
{
transactionSortColumn = transactionView->horizontalHeader()->sortIndicatorSection();
transactionSortOrder = transactionView->horizontalHeader()->sortIndicatorOrder();
transactionProxyModel->setDynamicSortFilter(false);
transactionView->setSortingEnabled(false);
transactionView->setUpdatesEnabled(false);
return;
}
transactionProxyModel->setDynamicSortFilter(true);
transactionView->setUpdatesEnabled(true);
transactionView->setSortingEnabled(true);
transactionProxyModel->invalidate();
transactionView->sortByColumn(transactionSortColumn, transactionSortOrder);
transactionView->viewport()->update();
}
void TransactionView::contextualMenu(const QPoint &point)
{
QModelIndex index = transactionView->indexAt(point);
+5 -1
View File
@@ -48,9 +48,12 @@ public:
private:
WalletModel *model;
TransactionFilterProxy *transactionProxyModel;
Ui::TransactionsPage *ui;
Ui::TransactionsPage *ui;
QTableView *transactionView;
bool transactionsSortOrderDown;
bool walletTransactionSyncing;
int transactionSortColumn;
Qt::SortOrder transactionSortOrder;
QComboBox *dateWidget;
QComboBox *typeWidget;
@@ -74,6 +77,7 @@ private slots:
void copyLabel();
void copyAmount();
void copyTxID();
void setTransactionSyncState(bool syncing);
signals:
void doubleClicked(const QModelIndex&);
+67 -13
View File
@@ -106,7 +106,9 @@ TrianglesGUI::TrianglesGUI(bool fIsTestnet, QWidget *parent):
trayIcon(0),
notificator(0),
rpcConsole(0),
prevBlocks(0)
prevBlocks(0),
walletTransactionSyncing(false),
walletTransactionSyncPending(0)
{
ui->setupUi(this);
@@ -592,6 +594,9 @@ void TrianglesGUI::setWalletModel(WalletModel *walletModel)
setEncryptionStatus(walletModel->getEncryptionStatus());
connect(walletModel, SIGNAL(encryptionStatusChanged(int)), this, SLOT(setEncryptionStatus(int)));
connect(walletModel, SIGNAL(transactionSyncStateChanged(bool)), this, SLOT(setWalletTransactionSyncState(bool)));
connect(walletModel, SIGNAL(transactionSyncProgressChanged(bool,int)), this, SLOT(setWalletTransactionSyncProgress(bool,int)));
setWalletTransactionSyncState(walletModel->isTransactionSyncing());
// Balloon pop-up for new transaction
connect(walletModel->getTransactionTableModel(), SIGNAL(rowsInserted(QModelIndex,int,int)),
@@ -766,6 +771,32 @@ void TrianglesGUI::restoreWindowGeometry()
move(pos);
}
void TrianglesGUI::refreshSyncStatusDisplay()
{
if (clientModel)
{
setNumBlocks(clientModel->getNumBlocks(), clientModel->getNumBlocksOfPeers());
return;
}
if (!walletTransactionSyncing)
{
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
ui->label_blocks->setVisible(false);
return;
}
progressBarLabel->setText(walletTransactionSyncPending > 0
? tr("Updating wallet history... %n change(s) queued", "", walletTransactionSyncPending)
: tr("Updating wallet history..."));
progressBarLabel->setVisible(true);
progressBar->setRange(0, 0);
progressBar->setValue(0);
progressBar->setVisible(true);
ui->label_blocks->setVisible(false);
}
void TrianglesGUI::optionsClicked()
{
if(!clientModel || !clientModel->getOptionsModel())
@@ -803,19 +834,10 @@ void TrianglesGUI::setNumBlocks(int count, int nTotalBlocks)
return;
int nConnections = clientModel->getNumConnections();
// Hide progress bar when disconnected, but don't return early -
// we still need to update sync state and the out-of-sync warning
if (nConnections == 0)
{
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
ui->label_blocks->setVisible(false);
}
const bool blockSyncActive = nConnections > 0 && count < nTotalBlocks;
QString tooltip;
if(nConnections > 0 && count < nTotalBlocks)
if(blockSyncActive)
{
// Calculate blocks/sec - only update rate when new blocks arrive
static int lastCount = 0;
@@ -867,10 +889,25 @@ void TrianglesGUI::setNumBlocks(int count, int nTotalBlocks)
tooltip = tr("Downloaded %1 of %2 blocks of transaction history (%3% done).").arg(count).arg(nTotalBlocks).arg(nPercentageDone, 0, 'f', 2);
}
else if (walletTransactionSyncing)
{
progressBarLabel->setText(walletTransactionSyncPending > 0
? tr("Updating wallet history... %n change(s) queued", "", walletTransactionSyncPending)
: tr("Updating wallet history..."));
progressBarLabel->setVisible(true);
progressBar->setRange(0, 0);
progressBar->setValue(0);
progressBar->setVisible(true);
ui->label_blocks->setVisible(false);
tooltip = tr("Wallet history is catching up to recent transactions and stakes.");
tooltip += QString("<br>") + (walletTransactionSyncPending > 0
? tr("%n wallet update(s) are queued for the UI.", "", walletTransactionSyncPending)
: tr("Finalizing the latest wallet updates."));
}
else
{
progressBarLabel->setVisible(false);
progressBar->setVisible(false);
ui->label_blocks->setVisible(false);
tooltip = tr("Processed %1 blocks of transaction history.").arg(count);
@@ -1039,6 +1076,8 @@ void TrianglesGUI::incomingTransaction(const QModelIndex & parent, int start, in
{
if(!walletModel || !clientModel)
return;
if(walletTransactionSyncing)
return;
TransactionTableModel *ttm = walletModel->getTransactionTableModel();
qint64 amount = ttm->index(start, TransactionTableModel::Amount, parent)
.data(Qt::EditRole).toULongLong();
@@ -1070,6 +1109,21 @@ void TrianglesGUI::incomingTransaction(const QModelIndex & parent, int start, in
}
}
void TrianglesGUI::setWalletTransactionSyncState(bool syncing)
{
walletTransactionSyncing = syncing;
if (!syncing)
walletTransactionSyncPending = 0;
refreshSyncStatusDisplay();
}
void TrianglesGUI::setWalletTransactionSyncProgress(bool syncing, int pendingNotifications)
{
walletTransactionSyncing = syncing;
walletTransactionSyncPending = pendingNotifications;
refreshSyncStatusDisplay();
}
void TrianglesGUI::incomingMessage(const QModelIndex & parent, int start, int end)
{
if(!messageModel)
+5
View File
@@ -143,6 +143,8 @@ private:
QMovie *syncIconMovie;
/** Keep track of previous number of blocks, to detect progress */
int prevBlocks;
bool walletTransactionSyncing;
int walletTransactionSyncPending;
/** Create the main UI actions. */
void createActions(bool fIsTestnet);
@@ -158,6 +160,7 @@ private:
void saveWindowGeometry();
/** Restore window size and position */
void restoreWindowGeometry();
void refreshSyncStatusDisplay();
public slots:
/** Set number of connections shown in the UI */
@@ -169,6 +172,8 @@ public slots:
@see WalletModel::EncryptionStatus
*/
void setEncryptionStatus(int status);
void setWalletTransactionSyncState(bool syncing);
void setWalletTransactionSyncProgress(bool syncing, int pendingNotifications);
/** Notify the user of an error in the network or transaction handling code. */
void error(const QString &title, const QString &message, bool modal);
+147 -5
View File
@@ -8,9 +8,15 @@
#include "wallet.h"
#include "walletdb.h" // for BackupWallet
#include "base58.h"
#include "main.h"
#include <QSet>
#include <QTimer>
#include <QMutexLocker>
static const int MODEL_UPDATE_BATCH_THRESHOLD = 128;
static const int MODEL_UPDATE_BATCH_DELAY_MS = 250;
static const int MODEL_FULL_REFRESH_MIN_INTERVAL_MS = 1500;
WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *parent) :
QObject(parent), wallet(wallet), optionsModel(optionsModel), addressTableModel(0),
@@ -18,7 +24,12 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
cachedBalance(0), cachedStake(0), cachedUnconfirmedBalance(0), cachedImmatureBalance(0),
cachedNumTransactions(0),
cachedEncryptionStatus(Unencrypted),
cachedNumBlocks(0)
cachedNumBlocks(0),
transactionNotificationFlushQueued(false),
fullTransactionRefreshQueued(false),
transactionSyncing(false),
transactionNotificationTimer(0),
lastFullTransactionRefreshTime(0)
{
addressTableModel = new AddressTableModel(wallet, this);
transactionTableModel = new TransactionTableModel(wallet, this);
@@ -28,6 +39,10 @@ WalletModel::WalletModel(CWallet *wallet, OptionsModel *optionsModel, QObject *p
connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollBalanceChanged()));
pollTimer->start(MODEL_UPDATE_DELAY);
transactionNotificationTimer = new QTimer(this);
transactionNotificationTimer->setSingleShot(true);
connect(transactionNotificationTimer, SIGNAL(timeout()), this, SLOT(flushTransactionNotifications()));
subscribeToCoreSignals();
}
@@ -66,6 +81,11 @@ int WalletModel::getNumTransactions() const
return numTransactions;
}
bool WalletModel::isTransactionSyncing() const
{
return transactionSyncing;
}
void WalletModel::updateStatus()
{
EncryptionStatus newEncryptionStatus = getEncryptionStatus();
@@ -108,8 +128,132 @@ bool WalletModel::checkBalanceChanged()
void WalletModel::updateTransaction(const QString &hash, int status)
{
queueTransactionUpdate(hash, status);
}
void WalletModel::queueTransactionUpdate(const QString &hash, int status)
{
bool shouldScheduleFlush = false;
{
QMutexLocker locker(&transactionNotificationMutex);
int mergedStatus = status;
QMap<QString, int>::iterator it = queuedTransactionNotifications.find(hash);
if (it != queuedTransactionNotifications.end())
{
// Preserve insert/delete semantics when multiple updates arrive
// for the same transaction before the UI thread drains the queue.
if (it.value() == CT_DELETED || status == CT_DELETED)
mergedStatus = CT_DELETED;
else if (it.value() == CT_NEW || status == CT_NEW)
mergedStatus = CT_NEW;
else
mergedStatus = CT_UPDATED;
it.value() = mergedStatus;
}
else
{
queuedTransactionNotifications.insert(hash, mergedStatus);
}
if (IsInitialBlockDownload() || queuedTransactionNotifications.size() >= MODEL_UPDATE_BATCH_THRESHOLD)
fullTransactionRefreshQueued = true;
if (!transactionNotificationFlushQueued)
{
transactionNotificationFlushQueued = true;
shouldScheduleFlush = true;
}
}
if (shouldScheduleFlush)
QMetaObject::invokeMethod(this, "startTransactionNotificationTimer", Qt::QueuedConnection);
}
void WalletModel::startTransactionNotificationTimer()
{
if (transactionNotificationTimer)
transactionNotificationTimer->start(MODEL_UPDATE_BATCH_DELAY_MS);
}
void WalletModel::flushTransactionNotifications()
{
QMap<QString, int> pendingNotifications;
bool refreshAll = false;
bool shouldRescheduleRefresh = false;
{
QMutexLocker locker(&transactionNotificationMutex);
pendingNotifications.swap(queuedTransactionNotifications);
refreshAll = fullTransactionRefreshQueued;
fullTransactionRefreshQueued = false;
transactionNotificationFlushQueued = false;
}
const bool shouldSync = refreshAll ||
IsInitialBlockDownload() ||
pendingNotifications.size() >= MODEL_UPDATE_BATCH_THRESHOLD;
if (transactionSyncing != shouldSync)
{
transactionSyncing = shouldSync;
emit transactionSyncStateChanged(transactionSyncing);
}
if(transactionTableModel)
transactionTableModel->updateTransaction(hash, status);
{
if (refreshAll)
{
const qint64 now = GetTimeMillis();
if (transactionSyncing &&
lastFullTransactionRefreshTime != 0 &&
now - lastFullTransactionRefreshTime < MODEL_FULL_REFRESH_MIN_INTERVAL_MS)
{
QMutexLocker locker(&transactionNotificationMutex);
fullTransactionRefreshQueued = true;
if (!transactionNotificationFlushQueued)
{
transactionNotificationFlushQueued = true;
shouldRescheduleRefresh = true;
}
}
else
{
transactionTableModel->refreshWallet();
lastFullTransactionRefreshTime = now;
}
}
else
{
for (QMap<QString, int>::const_iterator it = pendingNotifications.begin(); it != pendingNotifications.end(); ++it)
transactionTableModel->updateTransaction(it.key(), it.value());
}
}
if (shouldRescheduleRefresh && transactionNotificationTimer)
transactionNotificationTimer->start(MODEL_FULL_REFRESH_MIN_INTERVAL_MS);
bool stillPending = false;
int queuedNotificationCount = 0;
{
QMutexLocker locker(&transactionNotificationMutex);
stillPending = transactionNotificationFlushQueued || !queuedTransactionNotifications.isEmpty();
queuedNotificationCount = queuedTransactionNotifications.size();
}
if (!transactionSyncing && pendingNotifications.size() >= MODEL_UPDATE_BATCH_THRESHOLD)
{
transactionSyncing = true;
emit transactionSyncStateChanged(true);
}
if (transactionSyncing && !IsInitialBlockDownload() && !stillPending)
{
transactionSyncing = false;
emit transactionSyncStateChanged(false);
}
const int pendingNotificationCount = transactionSyncing
? pendingNotifications.size() + queuedNotificationCount
: queuedNotificationCount;
emit transactionSyncProgressChanged(transactionSyncing, pendingNotificationCount);
// Don't call checkBalanceChanged() here - it does LOCK(cs_wallet) + iterates
// all wallet transactions, blocking the UI thread. The pollBalanceChanged()
@@ -392,9 +536,7 @@ static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
static void NotifyTransactionChanged(WalletModel *walletmodel, CWallet *wallet, const uint256 &hash, ChangeType status)
{
OutputDebugStringF("NotifyTransactionChanged %s status=%i\n", hash.GetHex().c_str(), status);
QMetaObject::invokeMethod(walletmodel, "updateTransaction", Qt::QueuedConnection,
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
Q_ARG(int, status));
walletmodel->queueTransactionUpdate(QString::fromStdString(hash.GetHex()), status);
}
void WalletModel::subscribeToCoreSignals()
+20
View File
@@ -4,6 +4,8 @@
#include <QObject>
#include <vector>
#include <map>
#include <QMap>
#include <QMutex>
#include "allocators.h" /* for SecureString */
@@ -72,6 +74,7 @@ public:
qint64 getImmatureBalance() const;
int getNumTransactions() const;
EncryptionStatus getEncryptionStatus() const;
bool isTransactionSyncing() const;
// Check address for validity
bool validateAddress(const QString &address);
@@ -160,10 +163,16 @@ public slots:
void updateStatus();
/* New transaction, or transaction changed status */
void updateTransaction(const QString &hash, int status);
/* Queue a transaction update from a core thread without touching the UI directly */
void queueTransactionUpdate(const QString &hash, int status);
/* New, updated or removed address book entry */
void updateAddressBook(const QString &address, const QString &label, bool isMine, int status);
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
void pollBalanceChanged();
/* Start or restart the deferred transaction notification flush timer */
void startTransactionNotificationTimer();
/* Flush queued transaction notifications from core threads */
void flushTransactionNotifications();
signals:
// Signal that balance in wallet changed
@@ -182,6 +191,17 @@ signals:
// Asynchronous error notification
void error(const QString &title, const QString &message, bool modal);
void transactionSyncStateChanged(bool syncing);
void transactionSyncProgressChanged(bool syncing, int pendingNotifications);
private:
QMutex transactionNotificationMutex;
QMap<QString, int> queuedTransactionNotifications;
bool transactionNotificationFlushQueued;
bool fullTransactionRefreshQueued;
bool transactionSyncing;
QTimer *transactionNotificationTimer;
qint64 lastFullTransactionRefreshTime;
};
+9 -20
View File
@@ -14,10 +14,10 @@
#include <stdint.h>
// Tests this internal-to-main.cpp method:
extern bool AddOrphanTx(const CDataStream& vMsg);
extern bool AddOrphanTx(const CTransaction& tx);
extern unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans);
extern std::map<uint256, CDataStream*> mapOrphanTransactions;
extern std::map<uint256, std::map<uint256, CDataStream*> > mapOrphanTransactionsByPrev;
extern std::map<uint256, CTransaction> mapOrphanTransactions;
extern std::map<uint256, std::set<uint256> > mapOrphanTransactionsByPrev;
CService ip(uint32_t i)
{
@@ -131,14 +131,11 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
CTransaction RandomOrphan()
{
std::map<uint256, CDataStream*>::iterator it;
std::map<uint256, CTransaction>::iterator it;
it = mapOrphanTransactions.lower_bound(GetRandHash());
if (it == mapOrphanTransactions.end())
it = mapOrphanTransactions.begin();
const CDataStream* pvMsg = it->second;
CTransaction tx;
CDataStream(*pvMsg) >> tx;
return tx;
return it->second;
}
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
@@ -160,9 +157,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// ... and 50 that depend on other orphans:
@@ -179,9 +174,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
SignSignature(keystore, txPrev, tx, 0);
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// This really-big orphan should be ignored:
@@ -205,9 +198,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
for (unsigned int j = 1; j < tx.vin.size(); j++)
tx.vin[j].scriptSig = tx.vin[0].scriptSig;
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
BOOST_CHECK(!AddOrphanTx(ds));
BOOST_CHECK(!AddOrphanTx(tx));
}
// Test LimitOrphanTxSize() function:
@@ -243,9 +234,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
tx.vout[0].nValue = 1*CENT;
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
CDataStream ds(SER_DISK, CLIENT_VERSION);
ds << tx;
AddOrphanTx(ds);
AddOrphanTx(tx);
}
// Create a transaction that depends on orphans:
+249 -249
View File
@@ -1,451 +1,451 @@
[
[
"1AGNa15ZQXAZUgFiqJ2i7Z2DPU2J6hW62i",
"65a16059864a2fdbc7c99a4723a8395bc6f188eb",
"TKEaa4THZFHWdrKMRZgRdhiMJFmcFaMkWa",
"65a16059864a2fdbc7c99a4723a8395bc6f188eb",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"3CMNFxN1oHBc4R1EpboAL5yzHGgE611Xou",
"74f209f6ea907e2ea48f74fae05782ae8a665257",
"CT8EuTDe8RqksPDEPFTVUyF5ksbvNTs8Yp",
"74f209f6ea907e2ea48f74fae05782ae8a665257",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
"53c0307d6851aa0ce7825ba883c6bd9ad242b486",
"mo9ncXisMeAoXwqcV5EWuyncbmCcQN4rVs",
"53c0307d6851aa0ce7825ba883c6bd9ad242b486",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
"6349a418fc4578d10a372b54b45c280cc8c4382f",
"2N2JD6wb56AfK4tfmM6PwdVmoYk2dCKf4Br",
"6349a418fc4578d10a372b54b45c280cc8c4382f",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5Kd3NBUAdUnhyzenEwVLy9pBKxSwXvE9FMPyR4UKZvpe6E3AgLr",
"eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
"7VyRqFeF28kRkKRdAcqHxznWrNUcnh14PtzyGoBbBXFrAi1wcbq",
"eddbdc1168f1daeadbd3e44c1e3f8f5a284c2029f78ad26af98583a499de5b19",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"Kz6UJmQACJmLtaQj5A3JAge4kVTNQ8gbvXuwbmCj7bsaabudb3RD",
"55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
"VbnTUFpdaJKHEDGf25hLuznivjWmfLJrWFQQyHit2hrqt7rK8ubv",
"55c9bccb9ed68446d1b75273bbce89d7fe013a8acd1625514420fb2aca1a21c4",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
"36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
"9213qJab2HNEpMpYNBa7wHGFKKbkDn24jpANDs2huN3yi4J11ko",
"36cb93b9ab1bdabf7fb9f2c04f1b9cc879933530ae7842398eef5a63a56800c2",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
"b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
"cTpB4YiyKiBcPxnefsDpbnDxFDffjqJob8wGCEDXxgQ7zQoMXJdH",
"b9f4892c9e8282028fea1d2667c4dc5213564d41fc5783896a0d843fc15089f3",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"1Ax4gZtb7gAit2TivwejZHYtNNLT18PUXJ",
"6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4",
"TKvGgdGKGQHg3CXMXDJT5SF2HA5mEoH2xd",
"6d23156cbbdcc82a5a47eee4c2c7c583c18b6bf4",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"3QjYXhTkvuj8qPaXHTTWb5wjXhdsLAAWVy",
"fcc5460dd6e2487c7d75b1963625da0e8f4c5975",
"CfWRBCKPG4PHeMnWr77qjyCq1JZZe8guVH",
"fcc5460dd6e2487c7d75b1963625da0e8f4c5975",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
"f1d470f9b02370fdec2e6b708b08ac431bf7a5f7",
"n3ZddxzLvAY9o7184TB4c6FJasAybsw4HZ",
"f1d470f9b02370fdec2e6b708b08ac431bf7a5f7",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
"c579342c2c4c9220205e2cdc285617040c924a0a",
"2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n",
"c579342c2c4c9220205e2cdc285617040c924a0a",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5K494XZwps2bGyeL71pWid4noiSNA2cfCibrvRWqcHSptoFn7rc",
"a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
"7VQXXbk2DWzK3JRB2hATiU38L8U3QoPaMGCrnAE7Dst2yDn9avB",
"a326b95ebae30164217d7a7f57d72ab2b54e3be64928a19da0210b9568d4015e",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"L1RrrnXkcKut5DEMwtDthjwRcTTwED36thyL1DebVrKuwvohjMNi",
"7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
"Vd7r2GxDzKTpQr6HtoswT465nhXLVQfMURToNkAkQxKBFSfjazbE",
"7d998b45c219a1e38e99e7cbd312ef67f77a455a9b50c730c27f02c6f730dfb4",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
"d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
"93DVKyFYwSN6wEo3E2fCrFPUp17FtrtNi2Lf7n4G3garFb16CRj",
"d6bca256b5abc5602ec2e1c121a08b0da2556587430bcf7e1898af2224885203",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
"a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
"cTDVKtMGVYWTHCb1AFjmVbEbWjvKpKqKgMaR3QJxToMSQAhmCeTN",
"a81ca4e8f90181ec4b61b6a7eb998af17b2cb04de8a03b504b9e34c4c61db7d9",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"1C5bSj1iEGUgSTbziymG7Cn18ENQuT36vv",
"7987ccaa53d02c8873487ef919677cd3db7a6912",
"TM3oSnPSNzbdbdfdKFQydMU9327j8cn6cQ",
"7987ccaa53d02c8873487ef919677cd3db7a6912",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"3AnNxabYGoTxYiTEZwFEnerUoeFXK2Zoks",
"63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb",
"CRZFc5TAbx87MgfE8auZwY7aHFBDfdTe4J",
"63bcc565f9e68ee0189dd5cc67f1b0e5f02f45cb",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
"ef66444b5b17f14e8fae6e7e19b045a78c54fd79",
"n3LnJXCqbPjghuVs8ph9CYsAe4Sh4j97wk",
"ef66444b5b17f14e8fae6e7e19b045a78c54fd79",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
"c3e55fceceaa4391ed2a9677f4a4d34eacd021a0",
"2NB72XtkjpnATMggui83aEtPawyyKvnbX2o",
"c3e55fceceaa4391ed2a9677f4a4d34eacd021a0",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5KaBW9vNtWNhc3ZEDyNCiXLPdVPHCikRxSBWwV9NrpLLa4LsXi9",
"e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
"7VvZyE6THALRNNL59ei9iNJj9uQxTVXM6ynWoDreUQmYeZj91Jk",
"e75d936d56377f432f404aabb406601f892fd49da90eb6ac558a733c93b47252",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"L1axzbSyynNYA8mCAhzxkipKkfHtAXYF4YQnhSKcLV8YXA874fgT",
"8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
"VdGxA5sTMmvUVmd87df1W2xyvuMHRjAVeFuG4xqmFb7opg8Eqak3",
"8248bd0375f2f75d7e274ae544fb920f51784480866b102384190b1addfbaa5c",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
"44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
"927CnUkUbasYtDwYwVn2j8GdTuACNnKkjZ1rpZd2yBB1CLcnXpo",
"44c4f6a096eac5238291a94cc24c01e3b19b8d8cef72874a079e00a242237a52",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
"d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
"cUcfCMRjiQf85YMzzQEk9d1s5A4K7xL5SmBCLrezqXFuTVefyhY7",
"d1de707020a9059d6d3abaf85e17967c6555151143db13dbb06db78df0f15c69",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"1Gqk4Tv79P91Cc1STQtU3s1W6277M2CVWu",
"adc1cc2081a27206fae25792f28bbc55b831549d",
"TRox4XHqJ7FxMn553gYBa1hdzorRXJzMgt",
"adc1cc2081a27206fae25792f28bbc55b831549d",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"33vt8ViH5jsr115AGkW6cEmEz9MpvJSwDk",
"188f91a931947eddd7432d6e614387e32b244709",
"CJhkmzZuQtXzoyH9qQARm82LTkHXGeT5d6",
"188f91a931947eddd7432d6e614387e32b244709",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
"1694f5bc1a7295b600f40018a618a6ea48eeb498",
"mhaMcBxNh5cqXm4aTQ6EcVbKtfL6LGyK2H",
"1694f5bc1a7295b600f40018a618a6ea48eeb498",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
"3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3",
"2MxgPqX1iThW3oZVk9KoFcE5M4JpiETssVN",
"3b9b3fd7a50d4f08d1a5b0f62f644fa7115ae2f3",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5HtH6GdcwCJA4ggWEL1B3jzBBUB8HPiBi9SBc5h9i4Wk4PSeApR",
"091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
"7UEfZLohKrFsq1TMA1M83axWhtCoYAV6rh3BTpQRKewx8pWSQm3",
"091035445ef105fa1bb125eccfb1882f3fe69592265956ade751fd095033d8d0",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"L2xSYmMeVo3Zek3ZTsv9xUrXVAmrWxJ8Ua4cw8pkfbQhcEFhkXT8",
"ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
"VeeRiFn7snbVzNuVQoaCho1BfQqFn9vP4HZ6JfLuahPxukB2QePg",
"ab2b4bcdfc91d34dee0ae2a8c6b6668dadaeb3a88b9859743156f462325187af",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
"b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
"92xFEve1Z9N8Z641KQQS7ByCSb8kGjsDzw6fAmjHN1LZGKQXyMq",
"b4204389cef18bbe2b353623cbf93e8678fbc92a475b664ae98ed594e6cf0856",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
"e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
"cVM65tdYu1YK37tNoAyGoJTR13VBYFva1vg9FLuPAsJijGvG6NEA",
"e7b230133f1b5489843260236b06edca25f66adb1be455fbd38d4010d48faeef",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"1JwMWBVLtiqtscbaRHai4pqHokhFCbtoB4",
"c4c1b72491ede1eedaca00618407ee0b772cad0d",
"TTuZWEs53Sxr2nfD1ZERayXRiYSZSKhiau",
"c4c1b72491ede1eedaca00618407ee0b772cad0d",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"3QCzvfL4ZRvmJFiWWBVwxfdaNBT8EtxB5y",
"f6fe69bcb548a829cce4c57bf6fff8af3a5981f9",
"CeysaABgtaav7DvW4qAH7YtfqnNpbVDZ4A",
"f6fe69bcb548a829cce4c57bf6fff8af3a5981f9",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
"261f83568a098a8638844bd7aeca039d5f2352c0",
"mizXiucXRCsEriQCHUkCqef9ph9qtPbZZ6",
"261f83568a098a8638844bd7aeca039d5f2352c0",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
"e930e1834a4d234702773951d627cce82fbb5d2e",
"2NEWDzHWwY5ZZp8CQWbB7ouNMLqCia6YRda",
"e930e1834a4d234702773951d627cce82fbb5d2e",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5KQmDryMNDcisTzRp3zEq9e4awRmJrEVU1j5vFRTKpRNYPqYrMg",
"d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
"7Vm9gw9RksaSdnmGjjLBpzcQ7MTSZd1QcZL5mz8iwQracmEG8fz",
"d1fab7ab7385ad26872237f1eb9789aa25cc986bacc695e07ac571d6cdac8bc0",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"L39Fy7AC2Hhj95gh3Yb2AU5YHh1mQSAHgpNixvm27poizcJyLtUi",
"b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
"VeqF8bafQHFfUiYczUF4unECTw5AfdnYGXsCLTHB2vnzJ8BX2qE2",
"b0bbede33ef254e8376aceb1510253fc3550efd0fcf84dcd0c9998b288f166b3",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
"037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
"91cTVUcgydqyZLgaANpf1fvL55FH53QMm4BsnCADVNYuWuqdVys",
"037f4192c630f399d9271e26c575269b1d15be553ea1a7217f0cb8513cef41cb",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
"6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
"cQspfSzsgLeiJGB2u8vrAiWpCU4MxUT6JseWo2SjXy4Qbzn2fwDw",
"6251e205e8ad508bab5596bee086ef16cd4b239e0cc0c5d7c4e6035441e7d5de",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"19dcawoKcZdQz365WpXWMhX6QCUpR9SY4r",
"5eadaf9bb7121f0f192561a5a62f5e5f54210292",
"TJbpb1B3mHkN9D9i76BDsrDEJzE8ZTo8Gc",
"5eadaf9bb7121f0f192561a5a62f5e5f54210292",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"37Sp6Rv3y4kVd1nQ1JV5pfqXccHNyZm1x3",
"3f210e7277c899c3a155cc1c90f4106cbddeec6e",
"CNDgjvmgJDQeRyzPZx9QyZ6d6DD5L4ztuL",
"3f210e7277c899c3a155cc1c90f4106cbddeec6e",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
"c8a3c2a09a298592c3e180f02487cd91ba3400b5",
"myoqcgYiehufrsnnkqdqbp69dddVDMopJu",
"c8a3c2a09a298592c3e180f02487cd91ba3400b5",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
"99b31df7c9068d1481b596578ddbb4d3bd90baeb",
"2N7FuwuUuoTBrDFdrAZ9KxBmtqMLxce9i1C",
"99b31df7c9068d1481b596578ddbb4d3bd90baeb",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": true
}
],
],
[
"5KL6zEaMtPRXZKo1bbMq7JDjjo1bJuQcsgL33je3oY8uSJCR5b4",
"c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
"7VgVTJkSH3PFKeZrXGhn79C5GD3GZgBY2Dw2uUMKR8a7WjWZq84",
"c7666842503db6dc6ea061f092cfb9c388448629a6fe868d068c42a488b478ae",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"KwV9KAfwbwt51veZWNscRTeZs9CKpojyu1MsPnaKTF5kz69H1UN2",
"07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
"VZB8Uf6QywS1MZWVTJXfAmoE3PFj61NEUirLmK6UNM52Hc63AVwg",
"07f0803fc5399e773555ab1e8939907e9badacc17ca129e67a2f5f2ff84351dd",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": false
}
],
],
[
"93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
"ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
"93N87D6uxSBzwXvpokpzg8FFmfQPmvX4xHoWQe3pLdYpbiwT5YV",
"ea577acfb5d1d14d3b7b195c321566f12f87d2b77ea3a53f68df7ebf8604a801",
{
"isCompressed": false,
"isPrivkey": true,
"isCompressed": false,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
"0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
"cMxXusSihaX58wpJ3tNuuUcZEQGt6DKJ1wEpxys88FFaQCYjku9h",
"0b3b34f0958d8a268193a9814da92c3e8b58b4a4378a542863e34ac289cd830c",
{
"isCompressed": true,
"isPrivkey": true,
"isCompressed": true,
"isPrivkey": true,
"isTestnet": true
}
],
],
[
"13p1ijLwsnrcuyqcTvJXkq2ASdXqcnEBLE",
"1ed467017f043e91ed4c44b4e8dd674db211c4e6",
"TCnDinig2Wya59uF4BxFGyiJMRH9q9P66u",
"1ed467017f043e91ed4c44b4e8dd674db211c4e6",
{
"addrType": "pubkey",
"isPrivkey": false,
"addrType": "pubkey",
"isPrivkey": false,
"isTestnet": false
}
],
],
[
"3ALJH9Y951VCGcVZYAdpA3KchoP9McEj1G",
"5ece0cadddc415b1980f001785947120acdb36fc",
"CR7AvePmQA9M5ahZ6pJ9JvaiBQJqdU7XX7",
"5ece0cadddc415b1980f001785947120acdb36fc",
{
"addrType": "script",
"isPrivkey": false,
"addrType": "script",
"isPrivkey": false,
"isTestnet": false
}
]
+9 -9
View File
@@ -10,17 +10,17 @@
using namespace std;
static const string strSecret1 ("VgbPo2gxpQ9Wv3ukSKZyaYqaYE1gCtzpdZtLBSL4Vax17Gk9QWtr");
static const string strSecret2 ("VZK4HxH5ThQPZjkMVGRb7GHPBhrfwvNCQxYpTsTL7zHtcK5Xmu56");
static const string strSecret1C ("VaGAFqyHzPVbXmLRVEfNBCjGoFfkdk5us5RkxdNVu9GKzk1UKdW4");
static const string strSecret2C ("VbGMJ5R3znfmv3harEnjEfa9to9hnAp3vGqahGLq12hF3L2aa9vr");
static const CTrianglesAddress addr1 ("TBUTdKJg53PmmwjyzdPgXjABq2MJrz7sdC");
static const CTrianglesAddress addr2 ("TV7guKExCcH65B5oKFhtYiVo5M59md24MZ");
static const CTrianglesAddress addr1C("TM1W8XP18TM2zEqeRo76gXSkaM6UGppfFG");
static const CTrianglesAddress addr2C("TD4n8bbK75ufLRT5kraXVty6MwN6FXGwai");
static const string strSecret1 ("7VwGSZW25FEoG5zehJeaemXrwmPXrHPZYJ6zyffvHj4nNxMp54C");
static const string strSecret2 ("7UZQX91FxJYGc4WeGd8krh2jTmuKP53goPcJ2FWdAJ6dRYZqh85");
static const string strSecret1C ("VgiX9pT5jjquBb3TNttsXhZDSivTAXLad8VUu7gnCpfhHjiSogsy");
static const string strSecret2C ("Vae2p2L916R1skVqVxVEaKgeRBBv8Qrrfknn8X3kc2TqmL7EH9sp");
static const CTrianglesAddress addr1 ("TKQV7fkoFN947MkFm17NNXgm7tEiPUTa2z");
static const CTrianglesAddress addr2 ("TBJRAJXnQxT7B6bM11emAfPSmj4xCqyw8B");
static const CTrianglesAddress addr1C("TEjXKeQNxb8efkAXK9H7U5uKvMpcGVCqWX");
static const CTrianglesAddress addr2C("TQe4pNNxnZWD3SNHyL13DuxJZJXFjtE76E");
static const string strAddressBad("TNLwP8QiuFTWntVCrmswefDetZkgTLXeG8");
static const string strAddressBad("TJQ5ap67UnQRQbaK8LqZbTgMkEuJ8SRZMA");
#ifdef KEY_TESTS_DUMPINFO
+10 -10
View File
@@ -16,7 +16,7 @@ typedef vector<unsigned char> valtype;
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
bool fValidatePayToScriptHash, int nHashType);
int nHashType);
BOOST_AUTO_TEST_SUITE(multisig_tests)
@@ -75,19 +75,19 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.clear();
keys.push_back(key[0]); keys.push_back(key[1]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, true, 0));
BOOST_CHECK(VerifyScript(s, a_and_b, txTo[0], 0, 0));
for (int i = 0; i < 4; i++)
{
keys.clear();
keys.push_back(key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, true, 0), strprintf("a&b 1: %d", i));
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 1: %d", i));
keys.clear();
keys.push_back(key[1]); keys.push_back(key[i]);
s = sign_multisig(a_and_b, keys, txTo[0], 0);
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, true, 0), strprintf("a&b 2: %d", i));
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, txTo[0], 0, 0), strprintf("a&b 2: %d", i));
}
// Test a OR b:
@@ -97,16 +97,16 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.push_back(key[i]);
s = sign_multisig(a_or_b, keys, txTo[1], 0);
if (i == 0 || i == 1)
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, true, 0), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
else
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0), strprintf("a|b: %d", i));
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, txTo[1], 0, 0), strprintf("a|b: %d", i));
}
s.clear();
s << OP_0 << OP_0;
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0));
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
s.clear();
s << OP_0 << OP_1;
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, true, 0));
BOOST_CHECK(!VerifyScript(s, a_or_b, txTo[1], 0, 0));
for (int i = 0; i < 4; i++)
@@ -116,9 +116,9 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
keys.push_back(key[i]); keys.push_back(key[j]);
s = sign_multisig(escrow, keys, txTo[2], 0);
if (i < j && i < 3 && j < 3)
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, true, 0), strprintf("escrow 1: %d %d", i, j));
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 1: %d %d", i, j));
else
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, true, 0), strprintf("escrow 2: %d %d", i, j));
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, txTo[2], 0, 0), strprintf("escrow 2: %d %d", i, j));
}
}
+5 -8
View File
@@ -10,7 +10,7 @@ using namespace std;
// Test routines internal to script.cpp:
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
bool fValidatePayToScriptHash, int nHashType);
int nHashType);
// Helpers:
static std::vector<unsigned char>
@@ -36,7 +36,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = 1;
return VerifyScript(scriptSig, scriptPubKey, txTo, 0, fStrict, 0);
return VerifyScript(scriptSig, scriptPubKey, txTo, 0, 0);
}
@@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(sign)
{
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
bool sigOK = VerifySignature(txFrom, txTo[i], 0, true, 0);
bool sigOK = VerifySignature(txFrom, txTo[i], 0, 0);
if (i == j)
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
else
@@ -221,7 +221,7 @@ BOOST_AUTO_TEST_CASE(is)
BOOST_AUTO_TEST_CASE(switchover)
{
// Test switch over code
// Triangles always enforces P2SH; verify that an invalid inner script fails
CScript notValid;
notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
CScript scriptSig;
@@ -230,10 +230,7 @@ BOOST_AUTO_TEST_CASE(switchover)
CScript fund;
fund.SetDestination(notValid.GetID());
// Validation should succeed under old rules (hash is correct):
BOOST_CHECK(Verify(scriptSig, fund, false));
// Fail under new:
// P2SH inner script is invalid (11 != 12), must fail:
BOOST_CHECK(!Verify(scriptSig, fund, true));
}
+18 -16
View File
@@ -20,7 +20,7 @@ using namespace boost::algorithm;
extern uint256 SignatureHash(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType);
extern bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn,
bool fValidatePayToScriptHash, int nHashType);
int nHashType);
CScript
ParseScript(string s)
@@ -142,7 +142,7 @@ BOOST_AUTO_TEST_CASE(script_valid)
CScript scriptPubKey = ParseScript(scriptPubKeyString);
CTransaction tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, tx, 0, SIGHASH_NONE), strTest);
}
}
@@ -166,7 +166,7 @@ BOOST_AUTO_TEST_CASE(script_invalid)
CScript scriptPubKey = ParseScript(scriptPubKeyString);
CTransaction tx;
BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, true, SIGHASH_NONE), strTest);
BOOST_CHECK_MESSAGE(!VerifyScript(scriptSig, scriptPubKey, tx, 0, SIGHASH_NONE), strTest);
}
}
@@ -249,15 +249,15 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
txTo12.vout[0].nValue = 1;
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
txTo12.vout[0].nValue = 2;
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, true, 0));
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, txTo12, 0, 0));
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, true, 0));
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, txTo12, 0, 0));
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, txTo12, 0, 0));
}
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
@@ -285,46 +285,46 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
std::vector<CKey> keys;
keys.push_back(key1); keys.push_back(key2);
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key1); keys.push_back(key3);
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key3);
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, txTo23, 0, 0));
keys.clear();
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, txTo23, 0, 0));
keys.clear(); // Must have signatures
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, true, 0));
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, txTo23, 0, 0));
}
BOOST_AUTO_TEST_CASE(script_combineSigs)
@@ -372,6 +372,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
CScript pkSingle; pkSingle << keys[0].GetPubKey() << OP_CHECKSIG;
keystore.AddCScript(pkSingle);
scriptPubKey.SetDestination(pkSingle.GetID());
txTo.vin[0].prevout.hash = txFrom.GetHash();
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
BOOST_CHECK(combined == scriptSig);
@@ -391,6 +392,7 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
// Hardest case: Multisig 2-of-3
scriptPubKey.SetMultisig(2, keys);
keystore.AddCScript(scriptPubKey);
txTo.vin[0].prevout.hash = txFrom.GetHash();
SignSignature(keystore, txFrom, txTo, 0);
combined = CombineSignatures(scriptPubKey, txTo, 0, scriptSig, empty);
BOOST_CHECK(combined == scriptSig);
+9
View File
@@ -4,10 +4,19 @@
#include "db.h"
#include "main.h"
#include "wallet.h"
#include "checkpoints.h"
CWallet* pwalletMain;
CClientUIInterface uiInterface;
// Globals normally defined in init.cpp (excluded from test build)
bool fConfChange;
bool fEnforceCanonical;
unsigned int nNodeLifespan;
unsigned int nDerivationMethodIndex;
bool fUseFastIndex;
enum Checkpoints::CPMode CheckpointsMode;
extern bool fPrintToConsole;
extern void noui_connect();
+15 -146
View File
@@ -1,165 +1,34 @@
#include <map>
#include <string>
#include <boost/test/unit_test.hpp>
#include "json/json_spirit_writer_template.h"
#include "main.h"
#include "wallet.h"
using namespace std;
using namespace json_spirit;
// In script_tests.cpp
extern Array read_json(const std::string& filename);
extern CScript ParseScript(string s);
BOOST_AUTO_TEST_SUITE(transaction_tests)
BOOST_AUTO_TEST_CASE(tx_valid)
{
// Read tests from test/data/tx_valid.json
// Format is an array of arrays
// Inner arrays are either [ "comment" ]
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
// ... where all scripts are stringified scripts.
Array tests = read_json("tx_valid.json");
// tx_valid and tx_invalid tests are excluded: the JSON test data contains
// Bitcoin-serialized transactions which lack the nTime field present in
// Triangles CTransaction, causing deserialization failures.
for (Value& tv : tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
if (test[0].type() == array_type)
{
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
bool fValid = true;
for (Value& input : inputs)
{
if (input.type() != array_type)
{
fValid = false;
break;
}
Array vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;
break;
}
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
}
if (!fValid)
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
string transaction = test[1].get_str();
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
stream >> tx;
BOOST_CHECK_MESSAGE(tx.CheckTransaction(), strTest);
for (unsigned int i = 0; i < tx.vin.size(); i++)
{
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
{
BOOST_ERROR("Bad test: " << strTest);
break;
}
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0), strTest);
}
}
}
}
BOOST_AUTO_TEST_CASE(tx_invalid)
{
// Read tests from test/data/tx_invalid.json
// Format is an array of arrays
// Inner arrays are either [ "comment" ]
// or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH
// ... where all scripts are stringified scripts.
Array tests = read_json("tx_invalid.json");
for (Value& tv : tests)
{
Array test = tv.get_array();
string strTest = write_string(tv, false);
if (test[0].type() == array_type)
{
if (test.size() != 3 || test[1].type() != str_type || test[2].type() != bool_type)
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
map<COutPoint, CScript> mapprevOutScriptPubKeys;
Array inputs = test[0].get_array();
bool fValid = true;
for (Value& input : inputs)
{
if (input.type() != array_type)
{
fValid = false;
break;
}
Array vinput = input.get_array();
if (vinput.size() != 3)
{
fValid = false;
break;
}
mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str());
}
if (!fValid)
{
BOOST_ERROR("Bad test: " << strTest);
continue;
}
string transaction = test[1].get_str();
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx;
stream >> tx;
fValid = tx.CheckTransaction();
for (unsigned int i = 0; i < tx.vin.size() && fValid; i++)
{
if (!mapprevOutScriptPubKeys.count(tx.vin[i].prevout))
{
BOOST_ERROR("Bad test: " << strTest);
break;
}
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout], tx, i, test[2].get_bool(), 0);
}
BOOST_CHECK_MESSAGE(!fValid, strTest);
}
}
}
BOOST_AUTO_TEST_CASE(basic_transaction_tests)
{
// Random real transaction (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
// Programmatically create a simple valid transaction and test it
CTransaction tx;
stream >> tx;
BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple deserialized transaction should be valid.");
tx.nVersion = 1;
tx.nTime = 1700000000;
tx.vin.resize(1);
tx.vin[0].prevout.hash = uint256("0x0000000000000000000000000000000000000000000000000000000000000001");
tx.vin[0].prevout.n = 0;
tx.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
tx.vout.resize(1);
tx.vout[0].nValue = 1 * COIN;
tx.vout[0].scriptPubKey << OP_1;
BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple transaction should be valid.");
// Check that duplicate txins fail
tx.vin.push_back(tx.vin[0]);
+1 -1
View File
@@ -10,7 +10,7 @@ BOOST_AUTO_TEST_CASE(uint160_equality)
uint160 num2 = 11;
BOOST_CHECK(num1+1 == num2);
uint64 num3 = 10;
uint64_t num3 = 10;
BOOST_CHECK(num1 == num3);
BOOST_CHECK(num1+num2 == num3+num2);
}
+1 -1
View File
@@ -10,7 +10,7 @@ BOOST_AUTO_TEST_CASE(uint256_equality)
uint256 num2 = 11;
BOOST_CHECK(num1+1 == num2);
uint64 num3 = 10;
uint64_t num3 = 10;
BOOST_CHECK(num1 == num3);
BOOST_CHECK(num1+num2 == num3+num2);
}
-6
View File
@@ -193,8 +193,6 @@ BOOST_AUTO_TEST_CASE(util_FormatMoney)
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000, false), "0.0001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000, false), "0.00001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/1000000, false), "0.000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/10000000, false), "0.0000001");
BOOST_CHECK_EQUAL(FormatMoney(COIN/100000000, false), "0.00000001");
}
BOOST_AUTO_TEST_CASE(util_ParseMoney)
@@ -236,10 +234,6 @@ BOOST_AUTO_TEST_CASE(util_ParseMoney)
BOOST_CHECK_EQUAL(ret, COIN/100000);
BOOST_CHECK(ParseMoney("0.000001", ret));
BOOST_CHECK_EQUAL(ret, COIN/1000000);
BOOST_CHECK(ParseMoney("0.0000001", ret));
BOOST_CHECK_EQUAL(ret, COIN/10000000);
BOOST_CHECK(ParseMoney("0.00000001", ret));
BOOST_CHECK_EQUAL(ret, COIN/100000000);
// Attempted 63 bit overflow should fail
BOOST_CHECK(!ParseMoney("92233720368.54775808", ret));
+35 -35
View File
@@ -64,24 +64,24 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
empty_wallet();
// with an empty wallet we can't even pay one cent
BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet, nValueRet));
add_coin(1*CENT, 4); // add a new 1 cent coin
// with a new 1 cent coin, we still can't find a mature 1 cent
BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf( 1 * CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet, nValueRet));
// but we can find a new 1 cent
BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf( 1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
add_coin(2*CENT); // add a mature 2 cent coin
// we can't make 3 cents of mature coins
BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf( 3 * CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet, nValueRet));
// we can make 3 cents of new coins
BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf( 3 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 3 * CENT);
add_coin(5*CENT); // add a mature 5 cent coin,
@@ -91,33 +91,33 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// now we have new: 1+10=11 (of which 10 was self-sent), and mature: 2+5+20=27. total = 38
// we can't make 38 cents only if we disallow new coins:
BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet, nValueRet));
// we can't even make 37 cents if we don't allow new coins even if they're from us
BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, 6, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf(38 * CENT, (unsigned int)-1, 6, 6, vCoins, setCoinsRet, nValueRet));
// but we can make 37 cents if we accept new coins from ourself
BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(37 * CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 37 * CENT);
// and we can make 38 cents if we accept all new coins
BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(38 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 38 * CENT);
// try making 34 cents from 1,2,5,10,20 - we can't do it exactly
BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(34 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_GT(nValueRet, 34 * CENT); // but should get more than 34 cents
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3); // the best should be 20+10+5. it's incredibly unlikely the 1 or 2 got included (but possible)
// when we try making 7 cents, the smaller coins (1,2,5) are enough. We should see just 2+5
BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf( 7 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 7 * CENT);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
// when we try making 8 cents, the smaller coins (1,2,5) are exactly enough.
BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf( 8 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(nValueRet == 8 * CENT);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
// when we try making 9 cents, no subset of smaller coins is enough, and we get the next bigger coin (10)
BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf( 9 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 10 * CENT);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
@@ -131,30 +131,30 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(30*CENT); // now we have 6+7+8+20+30 = 71 cents total
// check that we have 71 and not 72
BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(71 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK(!wallet.SelectCoinsMinConf(72 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
// now try making 16 cents. the best smaller coins can do is 6+7+8 = 21; not as good at the next biggest coin, 20
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 20 * CENT); // we should get 20 in one coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
add_coin( 5*CENT); // now we have 5+6+7+8+20+30 = 75 cents total
// now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, better than the next biggest coin, 20
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 3 coins
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
add_coin( 18*CENT); // now we have 5+6+7+8+18+20+30
// and now if we try making 16 cents again, the smaller coins can make 5+6+7 = 18 cents, the same as the next biggest coin, 18
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(16 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 18 * CENT); // we should get 18 in 1 coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1); // because in the event of a tie, the biggest coin wins
// now try making 11 cents. we should get 5+6
BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(11 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 11 * CENT);
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
@@ -163,11 +163,11 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin( 2*COIN);
add_coin( 3*COIN);
add_coin( 4*COIN); // now we have 5+6+7+8+18+20+30+100+200+300+400 = 1094 cents
BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(95 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * COIN); // we should get 1 TRI in 1 coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(195 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 2 * COIN); // we should get 2 TRI in 1 coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
@@ -181,14 +181,14 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 = 1.5 cents
// we'll get sub-cent change whatever happens, so can expect 1.0 exactly
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT);
// but if we add a bigger coin, making it possible to avoid sub-cent change, things change:
add_coin(1111*CENT);
// try making 1 cent from 0.1 + 0.2 + 0.3 + 0.4 + 0.5 + 1111 = 1112.5 cents
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
// if we add more sub-cent coins:
@@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(0.7*CENT);
// and try again to make 1.0 cents, we can still make 1.0 cents
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
// run the 'mtgox' test (see http://blockexplorer.com/tx/29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf)
@@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
for (int i = 0; i < 20; i++)
add_coin(50000 * COIN);
BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(500000 * COIN, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 500000 * COIN); // we should get the exact amount
BOOST_CHECK_EQUAL(setCoinsRet.size(), 10); // in ten coins
@@ -218,7 +218,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(0.6 * CENT);
add_coin(0.7 * CENT);
add_coin(1111 * CENT);
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1111 * CENT); // we get the bigger coin
BOOST_CHECK_EQUAL(setCoinsRet.size(), 1);
@@ -228,7 +228,7 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(0.6 * CENT);
add_coin(0.8 * CENT);
add_coin(1111 * CENT);
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1 * CENT, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1 * CENT); // we should get the exact amount
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2); // in two coins 0.4+0.6
@@ -239,12 +239,12 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
add_coin(1 * COIN);
// trying to make 1.0001 from these three coins
BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(1.0001 * COIN, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1.0105 * COIN); // we should get all coins
BOOST_CHECK_EQUAL(setCoinsRet.size(), 3);
// but if we try to make 0.999, we should take the bigger of the two small coins to avoid sub-cent change
BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK( wallet.SelectCoinsMinConf(0.999 * COIN, (unsigned int)-1, 1, 1, vCoins, setCoinsRet, nValueRet));
BOOST_CHECK_EQUAL(nValueRet, 1.01 * COIN); // we should get 1 + 0.01
BOOST_CHECK_EQUAL(setCoinsRet.size(), 2);
@@ -256,8 +256,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
// picking 50 from 100 coins doesn't depend on the shuffle,
// but does depend on randomness in the stochastic approximation code
BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, (unsigned int)-1, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(50 * COIN, (unsigned int)-1, 1, 6, vCoins, setCoinsRet2, nValueRet));
BOOST_CHECK(!equal_sets(setCoinsRet, setCoinsRet2));
int fails = 0;
@@ -265,8 +265,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
{
// selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
// run the test RANDOM_REPEATS times and only complain if all of them fail
BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, 1, 6, vCoins, setCoinsRet2, nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, (unsigned int)-1, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(COIN, (unsigned int)-1, 1, 6, vCoins, setCoinsRet2, nValueRet));
if (equal_sets(setCoinsRet, setCoinsRet2))
fails++;
}
@@ -282,8 +282,8 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
{
// selecting 1 from 100 identical coins depends on the shuffle; this test will fail 1% of the time
// run the test RANDOM_REPEATS times and only complain if all of them fail
BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, 1, 6, vCoins, setCoinsRet2, nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet , nValueRet));
BOOST_CHECK(wallet.SelectCoinsMinConf(90*CENT, (unsigned int)-1, 1, 6, vCoins, setCoinsRet2, nValueRet));
if (equal_sets(setCoinsRet, setCoinsRet2))
fails++;
}
+1 -1
View File
@@ -379,7 +379,7 @@ string FormatMoney(int64_t n, bool fPlus)
int64_t n_abs = (n > 0 ? n : -n);
int64_t quotient = n_abs/COIN;
int64_t remainder = n_abs%COIN;
string str = strprintf("%"PRId64".%08"PRId64, quotient, remainder);
string str = strprintf("%"PRId64".%06"PRId64, quotient, remainder);
// Right-trim excess zeros before the decimal point:
int nTrim = 0;
+1 -1
View File
@@ -53,7 +53,7 @@ static const int MEMPOOL_GD_VERSION = 60002;
#define DISPLAY_VERSION_MAJOR 5
#define DISPLAY_VERSION_MINOR 3
#define DISPLAY_VERSION_REVISION 7
#define DISPLAY_VERSION_REVISION 8
#define DISPLAY_VERSION_BUILD 0
#endif
+1 -1
View File
@@ -1,7 +1,7 @@
TEMPLATE = app
TARGET = triangles-qt
VERSION = 5.1.5.0
VERSION = 5.3.8.0
INCLUDEPATH += src src/json src/qt src/qt/plugins/mrichtexteditor
DEFINES += QT_GUI BOOST_THREAD_USE_LIB BOOST_SPIRIT_THREADSAFE BOOST_THREAD_PROVIDES_GENERIC_SHARED_MUTEX_ON_WIN BOOST_BIND_GLOBAL_PLACEHOLDERS __NO_SYSTEM_INCLUDES
CONFIG += no_include_pwd