void deallocate(void *p, size_type n)
{
- assert(false);
+ //// Bitcoin: can't figure out why this is tripping on a few compiles.
+ //assert(false);
}
size_type max_size() const {return 0;}
mapFileUseCount.erase(strFile);
// Copy wallet.dat
+ filesystem::path pathSrc(GetDataDir() + "/" + strFile);
filesystem::path pathDest(strDest);
if (filesystem::is_directory(pathDest))
pathDest = pathDest / strFile;
- filesystem::copy_file(filesystem::path(GetDataDir() + "/" + strFile), pathDest, filesystem::copy_option::overwrite_if_exists);
+#if BOOST_VERSION >= 104000
+ filesystem::copy_file(pathSrc, pathDest, filesystem::copy_option::overwrite_if_exists);
+#else
+ filesystem::copy_file(pathSrc, pathDest);
+#endif
printf("copied wallet.dat to %s\n", pathDest.string().c_str());
return;
if (!strErrors.empty())
{
- wxMessageBox(strErrors, "Bitcoin");
+ wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
return false;
}
return false;
}
if (nTransactionFee > 1 * COIN)
- wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin");
+ wxMessageBox(_("Warning: -paytxfee is set very high. This is the transaction fee you will pay if you send a transaction."), "Bitcoin", wxOK | wxICON_EXCLAMATION);
}
//
int nGotIRCAddresses = 0;
+void ThreadIRCSeed2(void* parg);
+
+
#pragma pack(push, 1)
loop
{
string strLine;
+ strLine.reserve(10000);
if (!RecvLineIRC(hSocket, strLine))
return 0;
printf("IRC %s\n", strLine.c_str());
void ThreadIRCSeed(void* parg)
{
+ IMPLEMENT_RANDOMIZE_STACK(ThreadIRCSeed(parg));
+ try
+ {
+ ThreadIRCSeed2(parg);
+ }
+ catch (std::exception& e) {
+ PrintExceptionContinue(&e, "ThreadIRCSeed()");
+ } catch (...) {
+ PrintExceptionContinue(NULL, "ThreadIRCSeed()");
+ }
+ printf("ThreadIRCSeed exiting\n");
+}
+
+void ThreadIRCSeed2(void* parg)
+{
if (mapArgs.count("-connect"))
return;
if (mapArgs.count("-noirc"))
int64 nStart = GetTime();
string strLine;
+ strLine.reserve(10000);
while (!fShutdown && RecvLineIRC(hSocket, strLine))
{
if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')
CKey key;
key.MakeNewKey();
if (!AddKey(key))
- throw runtime_error("GenerateNewKey() : AddKey failed\n");
+ throw runtime_error("GenerateNewKey() : AddKey failed");
return key.GetPubKey();
}
-bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
+bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
{
if (pfMissingInputs)
*pfMissingInputs = false;
// Coinbase is only valid in a block, not as a loose transaction
if (IsCoinBase())
- return error("AcceptTransaction() : coinbase as individual tx");
+ return error("AcceptToMemoryPool() : coinbase as individual tx");
if (!CheckTransaction())
- return error("AcceptTransaction() : CheckTransaction failed");
+ return error("AcceptToMemoryPool() : CheckTransaction failed");
// To help v0.1.5 clients who would see it as a negative number
if ((int64)nLockTime > INT_MAX)
- return error("AcceptTransaction() : not accepting nLockTime beyond 2038 yet");
+ return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet");
+
+ // Rather not work on nonstandard transactions
+ if (GetSigOpCount() > 2 || ::GetSerializeSize(*this, SER_NETWORK) < 100)
+ return error("AcceptToMemoryPool() : nonstandard transaction");
// Do we already have it?
uint256 hash = GetHash();
{
if (pfMissingInputs)
*pfMissingInputs = true;
- return error("AcceptTransaction() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
+ return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,6).c_str());
}
// Store transaction in memory
{
if (ptxOld)
{
- printf("AcceptTransaction() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
+ printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
ptxOld->RemoveFromMemoryPool();
}
- AddToMemoryPool();
+ AddToMemoryPoolUnchecked();
}
///// are we sure this is ok when loading transactions or restoring block txes
if (ptxOld)
EraseFromWallet(ptxOld->GetHash());
- printf("AcceptTransaction(): accepted %s\n", hash.ToString().substr(0,6).c_str());
+ printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,6).c_str());
return true;
}
-bool CTransaction::AddToMemoryPool()
+bool CTransaction::AddToMemoryPoolUnchecked()
{
// Add to memory pool without checking anything. Don't call this directly,
- // call AcceptTransaction to properly check the transaction first.
+ // call AcceptToMemoryPool to properly check the transaction first.
CRITICAL_BLOCK(cs_mapTransactions)
{
uint256 hash = GetHash();
}
-bool CMerkleTx::AcceptTransaction(CTxDB& txdb, bool fCheckInputs)
+bool CMerkleTx::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs)
{
if (fClient)
{
if (!IsInMainChain() && !ClientConnectInputs())
return false;
- return CTransaction::AcceptTransaction(txdb, false);
+ return CTransaction::AcceptToMemoryPool(txdb, false);
}
else
{
- return CTransaction::AcceptTransaction(txdb, fCheckInputs);
+ return CTransaction::AcceptToMemoryPool(txdb, fCheckInputs);
}
}
{
CRITICAL_BLOCK(cs_mapTransactions)
{
+ // Add previous supporting transactions first
foreach(CMerkleTx& tx, vtxPrev)
{
if (!tx.IsCoinBase())
{
uint256 hash = tx.GetHash();
if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
- tx.AcceptTransaction(txdb, fCheckInputs);
+ tx.AcceptToMemoryPool(txdb, fCheckInputs);
}
}
- if (!IsCoinBase())
- return AcceptTransaction(txdb, fCheckInputs);
+ return AcceptToMemoryPool(txdb, fCheckInputs);
}
- return true;
+ return false;
}
void ReacceptWalletTransactions()
if (nTxFee < nMinFee)
return false;
nFees += nTxFee;
+ if (!MoneyRange(nFees))
+ return error("ConnectInputs() : nFees out of range");
}
if (fBlock)
// txPrev.vout[prevout.n].posNext = posThisTx;
nValueIn += txPrev.vout[prevout.n].nValue;
+
+ if (!MoneyRange(txPrev.vout[prevout.n].nValue) || !MoneyRange(nValueIn))
+ return error("ClientConnectInputs() : txin values out of range");
}
if (GetValueOut() > nValueIn)
return false;
// Resurrect memory transactions that were in the disconnected branch
foreach(CTransaction& tx, vResurrect)
- tx.AcceptTransaction(txdb, false);
+ tx.AcceptToMemoryPool(txdb, false);
// Delete redundant memory transactions that are in the connected branch
foreach(CTransaction& tx, vDelete)
// that can be verified before saving an orphan block.
// Size limits
- if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
+ if (vtx.empty() || vtx.size() > MAX_SIZE || ::GetSerializeSize(*this, SER_NETWORK) > MAX_SIZE)
return error("CheckBlock() : size limits failed");
// Check timestamp
if (mi == mapBlockIndex.end())
return error("AcceptBlock() : prev block not found");
CBlockIndex* pindexPrev = (*mi).second;
+ int nHeight = pindexPrev->nHeight+1;
+
+ // Check size
+ if (nHeight > 79400 && ::GetSerializeSize(*this, SER_NETWORK) > MAX_BLOCK_SIZE)
+ return error("AcceptBlock() : over size limit");
+
+ // Check that it's not full of nonstandard transactions
+ if (nHeight > 79400 && GetSigOpCount() > MAX_BLOCK_SIGOPS)
+ return error("AcceptBlock() : too many nonstandard transactions");
// Check timestamp against prev
if (GetBlockTime() <= pindexPrev->GetMedianTimePast())
// Check that all transactions are finalized
foreach(const CTransaction& tx, vtx)
- if (!tx.IsFinal(pindexPrev->nHeight+1, GetBlockTime()))
+ if (!tx.IsFinal(nHeight, GetBlockTime()))
return error("AcceptBlock() : contains a non-final transaction");
// Check proof of work
return error("AcceptBlock() : incorrect proof of work");
// Check that the block chain matches the known block chain up to a checkpoint
- if ((pindexPrev->nHeight+1 == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
- (pindexPrev->nHeight+1 == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
- (pindexPrev->nHeight+1 == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
- (pindexPrev->nHeight+1 == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
- (pindexPrev->nHeight+1 == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
- return error("AcceptBlock() : rejected by checkpoint lockin at %d", pindexPrev->nHeight+1);
+ if ((nHeight == 11111 && hash != uint256("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")) ||
+ (nHeight == 33333 && hash != uint256("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")) ||
+ (nHeight == 68555 && hash != uint256("0x00000000001e1b4903550a0b96e9a9405c8a95f387162e4944e8d9fbe501cd6a")) ||
+ (nHeight == 70567 && hash != uint256("0x00000000006a49b14bcf27462068f1264c961f11fa2e0eddd2be0791e1d4124a")) ||
+ (nHeight == 74000 && hash != uint256("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")))
+ return error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight);
// Scanback checkpoint lockin
for (CBlockIndex* pindex = pindexPrev; pindex->nHeight >= 74000; pindex = pindex->pprev)
}
else
{
- PrintException(&e, "ProcessMessage()");
+ PrintExceptionContinue(&e, "ProcessMessage()");
}
}
catch (std::exception& e) {
- PrintException(&e, "ProcessMessage()");
+ PrintExceptionContinue(&e, "ProcessMessage()");
} catch (...) {
- PrintException(NULL, "ProcessMessage()");
+ PrintExceptionContinue(NULL, "ProcessMessage()");
}
if (!fRet)
multimap<uint256, CNode*> mapMix;
foreach(CNode* pnode, vNodes)
mapMix.insert(make_pair(hashRand = Hash(BEGIN(hashRand), END(hashRand)), pnode));
- int nRelayNodes = 4;
+ int nRelayNodes = 2;
for (multimap<uint256, CNode*>::iterator mi = mapMix.begin(); mi != mapMix.end() && nRelayNodes-- > 0; ++mi)
((*mi).second)->PushAddress(addr);
}
pfrom->AddInventoryKnown(inv);
bool fMissingInputs = false;
- if (tx.AcceptTransaction(true, &fMissingInputs))
+ if (tx.AcceptToMemoryPool(true, &fMissingInputs))
{
AddToWalletIfMine(tx, NULL);
RelayMessage(inv, vMsg);
CDataStream(vMsg) >> tx;
CInv inv(MSG_TX, tx.GetHash());
- if (tx.AcceptTransaction(true))
+ if (tx.AcceptToMemoryPool(true))
{
printf(" accepted orphan tx %s\n", inv.hash.ToString().substr(0,6).c_str());
AddToWalletIfMine(tx, NULL);
map<uint256, CTxIndex> mapTestPool;
vector<char> vfAlreadyAdded(mapTransactions.size());
bool fFoundSomething = true;
- uint64 nBlockSize = 0;
- while (fFoundSomething && nBlockSize < MAX_SIZE/2)
+ uint64 nBlockSize = 10000;
+ int nBlockSigOps = 100;
+ while (fFoundSomething)
{
fFoundSomething = false;
unsigned int n = 0;
if (tx.IsCoinBase() || !tx.IsFinal())
continue;
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK);
- if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE - 10000)
+ if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE)
+ continue;
+ int nTxSigOps = tx.GetSigOpCount();
+ if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
// Transaction fee based on block size
pblock->vtx.push_back(tx);
nBlockSize += nTxSize;
+ nBlockSigOps += nTxSigOps;
vfAlreadyAdded[n] = true;
fFoundSomething = true;
}
// Add the change's private key to wallet
if (!key.IsNull() && !AddKey(key))
- throw runtime_error("CommitTransaction() : AddKey failed\n");
+ throw runtime_error("CommitTransaction() : AddKey failed");
// Add tx to wallet, because if it has change it's also ours,
// otherwise just for transaction history.
mapRequestCount[wtxNew.GetHash()] = 0;
// Broadcast
- if (!wtxNew.AcceptTransaction())
+ if (!wtxNew.AcceptToMemoryPool())
{
// This must not fail. The transaction has already been signed and recorded.
printf("CommitTransaction() : Error: Transaction not valid");
class CKeyItem;
static const unsigned int MAX_BLOCK_SIZE = 1000000;
+static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
static const int64 COIN = 100000000;
static const int64 CENT = 1000000;
static const int64 MAX_MONEY = 21000000 * COIN;
str += strprintf("CTxIn(");
str += prevout.ToString();
if (prevout.IsNull())
- str += strprintf(", coinbase %s", HexStr(scriptSig.begin(), scriptSig.end(), false).c_str());
+ str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
else
str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
if (nSequence != UINT_MAX)
return error("CTransaction::CheckTransaction() : vin or vout empty");
// Size limits
- if (::GetSerializeSize(*this, SER_DISK) > MAX_SIZE)
+ if (::GetSerializeSize(*this, SER_NETWORK) > MAX_SIZE)
return error("CTransaction::CheckTransaction() : size limits failed");
// Check for negative or overflow output values
return true;
}
+ int GetSigOpCount() const
+ {
+ int n = 0;
+ foreach(const CTxIn& txin, vin)
+ n += txin.scriptSig.GetSigOpCount();
+ foreach(const CTxOut& txout, vout)
+ n += txout.scriptPubKey.GetSigOpCount();
+ return n;
+ }
+
bool IsMine() const
{
foreach(const CTxOut& txout, vout)
if (txout.nValue < CENT)
nMinFee = CENT;
+ // Raise the price as the block approaches full
+ if (MAX_BLOCK_SIZE/2 <= nBlockSize && nBlockSize < MAX_BLOCK_SIZE)
+ nMinFee *= MAX_BLOCK_SIZE / (MAX_BLOCK_SIZE - nBlockSize);
+ if (!MoneyRange(nMinFee))
+ nMinFee = MAX_MONEY;
+
return nMinFee;
}
-
bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
{
CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
bool ClientConnectInputs();
- bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
+ bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
- bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
+ bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
{
CTxDB txdb("r");
- return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs);
+ return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
}
protected:
- bool AddToMemoryPool();
+ bool AddToMemoryPoolUnchecked();
public:
bool RemoveFromMemoryPool();
};
int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
int GetBlocksToMaturity() const;
- bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);
- bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); }
+ bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
+ bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); }
};
friend bool operator==(const CTxIndex& a, const CTxIndex& b)
{
- if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size())
- return false;
- for (int i = 0; i < a.vSpent.size(); i++)
- if (a.vSpent[i] != b.vSpent[i])
- return false;
- return true;
+ return (a.pos == b.pos &&
+ a.vSpent == b.vSpent);
}
friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
return (int64)nTime;
}
+ int GetSigOpCount() const
+ {
+ int n = 0;
+ foreach(const CTransaction& tx, vtx)
+ n += tx.GetSigOpCount();
+ return n;
+ }
+
uint256 BuildMerkleTree() const
{
-I"/usr/local/include/wx-2.9" \
-I"/usr/local/lib/wx/include/gtk2-unicode-debug-static-2.9"
+# for wxWidgets 2.9.1, add -l Xxf86vm
WXLIBS= \
-Wl,-Bstatic \
-l wx_gtk2ud-2.9 \
-Wl,-Bdynamic \
- -l gtk-x11-2.0 -l SM
+ -l gtk-x11-2.0 \
+ -l SM
# for boost 1.37, add -mt to the boost libraries
LIBS= \
uint64 nLocalHostNonce = 0;
array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
-int64 nThreadSocketHandlerHeartbeat = INT64_MAX;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
pnode->Release();
}
- nThreadSocketHandlerHeartbeat = GetTime();
Sleep(10);
}
}
// Generate coins in the background
GenerateBitcoins(fGenerateBitcoins);
-
- //
- // Thread monitoring
- // Not really needed anymore, the cause of the hanging was fixed
- //
- loop
- {
- Sleep(1000);
- if (fShutdown)
- return;
- if (GetTime() - nThreadSocketHandlerHeartbeat > 15 * 60)
- {
- // First see if closing sockets will free it
- printf("*** ThreadSocketHandler is stopped ***\n");
- CRITICAL_BLOCK(cs_vNodes)
- {
- foreach(CNode* pnode, vNodes)
- {
- bool fGot = false;
- TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
- TRY_CRITICAL_BLOCK(pnode->cs_vSend)
- fGot = true;
- if (!fGot)
- {
- printf("*** closing socket\n");
- pnode->CloseSocketDisconnect();
- }
- }
- }
- Sleep(10000);
- if (fShutdown)
- return;
- if (GetTime() - nThreadSocketHandlerHeartbeat < 60)
- continue;
-
- // Hopefully it never comes to this.
- // We know it'll always be hung in the recv or send call.
- // cs_vRecv or cs_vSend may be left permanently unreleased,
- // but we always only use TRY_CRITICAL_SECTION on them.
- printf("*** Restarting ThreadSocketHandler ***\n");
- TerminateThread(hThreadSocketHandler, 0);
- #ifdef __WXMSW__
- CloseHandle(hThreadSocketHandler);
- #endif
- vnThreadsRunning[0] = 0;
-
- // Restart
- hThreadSocketHandler = CreateThread(ThreadSocketHandler, NULL, true);
- nThreadSocketHandlerHeartbeat = GetTime();
- }
- }
}
bool StopNode()
}
// Message size
- if (nMessageSize > 0x10000000)
+ if (nMessageSize > MAX_SIZE)
{
- printf("CMessageHeader::IsValid() : nMessageSize too large %u\n", nMessageSize);
+ printf("CMessageHeader::IsValid() : (%s, %u bytes) nMessageSize > MAX_SIZE\n", GetCommand().c_str(), nMessageSize);
return false;
}
extern uint64 nLocalHostNonce;
extern array<int, 10> vnThreadsRunning;
extern SOCKET hListenSocket;
-extern int64 nThreadSocketHandlerHeartbeat;
extern vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;
//
#define stacktop(i) (stack.at(stack.size()+(i)))
#define altstacktop(i) (altstack.at(altstack.size()+(i)))
+static inline void popstack(vector<valtype>& stack)
+{
+ if (stack.empty())
+ throw runtime_error("popstack() : stack empty");
+ stack.pop_back();
+}
+
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, const CTransaction& txTo, unsigned int nIn, int nHashType)
{
CScript::const_iterator pc = script.begin();
CScript::const_iterator pend = script.end();
CScript::const_iterator pbegincodehash = script.begin();
+ opcodetype opcode;
+ valtype vchPushValue;
vector<bool> vfExec;
vector<valtype> altstack;
if (script.size() > 10000)
//
// Read instruction
//
- opcodetype opcode;
- valtype vchPushValue;
if (!script.GetOp(pc, opcode, vchPushValue))
return false;
if (vchPushValue.size() > 520)
return false;
- if (opcode > OP_16 && nOpCount++ > 200)
+ if (opcode > OP_16 && ++nOpCount > 201)
return false;
if (opcode == OP_CAT ||
opcode == OP_RSHIFT)
return false;
- if (fExec && opcode <= OP_PUSHDATA4)
+ if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4)
stack.push_back(vchPushValue);
else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF))
switch (opcode)
case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10:
break;
- case OP_VER:
- case OP_VERIF:
- case OP_VERNOTIF:
- {
- return false;
- }
- break;
-
case OP_IF:
case OP_NOTIF:
{
fValue = CastToBool(vch);
if (opcode == OP_NOTIF)
fValue = !fValue;
- stack.pop_back();
+ popstack(stack);
}
vfExec.push_back(fValue);
}
return false;
bool fValue = CastToBool(stacktop(-1));
if (fValue)
- stack.pop_back();
+ popstack(stack);
else
return false;
}
if (stack.size() < 1)
return false;
altstack.push_back(stacktop(-1));
- stack.pop_back();
+ popstack(stack);
}
break;
if (altstack.size() < 1)
return false;
stack.push_back(altstacktop(-1));
- altstack.pop_back();
+ popstack(altstack);
}
break;
case OP_2DROP:
{
// (x1 x2 -- )
- stack.pop_back();
- stack.pop_back();
+ if (stack.size() < 2)
+ return false;
+ popstack(stack);
+ popstack(stack);
}
break;
// (x -- )
if (stack.size() < 1)
return false;
- stack.pop_back();
+ popstack(stack);
}
break;
if (stack.size() < 2)
return false;
int n = CastToBigNum(stacktop(-1)).getint();
- stack.pop_back();
+ popstack(stack);
if (n < 0 || n >= stack.size())
return false;
valtype vch = stacktop(-n-1);
valtype& vch1 = stacktop(-2);
valtype& vch2 = stacktop(-1);
vch1.insert(vch1.end(), vch2.begin(), vch2.end());
- stack.pop_back();
+ popstack(stack);
if (stacktop(-1).size() > 520)
return false;
}
nEnd = vch.size();
vch.erase(vch.begin() + nEnd, vch.end());
vch.erase(vch.begin(), vch.begin() + nBegin);
- stack.pop_back();
- stack.pop_back();
+ popstack(stack);
+ popstack(stack);
}
break;
vch.erase(vch.begin() + nSize, vch.end());
else
vch.erase(vch.begin(), vch.end() - nSize);
- stack.pop_back();
+ popstack(stack);
}
break;
for (int i = 0; i < vch1.size(); i++)
vch1[i] ^= vch2[i];
}
- stack.pop_back();
+ popstack(stack);
}
break;
// zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001)
//if (opcode == OP_NOTEQUAL)
// fEqual = !fEqual;
- stack.pop_back();
- stack.pop_back();
+ popstack(stack);
+ popstack(stack);
stack.push_back(fEqual ? vchTrue : vchFalse);
if (opcode == OP_EQUALVERIFY)
{
if (fEqual)
- stack.pop_back();
+ popstack(stack);
else
return false;
}
case OP_NOT: bn = (bn == bnZero); break;
case OP_0NOTEQUAL: bn = (bn != bnZero); break;
}
- stack.pop_back();
+ popstack(stack);
stack.push_back(bn.getvch());
}
break;
case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break;
case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break;
}
- stack.pop_back();
- stack.pop_back();
+ popstack(stack);
+ popstack(stack);
stack.push_back(bn.getvch());
if (opcode == OP_NUMEQUALVERIFY)
{
if (CastToBool(stacktop(-1)))
- stack.pop_back();
+ popstack(stack);
else
return false;
}
CBigNum bn2 = CastToBigNum(stacktop(-2));
CBigNum bn3 = CastToBigNum(stacktop(-1));
bool fValue = (bn2 <= bn1 && bn1 < bn3);
- stack.pop_back();
- stack.pop_back();
- stack.pop_back();
+ popstack(stack);
+ popstack(stack);
+ popstack(stack);
stack.push_back(fValue ? vchTrue : vchFalse);
}
break;
uint256 hash = Hash(vch.begin(), vch.end());
memcpy(&vchHash[0], &hash, sizeof(hash));
}
- stack.pop_back();
+ popstack(stack);
stack.push_back(vchHash);
}
break;
bool fSuccess = CheckSig(vchSig, vchPubKey, scriptCode, txTo, nIn, nHashType);
- stack.pop_back();
- stack.pop_back();
+ popstack(stack);
+ popstack(stack);
stack.push_back(fSuccess ? vchTrue : vchFalse);
if (opcode == OP_CHECKSIGVERIFY)
{
if (fSuccess)
- stack.pop_back();
+ popstack(stack);
else
return false;
}
}
while (i-- > 0)
- stack.pop_back();
+ popstack(stack);
stack.push_back(fSuccess ? vchTrue : vchFalse);
if (opcode == OP_CHECKMULTISIGVERIFY)
{
if (fSuccess)
- stack.pop_back();
+ popstack(stack);
else
return false;
}
return true;
}
-#undef top
-
return false;
vchSig.pop_back();
- if (key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig))
- return true;
-
- return false;
+ return key.Verify(SignatureHash(scriptCode, txTo, nIn, nHashType), vchSig);
}
CScript::const_iterator pc2 = script2.begin();
loop
{
- bool f1 = script1.GetOp(pc1, opcode1, vch1);
- bool f2 = script2.GetOp(pc2, opcode2, vch2);
- if (!f1 && !f2)
+ if (pc1 == script1.end() && pc2 == script2.end())
{
- // Success
+ // Found a match
reverse(vSolutionRet.begin(), vSolutionRet.end());
return true;
}
- else if (f1 != f2)
- {
+ if (!script1.GetOp(pc1, opcode1, vch1))
break;
- }
- else if (opcode2 == OP_PUBKEY)
+ if (!script2.GetOp(pc2, opcode2, vch2))
+ break;
+ if (opcode2 == OP_PUBKEY)
{
- if (vch1.size() <= sizeof(uint256))
+ if (vch1.size() < 33)
break;
vSolutionRet.push_back(make_pair(opcode2, vch1));
}
break;
vSolutionRet.push_back(make_pair(opcode2, vch1));
}
- else if (opcode1 != opcode2)
+ else if (opcode1 != opcode2 || vch1 != vch2)
{
break;
}
scriptSigRet << vchSig << vchPubKey;
}
}
+ else
+ {
+ return false;
+ }
}
}
-
- // multi-byte opcodes
- OP_SINGLEBYTE_END = 0xF0,
- OP_DOUBLEBYTE_BEGIN = 0xF000,
-
// template matching params
- OP_PUBKEY,
- OP_PUBKEYHASH,
-
-
+ OP_PUBKEYHASH = 0xfd,
+ OP_PUBKEY = 0xfe,
- OP_INVALIDOPCODE = 0xFFFF,
+ OP_INVALIDOPCODE = 0xff,
};
- // multi-byte opcodes
- case OP_SINGLEBYTE_END : return "OP_SINGLEBYTE_END";
- case OP_DOUBLEBYTE_BEGIN : return "OP_DOUBLEBYTE_BEGIN";
- case OP_PUBKEY : return "OP_PUBKEY";
+ // template matching params
case OP_PUBKEYHASH : return "OP_PUBKEYHASH";
-
+ case OP_PUBKEY : return "OP_PUBKEY";
case OP_INVALIDOPCODE : return "OP_INVALIDOPCODE";
default:
- return "UNKNOWN_OPCODE";
+ return "OP_UNKNOWN";
}
};
if (vch.size() <= 4)
return strprintf("%d", CBigNum(vch).getint());
else
- return HexNumStr(vch.begin(), vch.end());
- //return string("(") + HexStr(vch.begin(), vch.end()) + string(")");
+ return HexStr(vch);
}
inline string StackString(const vector<vector<unsigned char> >& vStack)
CBigNum bn(n);
*this << bn.getvch();
}
- return (*this);
+ return *this;
}
CScript& push_uint64(uint64 n)
{
- if (n == -1 || (n >= 1 && n <= 16))
+ if (n >= 1 && n <= 16)
{
push_back(n + (OP_1 - 1));
}
CBigNum bn(n);
*this << bn.getvch();
}
- return (*this);
+ return *this;
}
public:
{
CScript ret = a;
ret += b;
- return (ret);
+ return ret;
}
explicit CScript(const vector<unsigned char>& b) { operator<<(b); }
- CScript& operator<<(char b) { return (push_int64(b)); }
- CScript& operator<<(short b) { return (push_int64(b)); }
- CScript& operator<<(int b) { return (push_int64(b)); }
- CScript& operator<<(long b) { return (push_int64(b)); }
- CScript& operator<<(int64 b) { return (push_int64(b)); }
- CScript& operator<<(unsigned char b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned int b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned short b) { return (push_uint64(b)); }
- CScript& operator<<(unsigned long b) { return (push_uint64(b)); }
- CScript& operator<<(uint64 b) { return (push_uint64(b)); }
+ CScript& operator<<(char b) { return push_int64(b); }
+ CScript& operator<<(short b) { return push_int64(b); }
+ CScript& operator<<(int b) { return push_int64(b); }
+ CScript& operator<<(long b) { return push_int64(b); }
+ CScript& operator<<(int64 b) { return push_int64(b); }
+ CScript& operator<<(unsigned char b) { return push_uint64(b); }
+ CScript& operator<<(unsigned int b) { return push_uint64(b); }
+ CScript& operator<<(unsigned short b) { return push_uint64(b); }
+ CScript& operator<<(unsigned long b) { return push_uint64(b); }
+ CScript& operator<<(uint64 b) { return push_uint64(b); }
CScript& operator<<(opcodetype opcode)
{
- if (opcode <= OP_SINGLEBYTE_END)
- {
- insert(end(), (unsigned char)opcode);
- }
- else
- {
- assert(opcode >= OP_DOUBLEBYTE_BEGIN);
- insert(end(), (unsigned char)(opcode >> 8));
- insert(end(), (unsigned char)(opcode & 0xFF));
- }
- return (*this);
+ if (opcode < 0 || opcode > 0xff)
+ throw runtime_error("CScript::operator<<() : invalid opcode");
+ insert(end(), (unsigned char)opcode);
+ return *this;
}
CScript& operator<<(const uint160& b)
{
insert(end(), sizeof(b));
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
- return (*this);
+ return *this;
}
CScript& operator<<(const uint256& b)
{
insert(end(), sizeof(b));
insert(end(), (unsigned char*)&b, (unsigned char*)&b + sizeof(b));
- return (*this);
+ return *this;
}
CScript& operator<<(const CBigNum& b)
{
*this << b.getvch();
- return (*this);
+ return *this;
}
CScript& operator<<(const vector<unsigned char>& b)
insert(end(), OP_PUSHDATA1);
insert(end(), (unsigned char)b.size());
}
- else
+ else if (b.size() <= 0xffff)
{
insert(end(), OP_PUSHDATA2);
unsigned short nSize = b.size();
insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
}
+ else
+ {
+ insert(end(), OP_PUSHDATA4);
+ unsigned int nSize = b.size();
+ insert(end(), (unsigned char*)&nSize, (unsigned char*)&nSize + sizeof(nSize));
+ }
insert(end(), b.begin(), b.end());
- return (*this);
+ return *this;
}
CScript& operator<<(const CScript& b)
// I'm not sure if this should push the script or concatenate scripts.
// If there's ever a use for pushing a script onto a script, delete this member fn
assert(("warning: pushing a CScript onto a CScript with << is probably not intended, use + to concatenate", false));
- return (*this);
+ return *this;
}
{
// Wrapper so it can be called with either iterator or const_iterator
const_iterator pc2 = pc;
- bool fRet = GetOp(pc2, opcodeRet, vchRet);
+ bool fRet = GetOp2(pc2, opcodeRet, &vchRet);
+ pc = begin() + (pc2 - begin());
+ return fRet;
+ }
+
+ bool GetOp(iterator& pc, opcodetype& opcodeRet)
+ {
+ const_iterator pc2 = pc;
+ bool fRet = GetOp2(pc2, opcodeRet, NULL);
pc = begin() + (pc2 - begin());
return fRet;
}
bool GetOp(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>& vchRet) const
{
+ return GetOp2(pc, opcodeRet, &vchRet);
+ }
+
+ bool GetOp(const_iterator& pc, opcodetype& opcodeRet) const
+ {
+ return GetOp2(pc, opcodeRet, NULL);
+ }
+
+ bool GetOp2(const_iterator& pc, opcodetype& opcodeRet, vector<unsigned char>* pvchRet) const
+ {
opcodeRet = OP_INVALIDOPCODE;
- vchRet.clear();
+ if (pvchRet)
+ pvchRet->clear();
if (pc >= end())
return false;
// Read instruction
+ if (end() - pc < 1)
+ return false;
unsigned int opcode = *pc++;
- if (opcode >= OP_SINGLEBYTE_END)
- {
- if (pc + 1 > end())
- return false;
- opcode <<= 8;
- opcode |= *pc++;
- }
// Immediate operand
if (opcode <= OP_PUSHDATA4)
{
- unsigned int nSize = opcode;
- if (opcode == OP_PUSHDATA1)
+ unsigned int nSize;
+ if (opcode < OP_PUSHDATA1)
+ {
+ nSize = opcode;
+ }
+ else if (opcode == OP_PUSHDATA1)
{
- if (pc + 1 > end())
+ if (end() - pc < 1)
return false;
nSize = *pc++;
}
else if (opcode == OP_PUSHDATA2)
{
- if (pc + 2 > end())
+ if (end() - pc < 2)
return false;
nSize = 0;
memcpy(&nSize, &pc[0], 2);
}
else if (opcode == OP_PUSHDATA4)
{
- if (pc + 4 > end())
+ if (end() - pc < 4)
return false;
memcpy(&nSize, &pc[0], 4);
pc += 4;
}
- if (pc + nSize > end())
+ if (end() - pc < nSize)
return false;
- vchRet.assign(pc, pc + nSize);
+ if (pvchRet)
+ pvchRet->assign(pc, pc + nSize);
pc += nSize;
}
void FindAndDelete(const CScript& b)
{
+ if (b.empty())
+ return;
iterator pc = begin();
opcodetype opcode;
- vector<unsigned char> vchPushValue;
- int count = 0;
do
{
while (end() - pc >= b.size() && memcmp(&pc[0], &b[0], b.size()) == 0)
- {
erase(pc, pc + b.size());
- count++;
- }
}
- while (GetOp(pc, opcode, vchPushValue));
- //printf("FindAndDeleted deleted %d items\n", count); /// debug
+ while (GetOp(pc, opcode));
+ }
+
+
+ int GetSigOpCount() const
+ {
+ int n = 0;
+ const_iterator pc = begin();
+ while (pc < end())
+ {
+ opcodetype opcode;
+ if (!GetOp(pc, opcode))
+ break;
+ if (opcode == OP_CHECKSIG || opcode == OP_CHECKSIGVERIFY)
+ n++;
+ else if (opcode == OP_CHECKMULTISIG || opcode == OP_CHECKMULTISIGVERIFY)
+ n += 20;
+ }
+ return n;
}
void PrintHex() const
{
- printf("CScript(%s)\n", HexStr(begin(), end()).c_str());
+ printf("CScript(%s)\n", HexStr(begin(), end(), true).c_str());
}
string ToString() const
string str;
opcodetype opcode;
vector<unsigned char> vch;
- const_iterator it = begin();
- while (GetOp(it, opcode, vch))
+ const_iterator pc = begin();
+ while (pc < end())
{
if (!str.empty())
str += " ";
- if (opcode <= OP_PUSHDATA4)
+ if (!GetOp(pc, opcode, vch))
+ {
+ str += "[error]";
+ return str;
+ }
+ if (0 <= opcode && opcode <= OP_PUSHDATA4)
str += ValueString(vch);
else
str += GetOpName(opcode);
static const unsigned int MAX_SIZE = 0x02000000;
static const int VERSION = 312;
-static const char* pszSubVer = ".0";
+static const char* pszSubVer = ".1";
\r
# General Symbol Definitions\r
!define REGKEY "SOFTWARE\$(^Name)"\r
-!define VERSION 0.3.10\r
+!define VERSION 0.3.12\r
!define COMPANY "Bitcoin project"\r
!define URL http://www.bitcoin.org/\r
\r
!insertmacro MUI_LANGUAGE English\r
\r
# Installer attributes\r
-OutFile bitcoin-0.3.10-win32-setup.exe\r
+OutFile bitcoin-0.3.12-win32-setup.exe\r
InstallDir $PROGRAMFILES\Bitcoin\r
CRCCheck on\r
XPStyle on\r
ShowInstDetails show\r
-VIProductVersion 0.3.10.0\r
+VIProductVersion 0.3.12.0\r
VIAddVersionKey ProductName Bitcoin\r
VIAddVersionKey ProductVersion "${VERSION}"\r
VIAddVersionKey CompanyName "${COMPANY}"\r
#else
#define dumpstate()
#endif
+
+
void Double_BlockSHA256(const void* pin, void* pad, const void *pre, unsigned int thash[9][NPAR], const void *init)
{
unsigned int* In = (unsigned int*)pin;
string strStatus = strprintf(_(" %d connections %d blocks %d transactions"), vNodes.size(), nBestHeight, nTransactionCount);
m_statusBar->SetStatusText(strStatus, 2);
- if (fDebug && GetTime() - nThreadSocketHandlerHeartbeat > 60)
- m_statusBar->SetStatusText(" ERROR: ThreadSocketHandler has stopped", 0);
-
// Update receiving address
string strDefaultAddress = PubKeyToAddress(vchDefaultKey);
if (m_textCtrlAddress->GetValue() != strDefaultAddress)
y += 46 + wxString(strMessage2).Freq('\n') * 14;
}
#ifndef __WXMSW__
- x *= 1.14;
- y *= 1.14;
+ x = x * 114 / 100;
+ y = y * 114 / 100;
#endif
SetSize(x, y);
}
void RandAddSeed()
{
// Seed with CPU performance counter
- int64 nCounter = PerformanceCounter();
+ int64 nCounter = GetPerformanceCounter();
RAND_add(&nCounter, sizeof(nCounter), 1.5);
memset(&nCounter, 0, sizeof(nCounter));
}
void LogException(std::exception* pex, const char* pszThread)
{
- char pszMessage[1000];
+ char pszMessage[10000];
FormatException(pszMessage, pex, pszThread);
printf("\n%s", pszMessage);
}
void PrintException(std::exception* pex, const char* pszThread)
{
- char pszMessage[1000];
+ char pszMessage[10000];
FormatException(pszMessage, pex, pszThread);
printf("\n\n************************\n%s\n", pszMessage);
fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
+ strMiscWarning = pszMessage;
#ifdef GUI
if (wxTheApp && !fDaemon)
- MyMessageBox(pszMessage, "Error", wxOK | wxICON_ERROR);
+ MyMessageBox(pszMessage, "Bitcoin", wxOK | wxICON_ERROR);
#endif
throw;
- //DebugBreak();
+}
+
+void ThreadOneMessageBox(string strMessage)
+{
+ // Skip message boxes if one is already open
+ static bool fMessageBoxOpen;
+ if (fMessageBoxOpen)
+ return;
+ fMessageBoxOpen = true;
+ ThreadSafeMessageBox(strMessage, "Bitcoin", wxOK | wxICON_EXCLAMATION);
+ fMessageBoxOpen = false;
+}
+
+void PrintExceptionContinue(std::exception* pex, const char* pszThread)
+{
+ char pszMessage[10000];
+ FormatException(pszMessage, pex, pszThread);
+ printf("\n\n************************\n%s\n", pszMessage);
+ fprintf(stderr, "\n\n************************\n%s\n", pszMessage);
+ strMiscWarning = pszMessage;
+#ifdef GUI
+ if (wxTheApp && !fDaemon)
+ boost::thread(bind(ThreadOneMessageBox, string(pszMessage)));
+#endif
}
if (!fMatch && !fDone)
{
fDone = true;
- string strMessage = _("Warning: Check your system date and time, you may not be able to generate or receive the most recent blocks!");
+ string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
int my_snprintf(char* buffer, size_t limit, const char* format, ...);
string strprintf(const char* format, ...);
bool error(const char* format, ...);
-void PrintException(std::exception* pex, const char* pszThread);
void LogException(std::exception* pex, const char* pszThread);
+void PrintException(std::exception* pex, const char* pszThread);
+void PrintExceptionContinue(std::exception* pex, const char* pszThread);
void ParseString(const string& str, char c, vector<string>& v);
string FormatMoney(int64 n, bool fPlus=false);
bool ParseMoney(const string& str, int64& nRet);
}
template<typename T>
-string HexStr(const T itbegin, const T itend, bool fSpaces=true)
+string HexStr(const T itbegin, const T itend, bool fSpaces=false)
{
if (itbegin == itend)
return "";
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
string str;
+ str.reserve((pend-pbegin) * (fSpaces ? 3 : 2));
for (const unsigned char* p = pbegin; p != pend; p++)
str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p);
return str;
}
-inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)
+inline string HexStr(const vector<unsigned char>& vch, bool fSpaces=false)
{
return HexStr(vch.begin(), vch.end(), fSpaces);
}
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
string str = (f0x ? "0x" : "");
+ str.reserve(str.size() + (pend-pbegin) * 2);
for (const unsigned char* p = pend-1; p >= pbegin; p--)
- str += strprintf("%02X", *p);
+ str += strprintf("%02x", *p);
return str;
}
+inline string HexNumStr(const vector<unsigned char>& vch, bool f0x=true)
+{
+ return HexNumStr(vch.begin(), vch.end(), f0x);
+}
+
template<typename T>
void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true)
{
printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
}
-inline void PrintHex(vector<unsigned char> vch, const char* pszFormat="%s", bool fSpaces=true)
+inline void PrintHex(const vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true)
{
printf(pszFormat, HexStr(vch, fSpaces).c_str());
}
-inline int64 PerformanceCounter()
+inline int64 GetPerformanceCounter()
{
int64 nCounter = 0;
#ifdef __WXMSW__
}
// Randomize the stack to help protect against buffer overrun exploits
-#define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \
- { \
- static char nLoops; \
- if (nLoops <= 0) \
- nLoops = GetRand(20) + 1; \
- if (nLoops-- > 1) \
- { \
- ThreadFn; \
- return; \
- } \
+#define IMPLEMENT_RANDOMIZE_STACK(ThreadFn) \
+ { \
+ static char nLoops; \
+ if (nLoops <= 0) \
+ nLoops = GetRand(20) + 1; \
+ if (nLoops-- > 1) \
+ { \
+ ThreadFn; \
+ return; \
+ } \
}
#define CATCH_PRINT_EXCEPTION(pszFn) \