Auto merge of #1566 - daira:1557.make-v2-txns-standard, r=ageis

1557.make v2 txns standard

Make v2 transactions standard. This also corrects a rule about admitting large orphan transactions into the mempool, to account for v2-specific fields. ref #1557
This commit is contained in:
zkbot 2016-10-21 01:10:37 -04:00
commit c99a1c7e4f
5 changed files with 59 additions and 6 deletions

View File

@ -157,7 +157,7 @@ static void RegisterLoad(const string& strInput)
static void MutateTxVersion(CMutableTransaction& tx, const string& cmdVal)
{
int64_t newVersion = atoi64(cmdVal);
if (newVersion < 1 || newVersion > CTransaction::CURRENT_VERSION)
if (newVersion < CTransaction::MIN_CURRENT_VERSION || newVersion > CTransaction::MAX_CURRENT_VERSION)
throw runtime_error("Invalid TX version requested");
tx.nVersion = (int) newVersion;

View File

@ -564,7 +564,7 @@ bool AddOrphanTx(const CTransaction& tx, NodeId peer)
// have been mined or received.
// 10,000 orphans, each of which is at most 5,000 bytes big is
// at most 500 megabytes of orphans:
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
unsigned int sz = tx.GetSerializeSize(SER_NETWORK, tx.nVersion);
if (sz > 5000)
{
LogPrint("mempool", "ignoring large orphan tx (size: %u, hash: %s)\n", sz, hash.ToString());
@ -639,7 +639,7 @@ unsigned int LimitOrphanTxSize(unsigned int nMaxOrphans)
bool IsStandardTx(const CTransaction& tx, string& reason)
{
if (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1) {
if (tx.nVersion > CTransaction::MAX_CURRENT_VERSION || tx.nVersion < CTransaction::MIN_CURRENT_VERSION) {
reason = "version";
return false;
}

View File

@ -137,7 +137,7 @@ std::string CTxOut::ToString() const
return strprintf("CTxOut(nValue=%d.%08d, scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30));
}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), nLockTime(0) {}
CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime),
vjoinsplit(tx.vjoinsplit), joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)
{
@ -154,7 +154,7 @@ void CTransaction::UpdateHash() const
*const_cast<uint256*>(&hash) = SerializeHash(*this);
}
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
CTransaction::CTransaction() : nVersion(CTransaction::MIN_CURRENT_VERSION), vin(), vout(), nLockTime(0), vjoinsplit(), joinSplitPubKey(), joinSplitSig() { }
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), vjoinsplit(tx.vjoinsplit),
joinSplitPubKey(tx.joinSplitPubKey), joinSplitSig(tx.joinSplitSig)

View File

@ -309,7 +309,9 @@ private:
public:
typedef boost::array<unsigned char, 64> joinsplit_sig_t;
static const int32_t CURRENT_VERSION=1;
// Transactions that include a list of JoinSplits are version 2.
static const int32_t MIN_CURRENT_VERSION = 1;
static const int32_t MAX_CURRENT_VERSION = 2;
// The local variables are made const to prevent unintended modification
// without updating the cached hash value. However, CTransaction is not

View File

@ -590,4 +590,55 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
BOOST_CHECK(!IsStandardTx(t, reason));
}
BOOST_AUTO_TEST_CASE(test_IsStandardV2)
{
LOCK(cs_main);
CBasicKeyStore keystore;
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
std::vector<CMutableTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
CMutableTransaction t;
t.vin.resize(1);
t.vin[0].prevout.hash = dummyTransactions[0].GetHash();
t.vin[0].prevout.n = 1;
t.vin[0].scriptSig << std::vector<unsigned char>(65, 0);
t.vout.resize(1);
t.vout[0].nValue = 90*CENT;
CKey key;
key.MakeNewKey(true);
t.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
string reason;
// A v2 transaction with no JoinSplits is still standard.
t.nVersion = 2;
BOOST_CHECK(IsStandardTx(t, reason));
// ... and with one JoinSplit.
t.vjoinsplit.push_back(JSDescription());
BOOST_CHECK(IsStandardTx(t, reason));
// ... and when that JoinSplit takes from a transparent input.
JSDescription *jsdesc = &t.vjoinsplit[0];
jsdesc->vpub_old = 10*CENT;
t.vout[0].nValue -= 10*CENT;
BOOST_CHECK(IsStandardTx(t, reason));
// A v2 transaction with JoinSplits but no transparent inputs is standard.
jsdesc->vpub_old = 0;
jsdesc->vpub_new = 100*CENT;
t.vout[0].nValue = 90*CENT;
t.vin.resize(0);
BOOST_CHECK(IsStandardTx(t, reason));
// v2 transactions can still be non-standard for the same reasons as v1.
t.vout[0].nValue = 501; // dust
BOOST_CHECK(!IsStandardTx(t, reason));
// v3 is not standard.
t.nVersion = 3;
t.vout[0].nValue = 90*CENT;
BOOST_CHECK(!IsStandardTx(t, reason));
}
BOOST_AUTO_TEST_SUITE_END()