mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-10 23:07:52 +00:00
Define dust transaction outputs, and make them non-standard
This commit is contained in:
parent
b8e1dc2e53
commit
8de9bb53af
@ -384,7 +384,7 @@ bool CTransaction::IsStandard() const
|
||||
BOOST_FOREACH(const CTxOut& txout, vout) {
|
||||
if (!::IsStandard(txout.scriptPubKey))
|
||||
return false;
|
||||
if (txout.nValue == 0)
|
||||
if (txout.IsDust())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
18
src/main.h
18
src/main.h
@ -439,6 +439,24 @@ public:
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return sizeof(nValue)+scriptPubKey.size();
|
||||
}
|
||||
|
||||
bool IsDust() const
|
||||
{
|
||||
// "Dust" is defined in terms of MIN_RELAY_TX_FEE, which
|
||||
// has units satoshis-per-kilobyte.
|
||||
// If you'd pay more than 1/3 in fees
|
||||
// to spend something, then we consider it dust.
|
||||
// A typical txout is 32 bytes big, and will
|
||||
// need a CTxIn of at least 148 bytes to spend,
|
||||
// so dust is a txout less than 54 uBTC
|
||||
// (5400 satoshis)
|
||||
return ((nValue*1000)/(3*(size()+148)) < MIN_RELAY_TX_FEE);
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
if (scriptPubKey.size() < 6)
|
||||
|
@ -78,7 +78,9 @@ BOOST_AUTO_TEST_CASE(sign)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
txFrom.vout[i].scriptPubKey = evalScripts[i];
|
||||
txFrom.vout[i].nValue = COIN;
|
||||
txFrom.vout[i+4].scriptPubKey = standardScripts[i];
|
||||
txFrom.vout[i+4].nValue = COIN;
|
||||
}
|
||||
BOOST_CHECK(txFrom.IsStandard());
|
||||
|
||||
@ -169,6 +171,7 @@ BOOST_AUTO_TEST_CASE(set)
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
txFrom.vout[i].scriptPubKey = outer[i];
|
||||
txFrom.vout[i].nValue = CENT;
|
||||
}
|
||||
BOOST_CHECK(txFrom.IsStandard());
|
||||
|
||||
@ -179,7 +182,7 @@ BOOST_AUTO_TEST_CASE(set)
|
||||
txTo[i].vout.resize(1);
|
||||
txTo[i].vin[0].prevout.n = i;
|
||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||
txTo[i].vout[0].nValue = 1;
|
||||
txTo[i].vout[0].nValue = 1*CENT;
|
||||
txTo[i].vout[0].scriptPubKey = inner[i];
|
||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
||||
}
|
||||
|
@ -242,24 +242,34 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
||||
BOOST_CHECK(!t1.AreInputsStandard(coins));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_GetThrow)
|
||||
BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||
{
|
||||
CBasicKeyStore keystore;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(coinsDummy);
|
||||
std::vector<CTransaction> dummyTransactions = SetupDummyInputs(keystore, coins);
|
||||
|
||||
CTransaction t1;
|
||||
t1.vin.resize(3);
|
||||
t1.vin[0].prevout.hash = dummyTransactions[0].GetHash();
|
||||
t1.vin[0].prevout.n = 0;
|
||||
t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();;
|
||||
t1.vin[1].prevout.n = 0;
|
||||
t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();;
|
||||
t1.vin[2].prevout.n = 1;
|
||||
t1.vout.resize(2);
|
||||
t1.vout[0].nValue = 90*CENT;
|
||||
t1.vout[0].scriptPubKey << OP_1;
|
||||
CTransaction 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.SetDestination(key.GetPubKey().GetID());
|
||||
|
||||
BOOST_CHECK(t.IsStandard());
|
||||
|
||||
t.vout[0].nValue = 5011; // dust
|
||||
BOOST_CHECK(!t.IsStandard());
|
||||
|
||||
t.vout[0].nValue = 6011; // not dust
|
||||
BOOST_CHECK(t.IsStandard());
|
||||
|
||||
t.vout[0].scriptPubKey = CScript() << OP_1;
|
||||
BOOST_CHECK(!t.IsStandard());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
@ -21,13 +21,12 @@ static vector<COutput> vCoins;
|
||||
|
||||
static void add_coin(int64 nValue, int nAge = 6*24, bool fIsFromMe = false, int nInput=0)
|
||||
{
|
||||
static int i;
|
||||
CTransaction* tx = new CTransaction;
|
||||
tx->nLockTime = i++; // so all transactions get different hashes
|
||||
tx->vout.resize(nInput+1);
|
||||
tx->vout[nInput].nValue = nValue;
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, *tx);
|
||||
delete tx;
|
||||
static int nextLockTime = 0;
|
||||
CTransaction tx;
|
||||
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
|
||||
tx.vout.resize(nInput+1);
|
||||
tx.vout[nInput].nValue = nValue;
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
||||
if (fIsFromMe)
|
||||
{
|
||||
// IsFromMe() returns (GetDebit() > 0), and GetDebit() is 0 if vin.empty(),
|
||||
@ -55,8 +54,8 @@ static bool equal_sets(CoinSet a, CoinSet b)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(coin_selection_tests)
|
||||
{
|
||||
static CoinSet setCoinsRet, setCoinsRet2;
|
||||
static int64 nValueRet;
|
||||
CoinSet setCoinsRet, setCoinsRet2;
|
||||
int64 nValueRet;
|
||||
|
||||
// test multiple times to allow for differences in the shuffle order
|
||||
for (int i = 0; i < RUN_TESTS; i++)
|
||||
|
@ -1162,7 +1162,12 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
|
||||
double dPriority = 0;
|
||||
// vouts to the payees
|
||||
BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
|
||||
wtxNew.vout.push_back(CTxOut(s.second, s.first));
|
||||
{
|
||||
CTxOut txout(s.second, s.first);
|
||||
if (txout.IsDust())
|
||||
return false;
|
||||
wtxNew.vout.push_back(txout);
|
||||
}
|
||||
|
||||
// Choose coins to use
|
||||
set<pair<const CWalletTx*,unsigned int> > setCoins;
|
||||
@ -1208,9 +1213,21 @@ bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CW
|
||||
CScript scriptChange;
|
||||
scriptChange.SetDestination(vchPubKey.GetID());
|
||||
|
||||
// Insert change txn at random position:
|
||||
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
|
||||
wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
|
||||
CTxOut newTxOut(nChange, scriptChange);
|
||||
|
||||
// Never create dust outputs; if we would, just
|
||||
// add the dust to the fee.
|
||||
if (newTxOut.IsDust())
|
||||
{
|
||||
nFeeRet += nChange;
|
||||
reservekey.ReturnKey();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Insert change txn at random position:
|
||||
vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
|
||||
wtxNew.vout.insert(position, newTxOut);
|
||||
}
|
||||
}
|
||||
else
|
||||
reservekey.ReturnKey();
|
||||
|
Loading…
Reference in New Issue
Block a user