|
|
@ -678,7 +678,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi |
|
|
|
|
|
|
|
|
|
|
|
// Safety limits
|
|
|
|
// Safety limits
|
|
|
|
unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK); |
|
|
|
unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK); |
|
|
|
if (GetSigOpCount() > 2 || nSize < 100) |
|
|
|
// Checking ECDSA signatures is a CPU bottleneck, so to avoid denial-of-service
|
|
|
|
|
|
|
|
// attacks disallow transactions with more than one SigOp per 34 bytes.
|
|
|
|
|
|
|
|
// 34 bytes because a TxOut is:
|
|
|
|
|
|
|
|
// 20-byte address + 8 byte bitcoin amount + 5 bytes of ops + 1 byte script length
|
|
|
|
|
|
|
|
if (GetSigOpCount() > nSize / 34 || nSize < 100) |
|
|
|
return error("AcceptToMemoryPool() : nonstandard transaction"); |
|
|
|
return error("AcceptToMemoryPool() : nonstandard transaction"); |
|
|
|
|
|
|
|
|
|
|
|
// Rather not work on nonstandard transactions
|
|
|
|
// Rather not work on nonstandard transactions
|
|
|
@ -3846,8 +3850,18 @@ bool SelectCoins(int64 nTargetValue, set<CWalletTx*>& setCoinsRet) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) |
|
|
|
bool CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int64 nValue = 0; |
|
|
|
|
|
|
|
foreach (const PAIRTYPE(CScript, int64)& s, vecSend) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
if (nValue < 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
nValue += s.second; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (vecSend.empty() || nValue < 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
CRITICAL_BLOCK(cs_main) |
|
|
|
CRITICAL_BLOCK(cs_main) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// txdb must be opened before the mapWallet lock
|
|
|
|
// txdb must be opened before the mapWallet lock
|
|
|
@ -3860,11 +3874,12 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR |
|
|
|
wtxNew.vin.clear(); |
|
|
|
wtxNew.vin.clear(); |
|
|
|
wtxNew.vout.clear(); |
|
|
|
wtxNew.vout.clear(); |
|
|
|
wtxNew.fFromMe = true; |
|
|
|
wtxNew.fFromMe = true; |
|
|
|
if (nValue < 0) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
int64 nValueOut = nValue; |
|
|
|
|
|
|
|
int64 nTotalValue = nValue + nFeeRet; |
|
|
|
int64 nTotalValue = nValue + nFeeRet; |
|
|
|
double dPriority = 0; |
|
|
|
double dPriority = 0; |
|
|
|
|
|
|
|
// vouts to the payees
|
|
|
|
|
|
|
|
foreach (const PAIRTYPE(CScript, int64)& s, vecSend) |
|
|
|
|
|
|
|
wtxNew.vout.push_back(CTxOut(s.second, s.first)); |
|
|
|
|
|
|
|
|
|
|
|
// Choose coins to use
|
|
|
|
// Choose coins to use
|
|
|
|
set<CWalletTx*> setCoins; |
|
|
|
set<CWalletTx*> setCoins; |
|
|
@ -3878,11 +3893,6 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR |
|
|
|
dPriority += (double)nCredit * pcoin->GetDepthInMainChain(); |
|
|
|
dPriority += (double)nCredit * pcoin->GetDepthInMainChain(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Fill a vout to the payee
|
|
|
|
|
|
|
|
bool fChangeFirst = GetRand(2); |
|
|
|
|
|
|
|
if (!fChangeFirst) |
|
|
|
|
|
|
|
wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fill a vout back to self with any change
|
|
|
|
// Fill a vout back to self with any change
|
|
|
|
int64 nChange = nValueIn - nTotalValue; |
|
|
|
int64 nChange = nValueIn - nTotalValue; |
|
|
|
if (nChange >= CENT) |
|
|
|
if (nChange >= CENT) |
|
|
@ -3900,19 +3910,18 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR |
|
|
|
|
|
|
|
|
|
|
|
// Fill a vout to ourself, using same address type as the payment
|
|
|
|
// Fill a vout to ourself, using same address type as the payment
|
|
|
|
CScript scriptChange; |
|
|
|
CScript scriptChange; |
|
|
|
if (scriptPubKey.GetBitcoinAddressHash160() != 0) |
|
|
|
if (vecSend[0].first.GetBitcoinAddressHash160() != 0) |
|
|
|
scriptChange.SetBitcoinAddress(vchPubKey); |
|
|
|
scriptChange.SetBitcoinAddress(vchPubKey); |
|
|
|
else |
|
|
|
else |
|
|
|
scriptChange << vchPubKey << OP_CHECKSIG; |
|
|
|
scriptChange << vchPubKey << OP_CHECKSIG; |
|
|
|
wtxNew.vout.push_back(CTxOut(nChange, scriptChange)); |
|
|
|
|
|
|
|
|
|
|
|
// Insert change txn at random position:
|
|
|
|
|
|
|
|
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()); |
|
|
|
|
|
|
|
wtxNew.vout.insert(position, CTxOut(nChange, scriptChange)); |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
reservekey.ReturnKey(); |
|
|
|
reservekey.ReturnKey(); |
|
|
|
|
|
|
|
|
|
|
|
// Fill a vout to the payee
|
|
|
|
|
|
|
|
if (fChangeFirst) |
|
|
|
|
|
|
|
wtxNew.vout.push_back(CTxOut(nValueOut, scriptPubKey)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Fill vin
|
|
|
|
// Fill vin
|
|
|
|
foreach(CWalletTx* pcoin, setCoins) |
|
|
|
foreach(CWalletTx* pcoin, setCoins) |
|
|
|
for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) |
|
|
|
for (int nOut = 0; nOut < pcoin->vout.size(); nOut++) |
|
|
@ -3954,6 +3963,13 @@ bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CR |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
vector< pair<CScript, int64> > vecSend; |
|
|
|
|
|
|
|
vecSend.push_back(make_pair(scriptPubKey, nValue)); |
|
|
|
|
|
|
|
return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Call after CreateTransaction unless you want to abort
|
|
|
|
// Call after CreateTransaction unless you want to abort
|
|
|
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) |
|
|
|
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey) |
|
|
|
{ |
|
|
|
{ |
|
|
|