Claim name returned is strange #172
15 changed files with 227 additions and 65 deletions
|
@ -82,13 +82,15 @@ function cleanup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create unsigned merge commit.
|
# Create unsigned merge commit.
|
||||||
|
PRTITLE=`curl -s https://api.github.com/repos/$REPO/pulls/$PULL | grep -e ' "title": ".*",'| awk -F'"' '{print $4}'`
|
||||||
|
MERGEMESSAGE="Merge #$PULL: $PRTITLE"
|
||||||
(
|
(
|
||||||
echo "Merge pull request #$PULL"
|
echo $MERGEMESSAGE
|
||||||
echo ""
|
echo ""
|
||||||
git log --no-merges --topo-order --pretty='format:%h %s (%an)' pull/"$PULL"/base..pull/"$PULL"/head
|
git log --no-merges --topo-order --pretty='format:%h %s (%an)' pull/"$PULL"/base..pull/"$PULL"/head
|
||||||
)>"$TMPDIR/message"
|
)>"$TMPDIR/message"
|
||||||
if git merge -q --commit --no-edit --no-ff -m "$(<"$TMPDIR/message")" pull/"$PULL"/head; then
|
if git merge -q --commit --no-edit --no-ff -m "$(<"$TMPDIR/message")" pull/"$PULL"/head; then
|
||||||
if [ "d$(git log --pretty='format:%s' -n 1)" != "dMerge pull request #$PULL" ]; then
|
if [ "d$(git log --pretty='format:%s' -n 1)" != "d$MERGEMESSAGE" ]; then
|
||||||
echo "ERROR: Creating merge failed (already merged?)." >&2
|
echo "ERROR: Creating merge failed (already merged?)." >&2
|
||||||
cleanup
|
cleanup
|
||||||
exit 4
|
exit 4
|
||||||
|
|
BIN
contrib/gitian-downloader/jonasschnelli-key.pgp
Normal file
BIN
contrib/gitian-downloader/jonasschnelli-key.pgp
Normal file
Binary file not shown.
Binary file not shown.
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
static bool fDaemon;
|
static bool fDaemon;
|
||||||
|
|
||||||
void DetectShutdownThread(boost::thread_group* threadGroup)
|
void WaitForShutdown(boost::thread_group* threadGroup)
|
||||||
{
|
{
|
||||||
bool fShutdown = ShutdownRequested();
|
bool fShutdown = ShutdownRequested();
|
||||||
// Tell the main threads to shutdown.
|
// Tell the main threads to shutdown.
|
||||||
|
@ -56,7 +56,6 @@ void DetectShutdownThread(boost::thread_group* threadGroup)
|
||||||
bool AppInit(int argc, char* argv[])
|
bool AppInit(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
boost::thread_group threadGroup;
|
boost::thread_group threadGroup;
|
||||||
boost::thread* detectShutdownThread = NULL;
|
|
||||||
|
|
||||||
bool fRet = false;
|
bool fRet = false;
|
||||||
|
|
||||||
|
@ -144,7 +143,6 @@ bool AppInit(int argc, char* argv[])
|
||||||
#endif
|
#endif
|
||||||
SoftSetBoolArg("-server", true);
|
SoftSetBoolArg("-server", true);
|
||||||
|
|
||||||
detectShutdownThread = new boost::thread(boost::bind(&DetectShutdownThread, &threadGroup));
|
|
||||||
fRet = AppInit2(threadGroup);
|
fRet = AppInit2(threadGroup);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (const std::exception& e) {
|
||||||
|
@ -155,20 +153,12 @@ bool AppInit(int argc, char* argv[])
|
||||||
|
|
||||||
if (!fRet)
|
if (!fRet)
|
||||||
{
|
{
|
||||||
if (detectShutdownThread)
|
|
||||||
detectShutdownThread->interrupt();
|
|
||||||
|
|
||||||
threadGroup.interrupt_all();
|
threadGroup.interrupt_all();
|
||||||
// threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
|
// threadGroup.join_all(); was left out intentionally here, because we didn't re-test all of
|
||||||
// the startup-failure cases to make sure they don't result in a hang due to some
|
// the startup-failure cases to make sure they don't result in a hang due to some
|
||||||
// thread-blocking-waiting-for-another-thread-during-startup case
|
// thread-blocking-waiting-for-another-thread-during-startup case
|
||||||
}
|
} else {
|
||||||
|
WaitForShutdown(&threadGroup);
|
||||||
if (detectShutdownThread)
|
|
||||||
{
|
|
||||||
detectShutdownThread->join();
|
|
||||||
delete detectShutdownThread;
|
|
||||||
detectShutdownThread = NULL;
|
|
||||||
}
|
}
|
||||||
Shutdown();
|
Shutdown();
|
||||||
|
|
||||||
|
|
|
@ -161,7 +161,12 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class CCheckQueueControl<T>;
|
bool IsIdle()
|
||||||
|
{
|
||||||
|
boost::unique_lock<boost::mutex> lock(mutex);
|
||||||
|
return (nTotal == nIdle && nTodo == 0 && fAllOk == true);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -180,9 +185,8 @@ public:
|
||||||
{
|
{
|
||||||
// passed queue is supposed to be unused, or NULL
|
// passed queue is supposed to be unused, or NULL
|
||||||
if (pqueue != NULL) {
|
if (pqueue != NULL) {
|
||||||
assert(pqueue->nTotal == pqueue->nIdle);
|
bool isIdle = pqueue->IsIdle();
|
||||||
assert(pqueue->nTodo == 0);
|
assert(isIdle);
|
||||||
assert(pqueue->fAllOk == true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
100
src/main.cpp
100
src/main.cpp
|
@ -1592,6 +1592,51 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CDiskBlockPos& pos, const uin
|
||||||
|
|
||||||
} // anon namespace
|
} // anon namespace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the undo operation of a CTxInUndo to the given chain state.
|
||||||
|
* @param undo The undo object.
|
||||||
|
* @param view The coins view to which to apply the changes.
|
||||||
|
* @param out The out point that corresponds to the tx input.
|
||||||
|
* @return True on success.
|
||||||
|
*/
|
||||||
|
static bool ApplyTxInUndo(const CTxInUndo& undo, CCoinsViewCache& view, CNCCTrieCache& trieCache, const COutPoint& out)
|
||||||
|
{
|
||||||
|
bool fClean = true;
|
||||||
|
|
||||||
|
CCoinsModifier coins = view.ModifyCoins(out.hash);
|
||||||
|
if (undo.nHeight != 0) {
|
||||||
|
// undo data contains height: this is the last output of the prevout tx being spent
|
||||||
|
if (!coins->IsPruned())
|
||||||
|
fClean = fClean && error("%s: undo data overwriting existing transaction", __func__);
|
||||||
|
coins->Clear();
|
||||||
|
coins->fCoinBase = undo.fCoinBase;
|
||||||
|
coins->nHeight = undo.nHeight;
|
||||||
|
coins->nVersion = undo.nVersion;
|
||||||
|
} else {
|
||||||
|
if (coins->IsPruned())
|
||||||
|
fClean = fClean && error("%s: undo data adding output to missing transaction", __func__);
|
||||||
|
}
|
||||||
|
if (coins->IsAvailable(out.n))
|
||||||
|
fClean = fClean && error("%s: undo data overwriting existing output", __func__);
|
||||||
|
if (coins->vout.size() < out.n+1)
|
||||||
|
coins->vout.resize(out.n+1);
|
||||||
|
|
||||||
|
// restore NCC claim if applicable
|
||||||
|
int op;
|
||||||
|
std::vector<std::vector<unsigned char> > vvchParams;
|
||||||
|
if (DecodeNCCScript(undo.txout.scriptPubKey, op, vvchParams))
|
||||||
|
{
|
||||||
|
assert(vvchParams.size() == 2);
|
||||||
|
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
||||||
|
if (!trieCache.insertName(name, out.hash, out.n, undo.txout.nValue, undo.nHeight))
|
||||||
|
LogPrintf("Something went wrong inserting the name");
|
||||||
|
}
|
||||||
|
|
||||||
|
coins->vout[out.n] = undo.txout;
|
||||||
|
|
||||||
|
return fClean;
|
||||||
|
}
|
||||||
|
|
||||||
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, CNCCTrieCache& trieCache, bool* pfClean)
|
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, CNCCTrieCache& trieCache, bool* pfClean)
|
||||||
{
|
{
|
||||||
assert(pindex->GetBlockHash() == view.GetBestBlock());
|
assert(pindex->GetBlockHash() == view.GetBestBlock());
|
||||||
|
@ -1617,11 +1662,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
uint256 hash = tx.GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
|
|
||||||
// Check that all outputs are available and match the outputs in the block itself
|
// Check that all outputs are available and match the outputs in the block itself
|
||||||
// exactly. Note that transactions with only provably unspendable outputs won't
|
// exactly.
|
||||||
// have outputs available even in the block itself, so we handle that case
|
|
||||||
// specially with outsEmpty.
|
|
||||||
{
|
{
|
||||||
CCoins outsEmpty;
|
|
||||||
CCoinsModifier outs = view.ModifyCoins(hash);
|
CCoinsModifier outs = view.ModifyCoins(hash);
|
||||||
outs->ClearUnspendable();
|
outs->ClearUnspendable();
|
||||||
|
|
||||||
|
@ -1662,36 +1704,8 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
for (unsigned int j = tx.vin.size(); j-- > 0;) {
|
for (unsigned int j = tx.vin.size(); j-- > 0;) {
|
||||||
const COutPoint &out = tx.vin[j].prevout;
|
const COutPoint &out = tx.vin[j].prevout;
|
||||||
const CTxInUndo &undo = txundo.vprevout[j];
|
const CTxInUndo &undo = txundo.vprevout[j];
|
||||||
CCoinsModifier coins = view.ModifyCoins(out.hash);
|
if (!ApplyTxInUndo(undo, view, trieCache, out))
|
||||||
if (undo.nHeight != 0) {
|
fClean = false;
|
||||||
// undo data contains height: this is the last output of the prevout tx being spent
|
|
||||||
if (!coins->IsPruned())
|
|
||||||
fClean = fClean && error("DisconnectBlock(): undo data overwriting existing transaction");
|
|
||||||
coins->Clear();
|
|
||||||
coins->fCoinBase = undo.fCoinBase;
|
|
||||||
coins->nHeight = undo.nHeight;
|
|
||||||
coins->nVersion = undo.nVersion;
|
|
||||||
} else {
|
|
||||||
if (coins->IsPruned())
|
|
||||||
fClean = fClean && error("DisconnectBlock(): undo data adding output to missing transaction");
|
|
||||||
}
|
|
||||||
if (coins->IsAvailable(out.n))
|
|
||||||
fClean = fClean && error("DisconnectBlock(): undo data overwriting existing output");
|
|
||||||
if (coins->vout.size() < out.n+1)
|
|
||||||
coins->vout.resize(out.n+1);
|
|
||||||
|
|
||||||
// restore NCC claim if applicable
|
|
||||||
int op;
|
|
||||||
std::vector<std::vector<unsigned char> > vvchParams;
|
|
||||||
if (DecodeNCCScript(undo.txout.scriptPubKey, op, vvchParams))
|
|
||||||
{
|
|
||||||
assert(vvchParams.size() == 2);
|
|
||||||
std::string name(vvchParams[0].begin(), vvchParams[0].end());
|
|
||||||
if (!trieCache.insertName(name, out.hash, out.n, undo.txout.nValue, undo.nHeight))
|
|
||||||
LogPrintf("Something went wrong inserting the name");
|
|
||||||
}
|
|
||||||
|
|
||||||
coins->vout[out.n] = undo.txout;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1702,9 +1716,9 @@ bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex
|
||||||
if (pfClean) {
|
if (pfClean) {
|
||||||
*pfClean = fClean;
|
*pfClean = fClean;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
return fClean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return fClean;
|
||||||
}
|
}
|
||||||
|
|
||||||
void static FlushBlockFile(bool fFinalize = false)
|
void static FlushBlockFile(bool fFinalize = false)
|
||||||
|
@ -3539,7 +3553,7 @@ void static ProcessGetData(CNode* pfrom)
|
||||||
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
|
bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv, int64_t nTimeReceived)
|
||||||
{
|
{
|
||||||
RandAddSeedPerfmon();
|
RandAddSeedPerfmon();
|
||||||
LogPrint("net", "received: %s (%u bytes) peer=%d\n", strCommand, vRecv.size(), pfrom->id);
|
LogPrint("net", "received: %s (%u bytes) peer=%d\n", SanitizeString(strCommand), vRecv.size(), pfrom->id);
|
||||||
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
|
if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
|
||||||
{
|
{
|
||||||
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
|
LogPrintf("dropmessagestest DROPPING RECV MESSAGE\n");
|
||||||
|
@ -4374,7 +4388,7 @@ bool ProcessMessages(CNode* pfrom)
|
||||||
|
|
||||||
// Scan for message start
|
// Scan for message start
|
||||||
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
|
if (memcmp(msg.hdr.pchMessageStart, Params().MessageStart(), MESSAGE_START_SIZE) != 0) {
|
||||||
LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", msg.hdr.GetCommand(), pfrom->id);
|
LogPrintf("PROCESSMESSAGE: INVALID MESSAGESTART %s peer=%d\n", SanitizeString(msg.hdr.GetCommand()), pfrom->id);
|
||||||
fOk = false;
|
fOk = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4383,7 +4397,7 @@ bool ProcessMessages(CNode* pfrom)
|
||||||
CMessageHeader& hdr = msg.hdr;
|
CMessageHeader& hdr = msg.hdr;
|
||||||
if (!hdr.IsValid())
|
if (!hdr.IsValid())
|
||||||
{
|
{
|
||||||
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", hdr.GetCommand(), pfrom->id);
|
LogPrintf("PROCESSMESSAGE: ERRORS IN HEADER %s peer=%d\n", SanitizeString(hdr.GetCommand()), pfrom->id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
string strCommand = hdr.GetCommand();
|
string strCommand = hdr.GetCommand();
|
||||||
|
@ -4399,7 +4413,7 @@ bool ProcessMessages(CNode* pfrom)
|
||||||
if (nChecksum != hdr.nChecksum)
|
if (nChecksum != hdr.nChecksum)
|
||||||
{
|
{
|
||||||
LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
|
LogPrintf("ProcessMessages(%s, %u bytes): CHECKSUM ERROR nChecksum=%08x hdr.nChecksum=%08x\n",
|
||||||
strCommand, nMessageSize, nChecksum, hdr.nChecksum);
|
SanitizeString(strCommand), nMessageSize, nChecksum, hdr.nChecksum);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4416,12 +4430,12 @@ bool ProcessMessages(CNode* pfrom)
|
||||||
if (strstr(e.what(), "end of data"))
|
if (strstr(e.what(), "end of data"))
|
||||||
{
|
{
|
||||||
// Allow exceptions from under-length message on vRecv
|
// Allow exceptions from under-length message on vRecv
|
||||||
LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand, nMessageSize, e.what());
|
LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught, normally caused by a message being shorter than its stated length\n", SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
}
|
}
|
||||||
else if (strstr(e.what(), "size too large"))
|
else if (strstr(e.what(), "size too large"))
|
||||||
{
|
{
|
||||||
// Allow exceptions from over-long size
|
// Allow exceptions from over-long size
|
||||||
LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught\n", strCommand, nMessageSize, e.what());
|
LogPrintf("ProcessMessages(%s, %u bytes): Exception '%s' caught\n", SanitizeString(strCommand), nMessageSize, e.what());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4438,7 +4452,7 @@ bool ProcessMessages(CNode* pfrom)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fRet)
|
if (!fRet)
|
||||||
LogPrintf("ProcessMessage(%s, %u bytes) FAILED peer=%d\n", strCommand, nMessageSize, pfrom->id);
|
LogPrintf("ProcessMessage(%s, %u bytes) FAILED peer=%d\n", SanitizeString(strCommand), nMessageSize, pfrom->id);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1971,7 +1971,7 @@ void CNode::BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSen
|
||||||
ENTER_CRITICAL_SECTION(cs_vSend);
|
ENTER_CRITICAL_SECTION(cs_vSend);
|
||||||
assert(ssSend.size() == 0);
|
assert(ssSend.size() == 0);
|
||||||
ssSend << CMessageHeader(pszCommand, 0);
|
ssSend << CMessageHeader(pszCommand, 0);
|
||||||
LogPrint("net", "sending: %s ", pszCommand);
|
LogPrint("net", "sending: %s ", SanitizeString(pszCommand));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
|
void CNode::AbortMessage() UNLOCK_FUNCTION(cs_vSend)
|
||||||
|
|
|
@ -14,6 +14,69 @@
|
||||||
<string notr="true">Bitcoin Core - Command-line options</string>
|
<string notr="true">Bitcoin Core - Command-line options</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayoutLogo" stretch="0,0">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="aboutLogo">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Ignored">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>100</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="pixmap">
|
||||||
|
<pixmap resource="../bitcoin.qrc">:/icons/bitcoin</pixmap>
|
||||||
|
</property>
|
||||||
|
<property name="scaledContents">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QFrame" name="frame">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
|
@ -25,6 +88,9 @@
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QScrollArea" name="scrollArea">
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
<property name="verticalScrollBarPolicy">
|
<property name="verticalScrollBarPolicy">
|
||||||
<enum>Qt::ScrollBarAlwaysOn</enum>
|
<enum>Qt::ScrollBarAlwaysOn</enum>
|
||||||
</property>
|
</property>
|
||||||
|
@ -56,6 +122,22 @@
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>4</width>
|
||||||
|
<height>4</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="okButton">
|
<widget class="QDialogButtonBox" name="okButton">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -569,6 +569,14 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bitcoin amounts are stored as (optional) uint64 in the protobuf messages (see paymentrequest.proto),
|
||||||
|
// but CAmount is defined as int64_t. Because of that we need to verify that amounts are in a valid range
|
||||||
|
// and no overflow has happened.
|
||||||
|
if (!verifyAmount(sendingTo.second)) {
|
||||||
|
emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Extract and check amounts
|
// Extract and check amounts
|
||||||
CTxOut txOut(sendingTo.second, sendingTo.first);
|
CTxOut txOut(sendingTo.second, sendingTo.first);
|
||||||
if (txOut.IsDust(::minRelayTxFee)) {
|
if (txOut.IsDust(::minRelayTxFee)) {
|
||||||
|
@ -580,6 +588,11 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins
|
||||||
}
|
}
|
||||||
|
|
||||||
recipient.amount += sendingTo.second;
|
recipient.amount += sendingTo.second;
|
||||||
|
// Also verify that the final amount is still in a valid range after adding additional amounts.
|
||||||
|
if (!verifyAmount(recipient.amount)) {
|
||||||
|
emit message(tr("Payment request rejected"), tr("Invalid payment request."), CClientUIInterface::MSG_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Store addresses and format them to fit nicely into the GUI
|
// Store addresses and format them to fit nicely into the GUI
|
||||||
recipient.address = addresses.join("<br />");
|
recipient.address = addresses.join("<br />");
|
||||||
|
@ -768,3 +781,15 @@ bool PaymentServer::verifyExpired(const payments::PaymentDetails& requestDetails
|
||||||
}
|
}
|
||||||
return fVerified;
|
return fVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PaymentServer::verifyAmount(const CAmount& requestAmount)
|
||||||
|
{
|
||||||
|
bool fVerified = MoneyRange(requestAmount);
|
||||||
|
if (!fVerified) {
|
||||||
|
qWarning() << QString("PaymentServer::%1: Payment request amount out of allowed range (%2, allowed 0 - %3).")
|
||||||
|
.arg(__func__)
|
||||||
|
.arg(requestAmount)
|
||||||
|
.arg(MAX_MONEY);
|
||||||
|
}
|
||||||
|
return fVerified;
|
||||||
|
}
|
||||||
|
|
|
@ -95,6 +95,8 @@ public:
|
||||||
static bool verifyNetwork(const payments::PaymentDetails& requestDetails);
|
static bool verifyNetwork(const payments::PaymentDetails& requestDetails);
|
||||||
// Verify if the payment request is expired
|
// Verify if the payment request is expired
|
||||||
static bool verifyExpired(const payments::PaymentDetails& requestDetails);
|
static bool verifyExpired(const payments::PaymentDetails& requestDetails);
|
||||||
|
// Verify the payment request amount is valid
|
||||||
|
static bool verifyAmount(const CAmount& requestAmount);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// Fired when a valid payment request is received
|
// Fired when a valid payment request is received
|
||||||
|
|
|
@ -433,3 +433,28 @@ dGluZyB0ZXN0bmV0ISqAAXSQG8+GFA18VaKarlYrOz293rNMIub0swKGcQm8jAGX\
|
||||||
HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\
|
HSLaRgHfUDeEPr4hydy4dtfu59KNwe2xsHOHu/SpO4L8SrA4Dm9A7SlNBVWdcLbw\
|
||||||
d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\
|
d2hj739GDLz0b5KuJ2SG6VknMRQM976w/m2qlq0ccVGaaZ2zMIGfpzL3p6adwx/5\
|
||||||
";
|
";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Payment request with amount overflow (amount is set to 21000001 BTC)
|
||||||
|
//
|
||||||
|
const char* paymentrequest5_cert2_BASE64 =
|
||||||
|
"\
|
||||||
|
Egt4NTA5K3NoYTI1NhrQBArNBDCCAkkwggExoAMCAQICAQEwDQYJKoZIhvcNAQEL\
|
||||||
|
BQAwITEfMB0GA1UEAwwWUGF5bWVudFJlcXVlc3QgVGVzdCBDQTAeFw0xNTAxMTEx\
|
||||||
|
ODIxMDhaFw0yNTAxMDgxODIxMDhaMCExHzAdBgNVBAMMFlBheW1lbnRSZXF1ZXN0\
|
||||||
|
IFRlc3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMsZqzkzeBGo+i2N\
|
||||||
|
mUak3Ciodr1V7S062VOy7N0OQYNDQHYkgDFAUET7cEb5VJaHPv5m3ppTBpU9xBcf\
|
||||||
|
wbHHUt4VjA+mhRmYrl1khjvZM+X8kEqvWn20BtcM9R6r0yIYec8UERDDHBleL/P8\
|
||||||
|
RkxEnVLjYTV9zigCXfMsgYb3EQShAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJ\
|
||||||
|
KoZIhvcNAQELBQADggEBABUJpl3QCqsoDSxAsQdV6zKT4VGV76AzoGj7etQsQY+r\
|
||||||
|
+S26VfWh/fMobEzuxFChr0USgLJ6FoK78hAtoZvt1lrye9yqFv/ig3WLWsJKWHHb\
|
||||||
|
3RT6oR03CIwZXFSUasi08QDVLxafwsU5OMcPLucF3a1lRL1ccYrNgVCCx1+X7Bos\
|
||||||
|
tIgDGRQQ4AyoHTcfVd2hEGeUv7k14mOxFsAp6851yosHq9Q2kwmdH+rHEJbjof87\
|
||||||
|
yyKLagc4owyXBZYkQmkeHWCNqnuRmO5vUsfVb0UUrkD64o7Th/NjwooA7SCiUXl6\
|
||||||
|
dfygT1b7ggpx7GC+sP2DsIM47IAZ55drjqX5u2f+Ba0iTAoEdGVzdBIkCIDC9P+F\
|
||||||
|
vt0DEhl2qRQErGqUUwSsaMpDvWIaGnJGNQqi8oisGLzcrKYFKhhUZXN0aW5nIGFt\
|
||||||
|
b3VudCBvdmVyZmxvdyEqgAG8S7WEDUC6tCL6q2CTBjop/AitgEy31RL9IqYruytR\
|
||||||
|
iEBFUrBDJZU+UEezGwr7/zoECjo5ZY3PmtZcM2sILNjyweJF6XVzGqTxUw6pN6sW\
|
||||||
|
XR2T3Gy2LzRvhVA25QgGqpz0/juS2BtmNbsZPkN9gMMwKimgzc+PuCzmEKwPK9cQ\
|
||||||
|
YQ==\
|
||||||
|
";
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
#include "optionsmodel.h"
|
#include "optionsmodel.h"
|
||||||
#include "paymentrequestdata.h"
|
#include "paymentrequestdata.h"
|
||||||
|
|
||||||
|
#include "amount.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
|
#include "script/script.h"
|
||||||
|
#include "script/standard.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "utilstrencodings.h"
|
||||||
|
|
||||||
|
@ -184,6 +187,20 @@ void PaymentServerTests::paymentServerTests()
|
||||||
tempFile.close();
|
tempFile.close();
|
||||||
QCOMPARE(PaymentServer::readPaymentRequestFromFile(tempFile.fileName(), r.paymentRequest), false);
|
QCOMPARE(PaymentServer::readPaymentRequestFromFile(tempFile.fileName(), r.paymentRequest), false);
|
||||||
|
|
||||||
|
// Payment request with amount overflow (amount is set to 21000001 BTC):
|
||||||
|
data = DecodeBase64(paymentrequest5_cert2_BASE64);
|
||||||
|
byteArray = QByteArray((const char*)&data[0], data.size());
|
||||||
|
r.paymentRequest.parse(byteArray);
|
||||||
|
// Ensure the request is initialized
|
||||||
|
QVERIFY(r.paymentRequest.IsInitialized());
|
||||||
|
// Extract address and amount from the request
|
||||||
|
QList<std::pair<CScript, CAmount> > sendingTos = r.paymentRequest.getPayTo();
|
||||||
|
foreach (const PAIRTYPE(CScript, CAmount)& sendingTo, sendingTos) {
|
||||||
|
CTxDestination dest;
|
||||||
|
if (ExtractDestination(sendingTo.first, dest))
|
||||||
|
QCOMPARE(PaymentServer::verifyAmount(sendingTo.second), false);
|
||||||
|
}
|
||||||
|
|
||||||
delete server;
|
delete server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,6 +137,7 @@ HelpMessageDialog::HelpMessageDialog(QWidget *parent, bool about) :
|
||||||
|
|
||||||
ui->helpMessage->moveCursor(QTextCursor::Start);
|
ui->helpMessage->moveCursor(QTextCursor::Start);
|
||||||
ui->scrollArea->setVisible(false);
|
ui->scrollArea->setVisible(false);
|
||||||
|
ui->aboutLogo->setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ Value GetNetworkHashPS(int lookup, int height) {
|
||||||
|
|
||||||
// If lookup is -1, then use blocks since last difficulty change.
|
// If lookup is -1, then use blocks since last difficulty change.
|
||||||
if (lookup <= 0)
|
if (lookup <= 0)
|
||||||
lookup = pb->nHeight % 2016 + 1;
|
lookup = pb->nHeight % Params().Interval() + 1;
|
||||||
|
|
||||||
// If lookup is larger than chain, then set it to chain length.
|
// If lookup is larger than chain, then set it to chain length.
|
||||||
if (lookup > pb->nHeight)
|
if (lookup > pb->nHeight)
|
||||||
|
|
|
@ -857,7 +857,7 @@ void JSONRequest::parse(const Value& valRequest)
|
||||||
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
|
throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
|
||||||
strMethod = valMethod.get_str();
|
strMethod = valMethod.get_str();
|
||||||
if (strMethod != "getblocktemplate")
|
if (strMethod != "getblocktemplate")
|
||||||
LogPrint("rpc", "ThreadRPCServer method=%s\n", strMethod);
|
LogPrint("rpc", "ThreadRPCServer method=%s\n", SanitizeString(strMethod));
|
||||||
|
|
||||||
// Parse params
|
// Parse params
|
||||||
Value valParams = find_value(request, "params");
|
Value valParams = find_value(request, "params");
|
||||||
|
|
Loading…
Reference in a new issue