Added supporting tx to adding input

This commit is contained in:
Evan 2014-03-27 11:43:45 -07:00
parent eb8bda3bb5
commit cfaff69931
6 changed files with 113 additions and 72 deletions

View File

@ -843,8 +843,10 @@ bool CTxMemPool::acceptable(CValidationState &state, CTransaction &tx, bool fChe
uint256 hash = tx.GetHash();
{
LOCK(cs);
if (mapTx.count(hash))
if (mapTx.count(hash)) {
printf("false1\n");
return false;
}
}
// Check for conflicts with in-memory transactions
@ -853,6 +855,7 @@ bool CTxMemPool::acceptable(CValidationState &state, CTransaction &tx, bool fChe
COutPoint outpoint = tx.vin[i].prevout;
if (mapNextTx.count(outpoint))
{
printf("false2\n");
// Disable replacement feature for now
return false;
}
@ -869,23 +872,28 @@ bool CTxMemPool::acceptable(CValidationState &state, CTransaction &tx, bool fChe
view.SetBackend(viewMemPool);
// do we already have it?
if (view.HaveCoins(hash))
if (view.HaveCoins(hash)){
printf("false3\n");
return false;
}
// do all inputs exist?
// Note that this does not check for the presence of actual outputs (see the next check for that),
// only helps filling in pfMissingInputs (to determine missing vs spent).
BOOST_FOREACH(const CTxIn txin, tx.vin) {
if (!view.HaveCoins(txin.prevout.hash)) {
if (pfMissingInputs)
if (pfMissingInputs)
*pfMissingInputs = true;
printf("false4\n");
return false;
}
}
// are the actual inputs available?
if (!tx.HaveInputs(view))
if (!tx.HaveInputs(view)) {
printf("false5\n");
return state.Invalid(error("CTxMemPool::accept() : inputs already spent"));
}
// Bring the best block into scope
view.GetBestBlock();
@ -895,8 +903,10 @@ bool CTxMemPool::acceptable(CValidationState &state, CTransaction &tx, bool fChe
}
// Check for non-standard pay-to-script-hash in inputs
if (!tx.AreInputsStandard(view) && !fTestNet)
if (!tx.AreInputsStandard(view) && !fTestNet) {
printf("false6\n");
return error("CTxMemPool::accept() : nonstandard transaction input");
}
// Note: if you modify this code to accept non-standard transactions, then
// you should add code here to check that the transaction does a
@ -906,15 +916,18 @@ bool CTxMemPool::acceptable(CValidationState &state, CTransaction &tx, bool fChe
// Don't accept it if it can't get into a block
int64 txMinFee = tx.GetMinFee(1000, true, GMF_RELAY);
if (fLimitFree && nFees < txMinFee)
if (fLimitFree && nFees < txMinFee) {
printf("false7\n");
return error("CTxMemPool::accept() : not enough fees %s, %"PRI64d" < %"PRI64d,
hash.ToString().c_str(),
nFees, txMinFee);
}
// Check against previous transactions
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC))
{
printf("false8\n");
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().c_str());
}
}
@ -3298,14 +3311,6 @@ bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlert
@ -3730,16 +3735,23 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
CTxIn in;
int64 nAmount;
CTransaction txCollateral;
vRecv >> session_id >> in >> nAmount >> txCollateral;
CTransaction txSupporting;
vRecv >> session_id >> in >> nAmount >> txCollateral >> txSupporting;
if(session_id != darkSendPool.GetSessionID()){
printf("CDarkSendPool()::%s - stale session \n", strCommand.c_str());
return false;
}
if(txSupporting != CTransaction()) {
CValidationState state;
bool fMissingInputs = false;
txSupporting.AcceptToMemoryPool(state, true, true, &fMissingInputs);
}
//check to see if input is spent already? (and probably not confirmed)
if(darkSendPool.AddInput(in, nAmount, txCollateral)){
RelayTxPoolIn(session_id, in, nAmount, txCollateral);
RelayTxPoolIn(session_id, in, nAmount, txCollateral, txSupporting);
darkSendPool.Check();
}
}
@ -5341,13 +5353,13 @@ void CDarkSendPool::AddQueuedInput()
BOOST_FOREACH(const CDarkSendTransaction dst, vDST) {
if(fDebug) printf("CDarkSendPool::AddQueuedInput: adding my input\n");
AddInput(dst.fromAddress, dst.fromAddress_nValue, dst.txCollateral);
RelayTxPoolIn(session_id, dst.fromAddress, dst.fromAddress_nValue, dst.txCollateral);
RelayTxPoolIn(session_id, dst.fromAddress, dst.fromAddress_nValue, dst.txCollateral, dst.txSupporting); //*** ! do I need this here?
}
for(unsigned int i = 0; i < queuedVin.size(); i++){
if(fDebug) printf("CDarkSendPool::AddQueuedInput: adding queued input %u\n", i);
AddInput(queuedVin[i], queuedVinAmount[i], queuedVinCollateral[i]);
RelayTxPoolIn(session_id, queuedVin[i], queuedVinAmount[i], queuedVinCollateral[i]);
RelayTxPoolIn(session_id, queuedVin[i], queuedVinAmount[i], queuedVinCollateral[i], CTransaction());
}
queuedVin.clear();
queuedVinAmount.clear();
@ -5363,11 +5375,11 @@ void CDarkSendPool::AddQueuedOutput()
BOOST_FOREACH(const CDarkSendTransaction dst, vDST) {
if(fDebug) printf("CDarkSendPool::AddQueuedOutput: adding my output\n");
AddOutput(dst.theirAddress, dst.theirAddressEnc, dst.txCollateral);
RelayTxPoolOut(session_id, dst.theirAddress, dst.theirAddressEnc, dst.txCollateral);
RelayTxPoolOut(session_id, dst.theirAddress, dst.theirAddressEnc, dst.txCollateral); //*** ! do I need this here?
if(fDebug) printf("CDarkSendPool::AddQueuedOutput: adding my output -- change\n");
AddOutput(dst.changeAddress, dst.changeAddressEnc, dst.txCollateral);
RelayTxPoolOut(session_id, dst.changeAddress, dst.changeAddressEnc, dst.txCollateral);
RelayTxPoolOut(session_id, dst.changeAddress, dst.changeAddressEnc, dst.txCollateral); //*** ! do I need this here?
}
for(unsigned int i = 0; i < queuedVout.size(); i++){
@ -5599,7 +5611,8 @@ void CDarkSendPool::ChargeFees(){
}
std::string CDarkSendPool::Denominate(){
return pwalletMain->Denominate();
CWalletTx wtxDenominate = CWalletTx();
return pwalletMain->Denominate(wtxDenominate);
}
void CDarkSendPool::CheckTimeout(){
@ -5687,27 +5700,21 @@ bool CDarkSendPool::SignatureValid(CScript& newSig, const CTxIn& theVin, const C
return true;
}
bool CDarkSendPool::IsCollateralValid(const CTransaction& txCollateral){
bool CDarkSendPool::IsCollateralValid(const CTransaction& txCollateral){
CValidationState valState;
if (!txCollateral.CheckTransaction(valState)){
if(fDebug) printf ("CDarkSendPool::IsCollateralValid - invalid transaction\n");
if(txCollateral.vout.size() != 1){
if(fDebug) printf ("CDarkSendPool::IsCollateralValid - vout wrong size\n");
return false;
}
bool foundCollateralAddr = false;
bool foundCollateralAmount = false;
BOOST_FOREACH(CTxOut v, txCollateral.vout){
if(v.scriptPubKey == collateralPubKey) {
foundCollateralAddr = true;
if(v.nValue == POOL_FEE_AMOUNT){
foundCollateralAmount = true;
}
}
if(txCollateral.vin.size() != 1){
if(fDebug) printf ("CDarkSendPool::IsCollateralValid - vin wrong size\n");
return false;
}
if (!foundCollateralAmount || !foundCollateralAddr) {
if(fDebug) printf ("CDarkSendPool::IsCollateralValid - not correct amount or addr\n");
if(txCollateral.vout[0].scriptPubKey != collateralPubKey ||
txCollateral.vout[0].nValue != POOL_FEE_AMOUNT) {
if(fDebug) printf ("CDarkSendPool::IsCollateralValid - not correct amount or addr (0)\n");
return false;
}
@ -5850,7 +5857,7 @@ void CDarkSendPool::CatchUpNode(CNode* pfrom){
if(fDebug) printf("CDarkSendPool::CatchUpNode\n");
for(unsigned int i = 0; i < vin.size(); i++){
if(fDebug) printf("CDarkSendPool::CatchUpNode -- add vin %u\n", i);
pfrom->PushMessage("dsi", session_id, vin[i], vinAmount[i], vinCollateral[i]);
pfrom->PushMessage("dsi", session_id, vin[i], vinAmount[i], vinCollateral[i], CTransaction());
}
for(unsigned int i = 0; i < vout.size(); i++){
@ -5864,7 +5871,7 @@ void CDarkSendPool::CatchUpNode(CNode* pfrom){
}
}
void CDarkSendPool::SendMoney(const CTransaction& txCollateral, const CTxIn& from, const CTxOut& to, int64& nFeeRet, CKeyStore& newKeys, int64 from_nValue, CScript& pubScript, CReserveKey& newReserveKey){
void CDarkSendPool::SendMoney(const CTransaction& txCollateral, const CTxIn& from, const CTxOut& to, int64& nFeeRet, CKeyStore& newKeys, int64 from_nValue, CScript& pubScript, CReserveKey& newReserveKey, const CTransaction& txSupporting){
printf("CDarkSendPool::SendMoney() - Added transaction to pool.\n");
/*
@ -5873,11 +5880,6 @@ void CDarkSendPool::SendMoney(const CTransaction& txCollateral, const CTxIn& fro
*/
if(fDebug){
printf("CDarkSendPool::SendMoney() - from_nValue %+"PRI64d"\n", from_nValue);
printf("CDarkSendPool::SendMoney() - nFeeRet %+"PRI64d"\n", from_nValue);
printf("CDarkSendPool::SendMoney() - to.nValue %+"PRI64d"\n", to.nValue);
printf("CDarkSendPool::SendMoney() - from_nValue-to.nValue-nFeeRet %+"PRI64d"\n", from_nValue-to.nValue-nFeeRet);
printf("CDarkSendPool::SendMoney() -- NEW INPUT -- adding %s\n", from.ToString().c_str());
}
@ -5898,7 +5900,7 @@ void CDarkSendPool::SendMoney(const CTransaction& txCollateral, const CTxIn& fro
CTxOut change = CTxOut(from_nValue-to.nValue-nFeeRet, scriptChange);
CDarkSendTransaction dst;
dst.Add(from_nValue, from, pubScript, to, change, nFeeRet, GetRand(999999), GetRand(999999), txCollateral);
dst.Add(from_nValue, from, pubScript, to, change, nFeeRet, GetRand(999999), GetRand(999999), txCollateral, txSupporting);
vDST.push_back(dst);
keystore = &newKeys;

View File

@ -2307,10 +2307,10 @@ public:
int64 changeAddressEnc;
int64 nFeeRet;
CTransaction txCollateral;
CTransaction txSupporting;
CDarkSendTransaction()
{
printf("CDarkSendTransaction::INIT()\n");
SetNull();
}
@ -2318,8 +2318,6 @@ public:
void SetNull()
{
printf("CDarkSendTransaction::SetNull\n");
nFeeRet = 0;
fromAddress_nValue = 0;
fromAddress = CTxIn();
@ -2327,16 +2325,15 @@ public:
changeAddress = CTxOut();
isSet = false;
printf("CDarkSendTransaction::SetNull::exit \n");
txCollateral = CTransaction();
txSupporting = CTransaction();
}
bool Add(int64 newFromAddress_nValue, const CTxIn& newFromAddress, const CScript& pubScript, const CTxOut& newTheirAddress,
const CTxOut& newChangeAddress, int64 newFeeRet, int64 theirEnc, int64 changeEnc, CTransaction newTxCollateral)
const CTxOut& newChangeAddress, int64 newFeeRet, int64 theirEnc, int64 changeEnc, CTransaction newTxCollateral, CTransaction newTxSupporting)
{
if(isSet){return false;}
printf("CDarkSendTransaction::Add \n");
fromAddress = newFromAddress;
fromAddress.prevPubKey = pubScript;
fromAddress_nValue = newFromAddress_nValue;
@ -2346,6 +2343,7 @@ public:
theirAddressEnc = theirEnc;
changeAddressEnc = changeEnc;
txCollateral = newTxCollateral;
txSupporting = newTxSupporting;
isSet = true;
return true;
@ -2532,7 +2530,7 @@ public:
bool AddOutput(const CTxOut& newOutput, const int64 newOutEnc, const CTransaction& txCollateral);
bool AddScriptSig(CScript& newSig, const CTxIn& theVin, const CScript& pubKey);
void CatchUpNode(CNode* pfrom);
void SendMoney(const CTransaction& txCollateral, const CTxIn& from, const CTxOut& to, int64& nFeeRet, CKeyStore& newKeys, int64 from_nValue, CScript& pubScript, CReserveKey& reservekey);
void SendMoney(const CTransaction& txCollateral, const CTxIn& from, const CTxOut& to, int64& nFeeRet, CKeyStore& newKeys, int64 from_nValue, CScript& pubScript, CReserveKey& newReserveKey, const CTransaction& txSupporting);
void AddQueuedSignatures();
std::string Denominate();
bool AddFinalTransaction(CTransaction& txNewFinalTransaction);

View File

@ -1939,15 +1939,14 @@ void RelayTxPoolFinalTransaction(const int64 session_id, const CTransaction& txN
}
}
void RelayTxPoolIn(const int64 session_id, const CTxIn& tx, const int64& nAmount, const CTransaction& txCollateral)
void RelayTxPoolIn(const int64 session_id, const CTxIn& tx, const int64& nAmount, const CTransaction& txCollateral, const CTransaction& txSupporting)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
if(!pnode->fRelayTxes)
continue;
pnode->PushMessage("dsi", session_id, tx, nAmount, txCollateral);
pnode->PushMessage("dsi", session_id, tx, nAmount, txCollateral, txSupporting);
}
}

View File

@ -645,7 +645,7 @@ void RelayTransaction(const CTransaction& tx, const uint256& hash, const CDataSt
void RelayTxPool(const int64 session_id, const unsigned int state);
void RelayTxPoolFinalTransaction(const int64 session_id, const CTransaction& txNew);
void RelayGetTxPool();
void RelayTxPoolIn(const int64 session_id, const CTxIn& tx, const int64& nAmount, const CTransaction& txCollateral);
void RelayTxPoolIn(const int64 session_id, const CTxIn& tx, const int64& nAmount, const CTransaction& txCollateral, const CTransaction& txSupporting);
void RelayTxPoolOut(const int64 session_id, const CTxOut& tx, const int64 voutEnc, const CTransaction& txCollateral);
void RelayTxPoolSig(const int64 session_id, const CScript& sig, const CTxIn& vin, const CScript& pubKey);
void RelayTxPoolForceReset();

View File

@ -1228,7 +1228,7 @@ bool CWallet::SelectCoinsExactOutput(int64 nTargetValue, CTxIn& vin, int64& nVal
BOOST_FOREACH(const COutput& out, vCoins)
{
//printf("Checking input %"PRI64d" > %"PRI64d"\n", out.tx->vout[out.i].nValue, nTargetValue);
if(out.tx->vout[out.i].nValue == nTargetValue){ //more than min
if(out.tx->vout[out.i].nValue == nTargetValue){ //exactly
vin = CTxIn(out.tx->GetHash(),out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
nValueRet = out.tx->vout[out.i].nValue;
@ -1242,6 +1242,31 @@ bool CWallet::SelectCoinsExactOutput(int64 nTargetValue, CTxIn& vin, int64& nVal
return false;
}
bool CWallet::SelectCoinsMoreThanOutput(int64 nTargetValue, CTxIn& vin, int64& nValueRet, CScript& pubScript, bool confirmed, const CCoinControl* coinControl) const
{
vector<COutput> vCoins;
AvailableCoins2(vCoins, confirmed);
// coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
{
//printf("has coinControl\n");
BOOST_FOREACH(const COutput& out, vCoins)
{
printf("2 Checking input %"PRI64d" > %"PRI64d"\n", out.tx->vout[out.i].nValue, nTargetValue);
if(out.tx->vout[out.i].nValue >= nTargetValue){ //more than min
vin = CTxIn(out.tx->GetHash(),out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
nValueRet = out.tx->vout[out.i].nValue;
printf("2 Found unspent output more than nValue\n");
return true;
}
}
}
printf("2 Can't find unspent output, run denominate\n");
return false;
}
bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend,
CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl, bool noDenominatedInputs)
{
@ -1531,7 +1556,7 @@ string CWallet::DarkSendMoney(const CTxDestination& address, int64 nValue)
}
CReserveKey reservekey(this);
CWalletTx wtxCollateral;
CTransaction txCollateral;
// Parse Bitcoin address
CScript scriptPubKey;
@ -1558,11 +1583,11 @@ string CWallet::DarkSendMoney(const CTxDestination& address, int64 nValue)
int64 nValueIn = 0;
CScript pubScript = CScript();
CTxIn vin;
CWalletTx wtxDenominate = CWalletTx();
// try once before we try to denominate
if (!SelectCoinsExactOutput(10*COIN, vin, nValueIn, pubScript, true, coinControl))
{
Denominate();
Denominate(wtxDenominate);
}
@ -1577,6 +1602,26 @@ string CWallet::DarkSendMoney(const CTxDestination& address, int64 nValue)
// create another transaction as collateral for using DarkSend
{
CScript pubScript2 = CScript();
int64 nValueIn2 = 0;
CTxIn Vin = CTxIn();
CTxOut Vout = CTxOut(POOL_FEE_AMOUNT, darkSendPool.collateralPubKey);
if (!SelectCoinsExactOutput(POOL_FEE_AMOUNT+(0.01*COIN), Vin, nValueIn2, pubScript2, true, coinControl))
{
return _("Error: The DarkSend collateral transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!");
}
txCollateral.vin.push_back(Vin);
txCollateral.vout.push_back(Vout);
if(!SignSignature(*this, pubScript2, txCollateral, 0, int(SIGHASH_ALL|SIGHASH_ANYONECANPAY))) {
return _("CDarkSendPool::Sign - Unable to sign collateral transaction!!! GAH! \n");
}
LockCoin(Vin.prevout);
/*
int64 nValue = POOL_FEE_AMOUNT;
int64 nFeeRequired;
@ -1585,22 +1630,20 @@ string CWallet::DarkSendMoney(const CTxDestination& address, int64 nValue)
if (!CreateTransaction(darkSendPool.collateralPubKey, nValue, wtxCollateral, reservekey, nFeeRequired, strError))
{
if (nValue + nFeeRequired > GetBalance())
strError = strprintf(_("Error: The DarkSend collateral transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds!"), FormatMoney(nFeeRequired).c_str());
printf("DarkSendMoney() : %s\n", strError.c_str());
return strError;
}
}
} */
}
LockCoin(vin.prevout);
CTxOut out(nValue, scriptPubKey);
darkSendPool.SendMoney((CTransaction)wtxCollateral, vin, out, nFeeRet, *this, nValueIn, pubScript, reservekey);
darkSendPool.SendMoney(txCollateral, vin, out, nFeeRet, *this, nValueIn, pubScript, reservekey, wtxDenominate);
return "";
}
std::string CWallet::Denominate()
std::string CWallet::Denominate(CWalletTx& wtxDenominate)
{
int count = 10;
@ -1630,8 +1673,6 @@ std::string CWallet::Denominate()
while(!done && count > 0)
{
CWalletTx wtxNew;
CWalletTx wtxNew2;
vector< pair<CScript, int64> > vecSend;
printf("Creating transaction\n");
@ -1642,9 +1683,9 @@ std::string CWallet::Denominate()
}
printf("Creating\n");
if(CreateTransaction(vecSend, wtxNew, reservekey, nFeeRequired, strError, NULL, true)){
if(CreateTransaction(vecSend, wtxDenominate, reservekey, nFeeRequired, strError, NULL, true)){
printf("Committing\n");
if (CommitTransaction(wtxNew, reservekey)) {
if (CommitTransaction(wtxDenominate, reservekey)) {
//if successfull, create the collateral needed to submit
done = true;
successful = count;

View File

@ -73,7 +73,6 @@ private:
bool SelectCoinsWithoutDenomination(int64 nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet, const CCoinControl *coinControl=NULL) const;
bool SelectCoinsExactOutput(int64 nTargetValue, CTxIn& vin, int64& nValueRet, CScript& pubScript, bool confirmed, const CCoinControl* coinControl) const;
CWalletDB *pwalletdbEncryption;
// the current wallet version: clients below this version are not able to load the wallet
@ -83,6 +82,8 @@ private:
int nWalletMaxVersion;
public:
bool SelectCoinsMoreThanOutput(int64 nTargetValue, CTxIn& vin, int64& nValueRet, CScript& pubScript, bool confirmed, const CCoinControl* coinControl) const;
mutable CCriticalSection cs_wallet;
bool fFileBacked;
@ -127,7 +128,7 @@ public:
// check whether we are allowed to upgrade (or already support) to the named feature
bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
std::string Denominate();
std::string Denominate(CWalletTx& wtxDenominate);
void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL, bool noDenominatedInputs=false) const;
void AvailableCoins2(std::vector<COutput>& vCoins, bool fOnlyConfirmed) const;
bool SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;