Add CMutableTransaction and make CTransaction immutable.
In addition, introduce a cached hash inside CTransaction, to prevent recalculating it over and over again.
This commit is contained in:
parent
8f59251b83
commit
4949004d68
@ -127,7 +127,7 @@ public:
|
|||||||
// CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
|
// CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
|
||||||
// vMerkleTree: 4a5e1e
|
// vMerkleTree: 4a5e1e
|
||||||
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
|
||||||
CTransaction txNew;
|
CMutableTransaction txNew;
|
||||||
txNew.vin.resize(1);
|
txNew.vin.resize(1);
|
||||||
txNew.vout.resize(1);
|
txNew.vout.resize(1);
|
||||||
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
txNew.vin[0].scriptSig = CScript() << 486604799 << CScriptNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
|
||||||
|
25
src/core.cpp
25
src/core.cpp
@ -91,11 +91,34 @@ std::string CFeeRate::ToString() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 CTransaction::GetHash() const
|
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
|
||||||
|
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {}
|
||||||
|
|
||||||
|
uint256 CMutableTransaction::GetHash() const
|
||||||
{
|
{
|
||||||
return SerializeHash(*this);
|
return SerializeHash(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CTransaction::UpdateHash() const
|
||||||
|
{
|
||||||
|
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTransaction::CTransaction() : hash(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
|
||||||
|
|
||||||
|
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
|
||||||
|
UpdateHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
||||||
|
*const_cast<int*>(&nVersion) = tx.nVersion;
|
||||||
|
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
|
||||||
|
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
|
||||||
|
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
|
||||||
|
*const_cast<uint256*>(&hash) = tx.hash;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
int64_t CTransaction::GetValueOut() const
|
int64_t CTransaction::GetValueOut() const
|
||||||
{
|
{
|
||||||
int64_t nValueOut = 0;
|
int64_t nValueOut = 0;
|
||||||
|
93
src/core.h
93
src/core.h
@ -203,49 +203,59 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct CMutableTransaction;
|
||||||
|
|
||||||
/** The basic transaction that is broadcasted on the network and contained in
|
/** The basic transaction that is broadcasted on the network and contained in
|
||||||
* blocks. A transaction can contain multiple inputs and outputs.
|
* blocks. A transaction can contain multiple inputs and outputs.
|
||||||
*/
|
*/
|
||||||
class CTransaction
|
class CTransaction
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
/** Memory only. */
|
||||||
|
const uint256 hash;
|
||||||
|
void UpdateHash() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static CFeeRate minTxFee;
|
static CFeeRate minTxFee;
|
||||||
static CFeeRate minRelayTxFee;
|
static CFeeRate minRelayTxFee;
|
||||||
static const int CURRENT_VERSION=1;
|
static const int CURRENT_VERSION=1;
|
||||||
int nVersion;
|
|
||||||
std::vector<CTxIn> vin;
|
|
||||||
std::vector<CTxOut> vout;
|
|
||||||
unsigned int nLockTime;
|
|
||||||
|
|
||||||
CTransaction()
|
// The local variables are made const to prevent unintended modification
|
||||||
{
|
// without updating the cached hash value. However, CTransaction is not
|
||||||
SetNull();
|
// actually immutable; deserialization and assignment are implemented,
|
||||||
}
|
// and bypass the constness. This is safe, as they update the entire
|
||||||
|
// structure, including the hash.
|
||||||
|
const int nVersion;
|
||||||
|
const std::vector<CTxIn> vin;
|
||||||
|
const std::vector<CTxOut> vout;
|
||||||
|
const unsigned int nLockTime;
|
||||||
|
|
||||||
IMPLEMENT_SERIALIZE
|
/** Construct a CTransaction that qualifies as IsNull() */
|
||||||
(
|
CTransaction();
|
||||||
READWRITE(this->nVersion);
|
|
||||||
|
/** Convert a CMutableTransaction into a CTransaction. */
|
||||||
|
CTransaction(const CMutableTransaction &tx);
|
||||||
|
|
||||||
|
CTransaction& operator=(const CTransaction& tx);
|
||||||
|
|
||||||
|
IMPLEMENT_SERIALIZE(
|
||||||
|
READWRITE(*const_cast<int*>(&this->nVersion));
|
||||||
nVersion = this->nVersion;
|
nVersion = this->nVersion;
|
||||||
READWRITE(vin);
|
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||||
READWRITE(vout);
|
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||||
READWRITE(nLockTime);
|
READWRITE(*const_cast<unsigned int*>(&nLockTime));
|
||||||
|
if (fRead)
|
||||||
|
UpdateHash();
|
||||||
)
|
)
|
||||||
|
|
||||||
void SetNull()
|
bool IsNull() const {
|
||||||
{
|
return vin.empty() && vout.empty();
|
||||||
nVersion = CTransaction::CURRENT_VERSION;
|
|
||||||
vin.clear();
|
|
||||||
vout.clear();
|
|
||||||
nLockTime = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsNull() const
|
const uint256& GetHash() const {
|
||||||
{
|
return hash;
|
||||||
return (vin.empty() && vout.empty());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 GetHash() const;
|
|
||||||
|
|
||||||
// Return sum of txouts.
|
// Return sum of txouts.
|
||||||
int64_t GetValueOut() const;
|
int64_t GetValueOut() const;
|
||||||
// GetValueIn() is a method on CCoinsViewCache, because
|
// GetValueIn() is a method on CCoinsViewCache, because
|
||||||
@ -261,22 +271,43 @@ public:
|
|||||||
|
|
||||||
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
friend bool operator==(const CTransaction& a, const CTransaction& b)
|
||||||
{
|
{
|
||||||
return (a.nVersion == b.nVersion &&
|
return a.hash == b.hash;
|
||||||
a.vin == b.vin &&
|
|
||||||
a.vout == b.vout &&
|
|
||||||
a.nLockTime == b.nLockTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
friend bool operator!=(const CTransaction& a, const CTransaction& b)
|
friend bool operator!=(const CTransaction& a, const CTransaction& b)
|
||||||
{
|
{
|
||||||
return !(a == b);
|
return a.hash != b.hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string ToString() const;
|
std::string ToString() const;
|
||||||
void print() const;
|
void print() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** A mutable version of CTransaction. */
|
||||||
|
struct CMutableTransaction
|
||||||
|
{
|
||||||
|
int nVersion;
|
||||||
|
std::vector<CTxIn> vin;
|
||||||
|
std::vector<CTxOut> vout;
|
||||||
|
unsigned int nLockTime;
|
||||||
|
|
||||||
|
CMutableTransaction();
|
||||||
|
CMutableTransaction(const CTransaction& tx);
|
||||||
|
|
||||||
|
IMPLEMENT_SERIALIZE(
|
||||||
|
READWRITE(this->nVersion);
|
||||||
|
nVersion = this->nVersion;
|
||||||
|
READWRITE(vin);
|
||||||
|
READWRITE(vout);
|
||||||
|
READWRITE(nLockTime);
|
||||||
|
)
|
||||||
|
|
||||||
|
/** Compute the hash of this CMutableTransaction. This is computed on the
|
||||||
|
* fly, as opposed to GetHash() in CTransaction, which uses a cached result.
|
||||||
|
*/
|
||||||
|
uint256 GetHash() const;
|
||||||
|
};
|
||||||
|
|
||||||
/** wrapper for CTxOut that provides a more compact serialization */
|
/** wrapper for CTxOut that provides a more compact serialization */
|
||||||
class CTxOutCompressor
|
class CTxOutCompressor
|
||||||
{
|
{
|
||||||
|
@ -86,14 +86,14 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
|
|
||||||
// Create coinbase tx
|
// Create coinbase tx
|
||||||
CTransaction txNew;
|
CMutableTransaction txNew;
|
||||||
txNew.vin.resize(1);
|
txNew.vin.resize(1);
|
||||||
txNew.vin[0].prevout.SetNull();
|
txNew.vin[0].prevout.SetNull();
|
||||||
txNew.vout.resize(1);
|
txNew.vout.resize(1);
|
||||||
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
|
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
|
||||||
|
|
||||||
// Add our coinbase tx as first transaction
|
// Add dummy coinbase tx as first transaction
|
||||||
pblock->vtx.push_back(txNew);
|
pblock->vtx.push_back(CTransaction());
|
||||||
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
||||||
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
|
pblocktemplate->vTxSigOps.push_back(-1); // updated at end
|
||||||
|
|
||||||
@ -294,7 +294,10 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
nLastBlockSize = nBlockSize;
|
nLastBlockSize = nBlockSize;
|
||||||
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
|
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
|
||||||
|
|
||||||
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
// Compute final coinbase transaction.
|
||||||
|
txNew.vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
|
||||||
|
txNew.vin[0].scriptSig = CScript() << OP_0 << OP_0;
|
||||||
|
pblock->vtx[0] = txNew;
|
||||||
pblocktemplate->vTxFees[0] = -nFees;
|
pblocktemplate->vTxFees[0] = -nFees;
|
||||||
|
|
||||||
// Fill in header
|
// Fill in header
|
||||||
@ -302,7 +305,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
UpdateTime(*pblock, pindexPrev);
|
UpdateTime(*pblock, pindexPrev);
|
||||||
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
|
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);
|
||||||
pblock->nNonce = 0;
|
pblock->nNonce = 0;
|
||||||
pblock->vtx[0].vin[0].scriptSig = CScript() << OP_0 << OP_0;
|
|
||||||
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
|
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
|
||||||
|
|
||||||
CBlockIndex indexDummy(*pblock);
|
CBlockIndex indexDummy(*pblock);
|
||||||
@ -328,9 +330,11 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
|
|||||||
}
|
}
|
||||||
++nExtraNonce;
|
++nExtraNonce;
|
||||||
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
|
unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2
|
||||||
pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
|
CMutableTransaction txCoinbase(pblock->vtx[0]);
|
||||||
assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100);
|
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
|
||||||
|
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
|
||||||
|
|
||||||
|
pblock->vtx[0] = txCoinbase;
|
||||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
|||||||
// nPayAmount
|
// nPayAmount
|
||||||
qint64 nPayAmount = 0;
|
qint64 nPayAmount = 0;
|
||||||
bool fDust = false;
|
bool fDust = false;
|
||||||
CTransaction txDummy;
|
CMutableTransaction txDummy;
|
||||||
foreach(const qint64 &amount, CoinControlDialog::payAmounts)
|
foreach(const qint64 &amount, CoinControlDialog::payAmounts)
|
||||||
{
|
{
|
||||||
nPayAmount += amount;
|
nPayAmount += amount;
|
||||||
|
@ -349,7 +349,7 @@ Value createrawtransaction(const Array& params, bool fHelp)
|
|||||||
Array inputs = params[0].get_array();
|
Array inputs = params[0].get_array();
|
||||||
Object sendTo = params[1].get_obj();
|
Object sendTo = params[1].get_obj();
|
||||||
|
|
||||||
CTransaction rawTx;
|
CMutableTransaction rawTx;
|
||||||
|
|
||||||
BOOST_FOREACH(const Value& input, inputs)
|
BOOST_FOREACH(const Value& input, inputs)
|
||||||
{
|
{
|
||||||
@ -554,11 +554,11 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
|
vector<unsigned char> txData(ParseHexV(params[0], "argument 1"));
|
||||||
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ssData(txData, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
vector<CTransaction> txVariants;
|
vector<CMutableTransaction> txVariants;
|
||||||
while (!ssData.empty())
|
while (!ssData.empty())
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
ssData >> tx;
|
ssData >> tx;
|
||||||
txVariants.push_back(tx);
|
txVariants.push_back(tx);
|
||||||
}
|
}
|
||||||
@ -572,7 +572,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
// mergedTx will end up with all the signatures; it
|
// mergedTx will end up with all the signatures; it
|
||||||
// starts as a clone of the rawtx:
|
// starts as a clone of the rawtx:
|
||||||
CTransaction mergedTx(txVariants[0]);
|
CMutableTransaction mergedTx(txVariants[0]);
|
||||||
bool fComplete = true;
|
bool fComplete = true;
|
||||||
|
|
||||||
// Fetch previous transactions (inputs):
|
// Fetch previous transactions (inputs):
|
||||||
@ -713,7 +713,7 @@ Value signrawtransaction(const Array& params, bool fHelp)
|
|||||||
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
|
SignSignature(keystore, prevPubKey, mergedTx, i, nHashType);
|
||||||
|
|
||||||
// ... and merge in other signatures:
|
// ... and merge in other signatures:
|
||||||
BOOST_FOREACH(const CTransaction& txv, txVariants)
|
BOOST_FOREACH(const CMutableTransaction& txv, txVariants)
|
||||||
{
|
{
|
||||||
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
|
txin.scriptSig = CombineSignatures(prevPubKey, mergedTx, i, txin.scriptSig, txv.vin[i].scriptSig);
|
||||||
}
|
}
|
||||||
|
@ -1636,7 +1636,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const C
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType)
|
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
|
||||||
{
|
{
|
||||||
assert(nIn < txTo.vin.size());
|
assert(nIn < txTo.vin.size());
|
||||||
CTxIn& txin = txTo.vin[nIn];
|
CTxIn& txin = txTo.vin[nIn];
|
||||||
@ -1671,7 +1671,7 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CTransa
|
|||||||
return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
|
return VerifyScript(txin.scriptSig, fromPubKey, txTo, nIn, STANDARD_SCRIPT_VERIFY_FLAGS, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType)
|
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
|
||||||
{
|
{
|
||||||
assert(nIn < txTo.vin.size());
|
assert(nIn < txTo.vin.size());
|
||||||
CTxIn& txin = txTo.vin[nIn];
|
CTxIn& txin = txTo.vin[nIn];
|
||||||
@ -1689,7 +1689,7 @@ static CScript PushAll(const vector<valtype>& values)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CScript CombineMultisig(CScript scriptPubKey, const CTransaction& txTo, unsigned int nIn,
|
static CScript CombineMultisig(CScript scriptPubKey, const CMutableTransaction& txTo, unsigned int nIn,
|
||||||
const vector<valtype>& vSolutions,
|
const vector<valtype>& vSolutions,
|
||||||
vector<valtype>& sigs1, vector<valtype>& sigs2)
|
vector<valtype>& sigs1, vector<valtype>& sigs2)
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
class CCoins;
|
class CCoins;
|
||||||
class CKeyStore;
|
class CKeyStore;
|
||||||
class CTransaction;
|
class CTransaction;
|
||||||
|
class CMutableTransaction;
|
||||||
|
|
||||||
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520; // bytes
|
||||||
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
static const unsigned int MAX_OP_RETURN_RELAY = 40; // bytes
|
||||||
@ -805,8 +806,8 @@ bool IsMine(const CKeyStore& keystore, const CTxDestination &dest);
|
|||||||
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
|
void ExtractAffectedKeys(const CKeyStore &keystore, const CScript& scriptPubKey, std::vector<CKeyID> &vKeys);
|
||||||
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
|
bool ExtractDestination(const CScript& scriptPubKey, CTxDestination& addressRet);
|
||||||
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<CTxDestination>& addressRet, int& nRequiredRet);
|
||||||
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
bool SignSignature(const CKeyStore& keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
||||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType=SIGHASH_ALL);
|
||||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
|
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CTransaction& txTo, unsigned int nIn, unsigned int flags, int nHashType);
|
||||||
|
|
||||||
// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
|
// Given two sets of signatures for scriptPubKey, possibly with OP_0 placeholders,
|
||||||
|
@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|||||||
// 50 orphan transactions:
|
// 50 orphan transactions:
|
||||||
for (int i = 0; i < 50; i++)
|
for (int i = 0; i < 50; i++)
|
||||||
{
|
{
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.vin.resize(1);
|
tx.vin.resize(1);
|
||||||
tx.vin[0].prevout.n = 0;
|
tx.vin[0].prevout.n = 0;
|
||||||
tx.vin[0].prevout.hash = GetRandHash();
|
tx.vin[0].prevout.hash = GetRandHash();
|
||||||
@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|||||||
{
|
{
|
||||||
CTransaction txPrev = RandomOrphan();
|
CTransaction txPrev = RandomOrphan();
|
||||||
|
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.vin.resize(1);
|
tx.vin.resize(1);
|
||||||
tx.vin[0].prevout.n = 0;
|
tx.vin[0].prevout.n = 0;
|
||||||
tx.vin[0].prevout.hash = txPrev.GetHash();
|
tx.vin[0].prevout.hash = txPrev.GetHash();
|
||||||
@ -201,7 +201,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|||||||
{
|
{
|
||||||
CTransaction txPrev = RandomOrphan();
|
CTransaction txPrev = RandomOrphan();
|
||||||
|
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.vout.resize(1);
|
tx.vout.resize(1);
|
||||||
tx.vout[0].nValue = 1*CENT;
|
tx.vout[0].nValue = 1*CENT;
|
||||||
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
||||||
@ -242,10 +242,10 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
|
|||||||
|
|
||||||
// 100 orphan transactions:
|
// 100 orphan transactions:
|
||||||
static const int NPREV=100;
|
static const int NPREV=100;
|
||||||
CTransaction orphans[NPREV];
|
CMutableTransaction orphans[NPREV];
|
||||||
for (int i = 0; i < NPREV; i++)
|
for (int i = 0; i < NPREV; i++)
|
||||||
{
|
{
|
||||||
CTransaction& tx = orphans[i];
|
CMutableTransaction& tx = orphans[i];
|
||||||
tx.vin.resize(1);
|
tx.vin.resize(1);
|
||||||
tx.vin[0].prevout.n = 0;
|
tx.vin[0].prevout.n = 0;
|
||||||
tx.vin[0].prevout.hash = GetRandHash();
|
tx.vin[0].prevout.hash = GetRandHash();
|
||||||
@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(DoS_checkSig)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a transaction that depends on orphans:
|
// Create a transaction that depends on orphans:
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.vout.resize(1);
|
tx.vout.resize(1);
|
||||||
tx.vout[0].nValue = 1*CENT;
|
tx.vout[0].nValue = 1*CENT;
|
||||||
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
tx.vout[0].scriptPubKey.SetDestination(key.GetPubKey().GetID());
|
||||||
|
@ -83,13 +83,21 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
|||||||
|
|
||||||
|
|
||||||
wtx.mapValue["comment"] = "y";
|
wtx.mapValue["comment"] = "y";
|
||||||
--wtx.nLockTime; // Just to change the hash :)
|
{
|
||||||
|
CMutableTransaction tx(wtx);
|
||||||
|
--tx.nLockTime; // Just to change the hash :)
|
||||||
|
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
|
||||||
|
}
|
||||||
pwalletMain->AddToWallet(wtx);
|
pwalletMain->AddToWallet(wtx);
|
||||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||||
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
|
vpwtx[1]->nTimeReceived = (unsigned int)1333333336;
|
||||||
|
|
||||||
wtx.mapValue["comment"] = "x";
|
wtx.mapValue["comment"] = "x";
|
||||||
--wtx.nLockTime; // Just to change the hash :)
|
{
|
||||||
|
CMutableTransaction tx(wtx);
|
||||||
|
--tx.nLockTime; // Just to change the hash :)
|
||||||
|
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
|
||||||
|
}
|
||||||
pwalletMain->AddToWallet(wtx);
|
pwalletMain->AddToWallet(wtx);
|
||||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||||
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
|
vpwtx[2]->nTimeReceived = (unsigned int)1333333329;
|
||||||
|
@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
{
|
{
|
||||||
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
CScript scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
|
||||||
CBlockTemplate *pblocktemplate;
|
CBlockTemplate *pblocktemplate;
|
||||||
CTransaction tx,tx2;
|
CMutableTransaction tx,tx2;
|
||||||
CScript script;
|
CScript script;
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
|
|
||||||
@ -68,10 +68,12 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
|||||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
pblock->nVersion = 1;
|
pblock->nVersion = 1;
|
||||||
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
||||||
pblock->vtx[0].vin[0].scriptSig = CScript();
|
CMutableTransaction txCoinbase(pblock->vtx[0]);
|
||||||
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
|
txCoinbase.vin[0].scriptSig = CScript();
|
||||||
pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height());
|
txCoinbase.vin[0].scriptSig.push_back(blockinfo[i].extranonce);
|
||||||
pblock->vtx[0].vout[0].scriptPubKey = CScript();
|
txCoinbase.vin[0].scriptSig.push_back(chainActive.Height());
|
||||||
|
txCoinbase.vout[0].scriptPubKey = CScript();
|
||||||
|
pblock->vtx[0] = CTransaction(txCoinbase);
|
||||||
if (txFirst.size() < 2)
|
if (txFirst.size() < 2)
|
||||||
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
||||||
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
pblock->hashMerkleRoot = pblock->BuildMerkleTree();
|
||||||
|
@ -55,13 +55,13 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
|||||||
CScript escrow;
|
CScript escrow;
|
||||||
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||||
|
|
||||||
CTransaction txFrom; // Funding transaction
|
CMutableTransaction txFrom; // Funding transaction
|
||||||
txFrom.vout.resize(3);
|
txFrom.vout.resize(3);
|
||||||
txFrom.vout[0].scriptPubKey = a_and_b;
|
txFrom.vout[0].scriptPubKey = a_and_b;
|
||||||
txFrom.vout[1].scriptPubKey = a_or_b;
|
txFrom.vout[1].scriptPubKey = a_or_b;
|
||||||
txFrom.vout[2].scriptPubKey = escrow;
|
txFrom.vout[2].scriptPubKey = escrow;
|
||||||
|
|
||||||
CTransaction txTo[3]; // Spending transaction
|
CMutableTransaction txTo[3]; // Spending transaction
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
@ -270,13 +270,13 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
|
|||||||
CScript escrow;
|
CScript escrow;
|
||||||
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
escrow << OP_2 << key[0].GetPubKey() << key[1].GetPubKey() << key[2].GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||||
|
|
||||||
CTransaction txFrom; // Funding transaction
|
CMutableTransaction txFrom; // Funding transaction
|
||||||
txFrom.vout.resize(3);
|
txFrom.vout.resize(3);
|
||||||
txFrom.vout[0].scriptPubKey = a_and_b;
|
txFrom.vout[0].scriptPubKey = a_and_b;
|
||||||
txFrom.vout[1].scriptPubKey = a_or_b;
|
txFrom.vout[1].scriptPubKey = a_or_b;
|
||||||
txFrom.vout[2].scriptPubKey = escrow;
|
txFrom.vout[2].scriptPubKey = escrow;
|
||||||
|
|
||||||
CTransaction txTo[3]; // Spending transaction
|
CMutableTransaction txTo[3]; // Spending transaction
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
|
@ -36,9 +36,9 @@ BOOST_AUTO_TEST_CASE(pmt_test1)
|
|||||||
// build a block with some dummy transactions
|
// build a block with some dummy transactions
|
||||||
CBlock block;
|
CBlock block;
|
||||||
for (unsigned int j=0; j<nTx; j++) {
|
for (unsigned int j=0; j<nTx; j++) {
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.nLockTime = rand(); // actual transaction data doesn't matter; just make the nLockTime's unique
|
tx.nLockTime = rand(); // actual transaction data doesn't matter; just make the nLockTime's unique
|
||||||
block.vtx.push_back(tx);
|
block.vtx.push_back(CTransaction(tx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate actual merkle root and height
|
// calculate actual merkle root and height
|
||||||
|
@ -30,11 +30,11 @@ static bool
|
|||||||
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
|
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict)
|
||||||
{
|
{
|
||||||
// Create dummy to/from transactions:
|
// Create dummy to/from transactions:
|
||||||
CTransaction txFrom;
|
CMutableTransaction txFrom;
|
||||||
txFrom.vout.resize(1);
|
txFrom.vout.resize(1);
|
||||||
txFrom.vout[0].scriptPubKey = scriptPubKey;
|
txFrom.vout[0].scriptPubKey = scriptPubKey;
|
||||||
|
|
||||||
CTransaction txTo;
|
CMutableTransaction txTo;
|
||||||
txTo.vin.resize(1);
|
txTo.vin.resize(1);
|
||||||
txTo.vout.resize(1);
|
txTo.vout.resize(1);
|
||||||
txTo.vin[0].prevout.n = 0;
|
txTo.vin[0].prevout.n = 0;
|
||||||
@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(sign)
|
|||||||
evalScripts[i].SetDestination(standardScripts[i].GetID());
|
evalScripts[i].SetDestination(standardScripts[i].GetID());
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction txFrom; // Funding transaction:
|
CMutableTransaction txFrom; // Funding transaction:
|
||||||
string reason;
|
string reason;
|
||||||
txFrom.vout.resize(8);
|
txFrom.vout.resize(8);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE(sign)
|
|||||||
}
|
}
|
||||||
BOOST_CHECK(IsStandardTx(txFrom, reason));
|
BOOST_CHECK(IsStandardTx(txFrom, reason));
|
||||||
|
|
||||||
CTransaction txTo[8]; // Spending transactions
|
CMutableTransaction txTo[8]; // Spending transactions
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(set)
|
|||||||
keystore.AddCScript(inner[i]);
|
keystore.AddCScript(inner[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction txFrom; // Funding transaction:
|
CMutableTransaction txFrom; // Funding transaction:
|
||||||
string reason;
|
string reason;
|
||||||
txFrom.vout.resize(4);
|
txFrom.vout.resize(4);
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
@ -183,7 +183,7 @@ BOOST_AUTO_TEST_CASE(set)
|
|||||||
}
|
}
|
||||||
BOOST_CHECK(IsStandardTx(txFrom, reason));
|
BOOST_CHECK(IsStandardTx(txFrom, reason));
|
||||||
|
|
||||||
CTransaction txTo[4]; // Spending transactions
|
CMutableTransaction txTo[4]; // Spending transactions
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
@ -265,7 +265,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||||||
keys.push_back(key[i].GetPubKey());
|
keys.push_back(key[i].GetPubKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction txFrom;
|
CMutableTransaction txFrom;
|
||||||
txFrom.vout.resize(6);
|
txFrom.vout.resize(6);
|
||||||
|
|
||||||
// First three are standard:
|
// First three are standard:
|
||||||
@ -299,7 +299,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||||||
|
|
||||||
coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0));
|
coins.SetCoins(txFrom.GetHash(), CCoins(txFrom, 0));
|
||||||
|
|
||||||
CTransaction txTo;
|
CMutableTransaction txTo;
|
||||||
txTo.vout.resize(1);
|
txTo.vout.resize(1);
|
||||||
txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
|
txTo.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
|
||||||
|
|
||||||
@ -326,7 +326,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||||||
txTo.vin[i].scriptSig = t;
|
txTo.vin[i].scriptSig = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction txToNonStd;
|
CMutableTransaction txToNonStd;
|
||||||
txToNonStd.vout.resize(1);
|
txToNonStd.vout.resize(1);
|
||||||
txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
|
txToNonStd.vout[0].scriptPubKey.SetDestination(key[1].GetPubKey().GetID());
|
||||||
txToNonStd.vout[0].nValue = 1000;
|
txToNonStd.vout[0].nValue = 1000;
|
||||||
|
@ -240,11 +240,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
|
|||||||
CScript scriptPubKey12;
|
CScript scriptPubKey12;
|
||||||
scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
scriptPubKey12 << OP_1 << key1.GetPubKey() << key2.GetPubKey() << OP_2 << OP_CHECKMULTISIG;
|
||||||
|
|
||||||
CTransaction txFrom12;
|
CMutableTransaction txFrom12;
|
||||||
txFrom12.vout.resize(1);
|
txFrom12.vout.resize(1);
|
||||||
txFrom12.vout[0].scriptPubKey = scriptPubKey12;
|
txFrom12.vout[0].scriptPubKey = scriptPubKey12;
|
||||||
|
|
||||||
CTransaction txTo12;
|
CMutableTransaction txTo12;
|
||||||
txTo12.vin.resize(1);
|
txTo12.vin.resize(1);
|
||||||
txTo12.vout.resize(1);
|
txTo12.vout.resize(1);
|
||||||
txTo12.vin[0].prevout.n = 0;
|
txTo12.vin[0].prevout.n = 0;
|
||||||
@ -274,11 +274,11 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
|
|||||||
CScript scriptPubKey23;
|
CScript scriptPubKey23;
|
||||||
scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
scriptPubKey23 << OP_2 << key1.GetPubKey() << key2.GetPubKey() << key3.GetPubKey() << OP_3 << OP_CHECKMULTISIG;
|
||||||
|
|
||||||
CTransaction txFrom23;
|
CMutableTransaction txFrom23;
|
||||||
txFrom23.vout.resize(1);
|
txFrom23.vout.resize(1);
|
||||||
txFrom23.vout[0].scriptPubKey = scriptPubKey23;
|
txFrom23.vout[0].scriptPubKey = scriptPubKey23;
|
||||||
|
|
||||||
CTransaction txTo23;
|
CMutableTransaction txTo23;
|
||||||
txTo23.vin.resize(1);
|
txTo23.vin.resize(1);
|
||||||
txTo23.vout.resize(1);
|
txTo23.vout.resize(1);
|
||||||
txTo23.vin[0].prevout.n = 0;
|
txTo23.vin[0].prevout.n = 0;
|
||||||
@ -345,11 +345,11 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||||||
keystore.AddKey(key);
|
keystore.AddKey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction txFrom;
|
CMutableTransaction txFrom;
|
||||||
txFrom.vout.resize(1);
|
txFrom.vout.resize(1);
|
||||||
txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID());
|
txFrom.vout[0].scriptPubKey.SetDestination(keys[0].GetPubKey().GetID());
|
||||||
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
|
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
|
||||||
CTransaction txTo;
|
CMutableTransaction txTo;
|
||||||
txTo.vin.resize(1);
|
txTo.vin.resize(1);
|
||||||
txTo.vout.resize(1);
|
txTo.vout.resize(1);
|
||||||
txTo.vin[0].prevout.n = 0;
|
txTo.vin[0].prevout.n = 0;
|
||||||
|
@ -28,7 +28,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un
|
|||||||
printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
|
printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
CTransaction txTmp(txTo);
|
CMutableTransaction txTmp(txTo);
|
||||||
|
|
||||||
// In case concatenating two scripts ends up with two codeseparators,
|
// In case concatenating two scripts ends up with two codeseparators,
|
||||||
// or an extra one at the end, this prevents all those possible incompatibilities.
|
// or an extra one at the end, this prevents all those possible incompatibilities.
|
||||||
@ -90,7 +90,7 @@ void static RandomScript(CScript &script) {
|
|||||||
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
|
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
|
||||||
}
|
}
|
||||||
|
|
||||||
void static RandomTransaction(CTransaction &tx, bool fSingle) {
|
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
|
||||||
tx.nVersion = insecure_rand();
|
tx.nVersion = insecure_rand();
|
||||||
tx.vin.clear();
|
tx.vin.clear();
|
||||||
tx.vout.clear();
|
tx.vout.clear();
|
||||||
@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(sighash_test)
|
|||||||
#endif
|
#endif
|
||||||
for (int i=0; i<nRandomTests; i++) {
|
for (int i=0; i<nRandomTests; i++) {
|
||||||
int nHashType = insecure_rand();
|
int nHashType = insecure_rand();
|
||||||
CTransaction txTo;
|
CMutableTransaction txTo;
|
||||||
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
|
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
RandomScript(scriptCode);
|
RandomScript(scriptCode);
|
||||||
|
@ -208,7 +208,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
|||||||
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
|
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||||
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
|
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
|
||||||
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
|
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
stream >> tx;
|
stream >> tx;
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
|
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state) && state.IsValid(), "Simple deserialized transaction should be valid.");
|
||||||
@ -224,10 +224,10 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
|||||||
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
|
// paid to a TX_PUBKEY, the second 21 and 22 CENT outputs
|
||||||
// paid to a TX_PUBKEYHASH.
|
// paid to a TX_PUBKEYHASH.
|
||||||
//
|
//
|
||||||
static std::vector<CTransaction>
|
static std::vector<CMutableTransaction>
|
||||||
SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet)
|
SetupDummyInputs(CBasicKeyStore& keystoreRet, CCoinsView & coinsRet)
|
||||||
{
|
{
|
||||||
std::vector<CTransaction> dummyTransactions;
|
std::vector<CMutableTransaction> dummyTransactions;
|
||||||
dummyTransactions.resize(2);
|
dummyTransactions.resize(2);
|
||||||
|
|
||||||
// Add some keys to the keystore:
|
// Add some keys to the keystore:
|
||||||
@ -261,9 +261,9 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
|||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
CCoinsView coinsDummy;
|
CCoinsView coinsDummy;
|
||||||
CCoinsViewCache coins(coinsDummy);
|
CCoinsViewCache coins(coinsDummy);
|
||||||
std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
||||||
|
|
||||||
CTransaction t1;
|
CMutableTransaction t1;
|
||||||
t1.vin.resize(3);
|
t1.vin.resize(3);
|
||||||
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
||||||
t1.vin[0].prevout.n = 1;
|
t1.vin[0].prevout.n = 1;
|
||||||
@ -296,9 +296,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
CCoinsView coinsDummy;
|
CCoinsView coinsDummy;
|
||||||
CCoinsViewCache coins(coinsDummy);
|
CCoinsViewCache coins(coinsDummy);
|
||||||
std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
||||||
|
|
||||||
CTransaction t;
|
CMutableTransaction t;
|
||||||
t.vin.resize(1);
|
t.vin.resize(1);
|
||||||
t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
||||||
t.vin[0].prevout.n = 1;
|
t.vin[0].prevout.n = 1;
|
||||||
|
@ -31,16 +31,18 @@ static vector<COutput> vCoins;
|
|||||||
static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
|
static void add_coin(int64_t nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
|
||||||
{
|
{
|
||||||
static int nextLockTime = 0;
|
static int nextLockTime = 0;
|
||||||
CTransaction tx;
|
CMutableTransaction tx;
|
||||||
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
|
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
|
||||||
tx.vout.resize(nInput+1);
|
tx.vout.resize(nInput+1);
|
||||||
tx.vout[nInput].nValue = nValue;
|
tx.vout[nInput].nValue = nValue;
|
||||||
|
if (fIsFromMe) {
|
||||||
|
// IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
|
||||||
|
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
|
||||||
|
tx.vin.resize(1);
|
||||||
|
}
|
||||||
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
||||||
if (fIsFromMe)
|
if (fIsFromMe)
|
||||||
{
|
{
|
||||||
// IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
|
|
||||||
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
|
|
||||||
wtx->vin.resize(1);
|
|
||||||
wtx->fDebitCached = true;
|
wtx->fDebitCached = true;
|
||||||
wtx->nDebitCached = 1;
|
wtx->nDebitCached = 1;
|
||||||
}
|
}
|
||||||
|
@ -1245,6 +1245,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
wtxNew.BindWallet(this);
|
wtxNew.BindWallet(this);
|
||||||
|
CMutableTransaction txNew;
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, cs_wallet);
|
LOCK2(cs_main, cs_wallet);
|
||||||
@ -1252,8 +1253,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
nFeeRet = payTxFee.GetFeePerK();
|
nFeeRet = payTxFee.GetFeePerK();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
wtxNew.vin.clear();
|
txNew.vin.clear();
|
||||||
wtxNew.vout.clear();
|
txNew.vout.clear();
|
||||||
wtxNew.fFromMe = true;
|
wtxNew.fFromMe = true;
|
||||||
|
|
||||||
int64_t nTotalValue = nValue + nFeeRet;
|
int64_t nTotalValue = nValue + nFeeRet;
|
||||||
@ -1267,7 +1268,7 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
strFailReason = _("Transaction amount too small");
|
strFailReason = _("Transaction amount too small");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
wtxNew.vout.push_back(txout);
|
txNew.vout.push_back(txout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose coins to use
|
// Choose coins to use
|
||||||
@ -1331,8 +1332,8 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Insert change txn at random position:
|
// Insert change txn at random position:
|
||||||
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
|
vector<CTxOut>::iterator position = txNew.vout.begin()+GetRandInt(txNew.vout.size()+1);
|
||||||
wtxNew.vout.insert(position, newTxOut);
|
txNew.vout.insert(position, newTxOut);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1340,17 +1341,20 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend,
|
|||||||
|
|
||||||
// Fill vin
|
// Fill vin
|
||||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
||||||
wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
|
txNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
|
||||||
|
|
||||||
// Sign
|
// Sign
|
||||||
int nIn = 0;
|
int nIn = 0;
|
||||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
|
||||||
if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
|
if (!SignSignature(*this, *coin.first, txNew, nIn++))
|
||||||
{
|
{
|
||||||
strFailReason = _("Signing transaction failed");
|
strFailReason = _("Signing transaction failed");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Embed the constructed transaction data in wtxNew.
|
||||||
|
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
|
||||||
|
|
||||||
// Limit size
|
// Limit size
|
||||||
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
|
unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
if (nBytes >= MAX_STANDARD_TX_SIZE)
|
if (nBytes >= MAX_STANDARD_TX_SIZE)
|
||||||
|
Loading…
Reference in New Issue
Block a user