Browse Source

cleanup,

catch some recoverable exceptions and continue

git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@148 1a98c847-1fd6-4fd8-948a-caf3550aa51b
pull/1/head
s_nakamoto 12 years ago
parent
commit
f1e1fb4bde
  1. 3
      cryptopp/secblock.h
  2. 7
      db.cpp
  3. 4
      init.cpp
  4. 20
      irc.cpp
  5. 99
      main.cpp
  6. 50
      main.h
  7. 4
      makefile.unix
  8. 53
      net.cpp
  9. 5
      net.h
  10. 112
      script.cpp
  11. 178
      script.h
  12. 2
      serialize.h
  13. 6
      setup.nsi
  14. 2
      sha256.cpp
  15. 3
      ui.cpp
  16. 4
      ui.h
  17. 36
      util.cpp
  18. 40
      util.h

3
cryptopp/secblock.h

@ -184,7 +184,8 @@ public: @@ -184,7 +184,8 @@ public:
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;}

7
db.cpp

@ -820,10 +820,15 @@ void BackupWallet(const string& strDest) @@ -820,10 +820,15 @@ void BackupWallet(const string& strDest)
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;

4
init.cpp

@ -297,7 +297,7 @@ bool AppInit2(int argc, char* argv[]) @@ -297,7 +297,7 @@ bool AppInit2(int argc, char* argv[])
if (!strErrors.empty())
{
wxMessageBox(strErrors, "Bitcoin");
wxMessageBox(strErrors, "Bitcoin", wxOK | wxICON_ERROR);
return false;
}
@ -374,7 +374,7 @@ bool AppInit2(int argc, char* argv[]) @@ -374,7 +374,7 @@ bool AppInit2(int argc, char* argv[])
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);
}
//

20
irc.cpp

@ -6,6 +6,9 @@ @@ -6,6 +6,9 @@
int nGotIRCAddresses = 0;
void ThreadIRCSeed2(void* parg);
#pragma pack(push, 1)
@ -128,6 +131,7 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha @@ -128,6 +131,7 @@ int RecvUntil(SOCKET hSocket, const char* psz1, const char* psz2=NULL, const cha
loop
{
string strLine;
strLine.reserve(10000);
if (!RecvLineIRC(hSocket, strLine))
return 0;
printf("IRC %s\n", strLine.c_str());
@ -157,6 +161,21 @@ bool Wait(int nSeconds) @@ -157,6 +161,21 @@ bool Wait(int nSeconds)
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;
@ -236,6 +255,7 @@ void ThreadIRCSeed(void* parg) @@ -236,6 +255,7 @@ void ThreadIRCSeed(void* parg)
int64 nStart = GetTime();
string strLine;
strLine.reserve(10000);
while (!fShutdown && RecvLineIRC(hSocket, strLine))
{
if (strLine.empty() || strLine.size() > 900 || strLine[0] != ':')

99
main.cpp

@ -91,7 +91,7 @@ vector<unsigned char> GenerateNewKey() @@ -91,7 +91,7 @@ vector<unsigned char> GenerateNewKey()
CKey key;
key.MakeNewKey();
if (!AddKey(key))
throw runtime_error("GenerateNewKey() : AddKey failed\n");
throw runtime_error("GenerateNewKey() : AddKey failed");
return key.GetPubKey();
}
@ -487,21 +487,25 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb) @@ -487,21 +487,25 @@ void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
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();
@ -545,7 +549,7 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -545,7 +549,7 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
{
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
@ -553,10 +557,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -553,10 +557,10 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
{
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
@ -564,15 +568,15 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis @@ -564,15 +568,15 @@ bool CTransaction::AcceptTransaction(CTxDB& txdb, bool fCheckInputs, bool* pfMis
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();
@ -637,17 +641,17 @@ int CMerkleTx::GetBlocksToMaturity() const @@ -637,17 +641,17 @@ int CMerkleTx::GetBlocksToMaturity() const
}
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);
}
}
@ -657,19 +661,19 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs) @@ -657,19 +661,19 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool 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()
@ -1046,6 +1050,8 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo @@ -1046,6 +1050,8 @@ bool CTransaction::ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPoo
if (nTxFee < nMinFee)
return false;
nFees += nTxFee;
if (!MoneyRange(nFees))
return error("ConnectInputs() : nFees out of range");
}
if (fBlock)
@ -1098,6 +1104,9 @@ bool CTransaction::ClientConnectInputs() @@ -1098,6 +1104,9 @@ bool CTransaction::ClientConnectInputs()
// 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;
@ -1251,7 +1260,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew) @@ -1251,7 +1260,7 @@ bool Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
// 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)
@ -1365,7 +1374,7 @@ bool CBlock::CheckBlock() const @@ -1365,7 +1374,7 @@ bool CBlock::CheckBlock() const
// 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
@ -1407,6 +1416,15 @@ bool CBlock::AcceptBlock() @@ -1407,6 +1416,15 @@ bool CBlock::AcceptBlock()
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())
@ -1414,7 +1432,7 @@ bool CBlock::AcceptBlock() @@ -1414,7 +1432,7 @@ bool CBlock::AcceptBlock()
// 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
@ -1422,12 +1440,12 @@ bool CBlock::AcceptBlock() @@ -1422,12 +1440,12 @@ bool CBlock::AcceptBlock()
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)
@ -2012,13 +2030,13 @@ bool ProcessMessages(CNode* pfrom) @@ -2012,13 +2030,13 @@ bool ProcessMessages(CNode* pfrom)
}
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)
@ -2165,7 +2183,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2165,7 +2183,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
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);
}
@ -2313,7 +2331,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2313,7 +2331,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
pfrom->AddInventoryKnown(inv);
bool fMissingInputs = false;
if (tx.AcceptTransaction(true, &fMissingInputs))
if (tx.AcceptToMemoryPool(true, &fMissingInputs))
{
AddToWalletIfMine(tx, NULL);
RelayMessage(inv, vMsg);
@ -2333,7 +2351,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv) @@ -2333,7 +2351,7 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
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);
@ -2809,8 +2827,9 @@ void BitcoinMiner() @@ -2809,8 +2827,9 @@ void BitcoinMiner()
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;
@ -2822,7 +2841,10 @@ void BitcoinMiner() @@ -2822,7 +2841,10 @@ void BitcoinMiner()
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
@ -2835,6 +2857,7 @@ void BitcoinMiner() @@ -2835,6 +2857,7 @@ void BitcoinMiner()
pblock->vtx.push_back(tx);
nBlockSize += nTxSize;
nBlockSigOps += nTxSigOps;
vfAlreadyAdded[n] = true;
fFoundSomething = true;
}
@ -3297,7 +3320,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key) @@ -3297,7 +3320,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
// 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.
@ -3320,7 +3343,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key) @@ -3320,7 +3343,7 @@ bool CommitTransaction(CWalletTx& wtxNew, const CKey& key)
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");

50
main.h

@ -15,6 +15,7 @@ class CWalletTx; @@ -15,6 +15,7 @@ class CWalletTx;
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;
@ -266,7 +267,7 @@ public: @@ -266,7 +267,7 @@ public:
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)
@ -474,7 +475,7 @@ public: @@ -474,7 +475,7 @@ public:
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
@ -505,6 +506,16 @@ public: @@ -505,6 +506,16 @@ public:
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)
@ -570,11 +581,16 @@ public: @@ -570,11 +581,16 @@ public:
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");
@ -639,16 +655,16 @@ public: @@ -639,16 +655,16 @@ public:
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();
};
@ -721,8 +737,8 @@ public: @@ -721,8 +737,8 @@ public:
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); }
};
@ -852,12 +868,8 @@ public: @@ -852,12 +868,8 @@ public:
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)
@ -948,6 +960,14 @@ public: @@ -948,6 +960,14 @@ public:
return (int64)nTime;
}
int GetSigOpCount() const
{
int n = 0;
foreach(const CTransaction& tx, vtx)
n += tx.GetSigOpCount();
return n;
}
uint256 BuildMerkleTree() const
{

4
makefile.unix

@ -7,11 +7,13 @@ INCLUDEPATHS= \ @@ -7,11 +7,13 @@ INCLUDEPATHS= \
-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= \

53
net.cpp

@ -25,7 +25,6 @@ CNode* pnodeLocalHost = NULL; @@ -25,7 +25,6 @@ CNode* pnodeLocalHost = NULL;
uint64 nLocalHostNonce = 0;
array<int, 10> vnThreadsRunning;
SOCKET hListenSocket = INVALID_SOCKET;
int64 nThreadSocketHandlerHeartbeat = INT64_MAX;
vector<CNode*> vNodes;
CCriticalSection cs_vNodes;
@ -789,7 +788,6 @@ void ThreadSocketHandler2(void* parg) @@ -789,7 +788,6 @@ void ThreadSocketHandler2(void* parg)
pnode->Release();
}
nThreadSocketHandlerHeartbeat = GetTime();
Sleep(10);
}
}
@ -1364,57 +1362,6 @@ void StartNode(void* parg) @@ -1364,57 +1362,6 @@ void StartNode(void* parg)
// 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()

5
net.h

@ -117,9 +117,9 @@ public: @@ -117,9 +117,9 @@ public:
}
// 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;
}
@ -466,7 +466,6 @@ extern CNode* pnodeLocalHost; @@ -466,7 +466,6 @@ extern CNode* pnodeLocalHost;
extern uint64 nLocalHostNonce;
extern array<int, 10> vnThreadsRunning;
extern SOCKET hListenSocket;
extern int64 nThreadSocketHandlerHeartbeat;
extern vector<CNode*> vNodes;
extern CCriticalSection cs_vNodes;

112
script.cpp

@ -59,6 +59,13 @@ void MakeSameSize(valtype& vch1, valtype& vch2) @@ -59,6 +59,13 @@ void MakeSameSize(valtype& vch1, valtype& vch2)
//
#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)
{
@ -66,6 +73,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -66,6 +73,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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)
@ -82,13 +91,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -82,13 +91,11 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
//
// 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 ||
@ -108,7 +115,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -108,7 +115,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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)
@ -149,14 +156,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -149,14 +156,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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:
{
@ -170,7 +169,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -170,7 +169,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
fValue = CastToBool(vch);
if (opcode == OP_NOTIF)
fValue = !fValue;
stack.pop_back();
popstack(stack);
}
vfExec.push_back(fValue);
}
@ -200,7 +199,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -200,7 +199,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
return false;
bool fValue = CastToBool(stacktop(-1));
if (fValue)
stack.pop_back();
popstack(stack);
else
return false;
}
@ -221,7 +220,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -221,7 +220,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
if (stack.size() < 1)
return false;
altstack.push_back(stacktop(-1));
stack.pop_back();
popstack(stack);
}
break;
@ -230,15 +229,17 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -230,15 +229,17 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
@ -327,7 +328,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -327,7 +328,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
// (x -- )
if (stack.size() < 1)
return false;
stack.pop_back();
popstack(stack);
}
break;
@ -368,7 +369,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -368,7 +369,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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);
@ -421,7 +422,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -421,7 +422,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
}
@ -443,8 +444,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -443,8 +444,8 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
@ -464,7 +465,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -464,7 +465,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
vch.erase(vch.begin() + nSize, vch.end());
else
vch.erase(vch.begin(), vch.end() - nSize);
stack.pop_back();
popstack(stack);
}
break;
@ -518,7 +519,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -518,7 +519,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
for (int i = 0; i < vch1.size(); i++)
vch1[i] ^= vch2[i];
}
stack.pop_back();
popstack(stack);
}
break;
@ -537,13 +538,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -537,13 +538,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
// 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;
}
@ -578,7 +579,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -578,7 +579,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
@ -657,14 +658,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -657,14 +658,14 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
}
@ -680,9 +681,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -680,9 +681,9 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
@ -718,7 +719,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -718,7 +719,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
uint256 hash = Hash(vch.begin(), vch.end());
memcpy(&vchHash[0], &hash, sizeof(hash));
}
stack.pop_back();
popstack(stack);
stack.push_back(vchHash);
}
break;
@ -752,13 +753,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -752,13 +753,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
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;
}
@ -822,13 +823,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -822,13 +823,13 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
}
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;
}
@ -856,8 +857,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co @@ -856,8 +857,6 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, co
return true;
}
#undef top
@ -945,10 +944,7 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc @@ -945,10 +944,7 @@ bool CheckSig(vector<unsigned char> vchSig, vector<unsigned char> vchPubKey, CSc
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);
}
@ -986,21 +982,19 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo @@ -986,21 +982,19 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
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));
}
@ -1010,7 +1004,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo @@ -1010,7 +1004,7 @@ bool Solver(const CScript& scriptPubKey, vector<pair<opcodetype, valtype> >& vSo
break;
vSolutionRet.push_back(make_pair(opcode2, vch1));
}
else if (opcode1 != opcode2)
else if (opcode1 != opcode2 || vch1 != vch2)
{
break;
}
@ -1068,6 +1062,10 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s @@ -1068,6 +1062,10 @@ bool Solver(const CScript& scriptPubKey, uint256 hash, int nHashType, CScript& s
scriptSigRet << vchSig << vchPubKey;
}
}
else
{
return false;
}
}
}

178
script.h

@ -150,18 +150,11 @@ enum opcodetype @@ -150,18 +150,11 @@ enum opcodetype
// 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,
};
@ -304,16 +297,13 @@ inline const char* GetOpName(opcodetype opcode) @@ -304,16 +297,13 @@ inline const char* GetOpName(opcodetype opcode)
// 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";
}
};
@ -325,8 +315,7 @@ inline string ValueString(const vector<unsigned char>& vch) @@ -325,8 +315,7 @@ inline string ValueString(const vector<unsigned char>& vch)
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)
@ -363,12 +352,12 @@ protected: @@ -363,12 +352,12 @@ protected:
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));
}
@ -377,7 +366,7 @@ protected: @@ -377,7 +366,7 @@ protected:
CBigNum bn(n);
*this << bn.getvch();
}
return (*this);
return *this;
}
public:
@ -398,7 +387,7 @@ public: @@ -398,7 +387,7 @@ public:
{
CScript ret = a;
ret += b;
return (ret);
return ret;
}
@ -419,50 +408,43 @@ public: @@ -419,50 +408,43 @@ public:
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)
@ -476,14 +458,20 @@ public: @@ -476,14 +458,20 @@ public:
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)
@ -491,7 +479,7 @@ public: @@ -491,7 +479,7 @@ public:
// 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;
}
@ -499,41 +487,59 @@ public: @@ -499,41 +487,59 @@ public:
{
// 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)
{