Fix applying transactions with a local destination to the wallet.

This commit is contained in:
JoelKatz
2012-01-20 13:43:07 -08:00
parent 5d08754104
commit 50e23112e3
3 changed files with 46 additions and 16 deletions

View File

@@ -22,14 +22,14 @@ protected:
uint64 mAmount; uint64 mAmount;
uint32 mTag; uint32 mTag;
std::string mComment; std::string mComment;
bool mPaid; bool mPaid, mCredited;
Transaction::pointer mTransaction; Transaction::pointer mTransaction;
public: public:
LocalTransaction(const uint160 &dest, uint64 amount, uint32 tag) : LocalTransaction(const uint160 &dest, uint64 amount, uint32 tag) :
mDestAcctID(dest), mAmount(amount), mTag(tag), mPaid(false) { ; } mDestAcctID(dest), mAmount(amount), mTag(tag), mPaid(false), mCredited(false) { ; }
void setComment(const std::string& comment) { mComment=comment; } void setComment(const std::string& comment) { mComment=comment; }
const uint160& getDestinationAccount() const { return mDestAcctID; } const uint160& getDestinationAccount() const { return mDestAcctID; }
@@ -43,6 +43,9 @@ public:
bool isPaid() const { return mPaid; } bool isPaid() const { return mPaid; }
void setPaid() { mPaid=true; } void setPaid() { mPaid=true; }
void setUnpaid() { mPaid=false; } void setUnpaid() { mPaid=false; }
bool isCredited() const { return mCredited; }
void setCredited() { mCredited=true; }
void setUncredited() { mCredited=false; }
void performTransaction(); // perform this transaction as if we received it from the network void performTransaction(); // perform this transaction as if we received it from the network
bool makeTransaction(); // create a transaction object according to these rules bool makeTransaction(); // create a transaction object according to these rules

View File

@@ -43,6 +43,9 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
if((r==Ledger::TR_PREASEQ) || (r==Ledger::TR_BADLSEQ)) if((r==Ledger::TR_PREASEQ) || (r==Ledger::TR_BADLSEQ))
{ // transaction should be held { // transaction should be held
#ifdef DEBUG
std::cerr << "Transaction should be held" << std::endl;
#endif
trans->setStatus(HELD); trans->setStatus(HELD);
trans->save(); trans->save();
theApp->getMasterLedger().addHeldTransaction(trans); theApp->getMasterLedger().addHeldTransaction(trans);
@@ -50,12 +53,18 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
} }
if( (r==Ledger::TR_PASTASEQ) || (r==Ledger::TR_ALREADY) ) if( (r==Ledger::TR_PASTASEQ) || (r==Ledger::TR_ALREADY) )
{ // duplicate or conflict { // duplicate or conflict
#ifdef DEBUG
std::cerr << "Transaction is obsolete" << std::endl;
#endif
trans->setStatus(OBSOLETE); trans->setStatus(OBSOLETE);
return trans; return trans;
} }
if(r==Ledger::TR_SUCCESS) if(r==Ledger::TR_SUCCESS)
{ {
#ifdef DEBUG
std::cerr << "Transaction is now included, synching to wallet" << std::endl;
#endif
trans->setStatus(INCLUDED); trans->setStatus(INCLUDED);
theApp->getWallet().applyTransaction(trans); theApp->getWallet().applyTransaction(trans);

View File

@@ -820,47 +820,65 @@ void Wallet::applyTransaction(Transaction::pointer txn)
TransStatus st=txn->getStatus(); TransStatus st=txn->getStatus();
bool shouldBePaid=(st==INCLUDED) || (st==HELD) || (st==NEW); bool shouldBePaid=(st==INCLUDED) || (st==HELD) || (st==NEW);
LocalTransaction::pointer ltx;
boost::recursive_mutex::scoped_lock sl(mLock); boost::recursive_mutex::scoped_lock sl(mLock);
std::map<uint160, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getFromAccount()); std::map<uint256, LocalTransaction::pointer>::iterator lti=mTransactions.find(txn->getID());
if(lti!=mTransactions.end()) ltx=lti->second;
std::map<uint160, LocalAccount::pointer>::iterator lac=mAccounts.find(txn->getToAccount());
if(lac!=mAccounts.end())
{ // this is to a local account
if(!ltx)
{ // this is to a local account, and we don't have a local transaction for it
ltx=LocalTransaction::pointer(new
LocalTransaction(txn->getToAccount(), txn->getAmount(), txn->getIdent()));
ltx->setTransaction(txn);
mTransactions.insert(std::make_pair<uint256, LocalTransaction::pointer>(txn->getID(), ltx));
ltx->setCredited();
lac->second->credit(txn->getAmount()-txn->getFee());
}
}
lac=mAccounts.find(txn->getFromAccount());
if(lac==mAccounts.end()) return; if(lac==mAccounts.end()) return;
if ( (st!=INVALID) && (lac->second->getTxnSeq()==txn->getFromAccountSeq()) ) if ( (st!=INVALID) && (lac->second->getTxnSeq()==txn->getFromAccountSeq()) )
lac->second->incTxnSeq(); lac->second->incTxnSeq();
std::map<uint256, LocalTransaction::pointer>::iterator ltx=mTransactions.find(txn->getID()); if(!ltx)
if(ltx==mTransactions.end())
{ // we don't have this transactions { // we don't have this transactions
if(shouldBePaid) if(shouldBePaid)
{ // we need it { // we need it
LocalTransaction::pointer nlt(new ltx=LocalTransaction::pointer(new
LocalTransaction(txn->getToAccount(), txn->getAmount(), txn->getIdent())); LocalTransaction(txn->getToAccount(), txn->getAmount(), txn->getIdent()));
nlt->setTransaction(txn); ltx->setTransaction(txn);
mTransactions.insert(std::make_pair<uint256, LocalTransaction::pointer>(txn->getID(), nlt)); mTransactions.insert(std::make_pair<uint256, LocalTransaction::pointer>(txn->getID(), ltx));
lac->second->debit(txn->getAmount()); lac->second->debit(txn->getAmount());
ltx->second->setPaid(); ltx->setPaid();
} }
} }
else else
{ // we have this transaction in some form (ltx->second) { // we have this transaction in some form (ltx->second)
if( (st==COMMITTED) || (st==INVALID) ) if( (st==COMMITTED) || (st==INVALID) )
{ // we need to remove it { // we need to remove it
if(ltx->second->isPaid()) if(ltx->isPaid())
{ {
lac->second->credit(txn->getAmount()); lac->second->credit(txn->getAmount());
ltx->second->setUnpaid(); ltx->setUnpaid();
} }
mTransactions.erase(txn->getID()); mTransactions.erase(txn->getID());
} }
else if(ltx->second->isPaid() && !shouldBePaid) else if(ltx->isPaid() && !shouldBePaid)
{ // we paid for this transaction and it didn't happen { // we paid for this transaction and it didn't happen
lac->second->credit(txn->getAmount()); lac->second->credit(txn->getAmount());
ltx->second->setUnpaid(); ltx->setUnpaid();
} }
else if(!ltx->second->isPaid() && shouldBePaid) else if(!ltx->isPaid() && shouldBePaid)
{ // this transaction happened, and we haven't paid locally { // this transaction happened, and we haven't paid locally
lac->second->debit(txn->getAmount()); lac->second->debit(txn->getAmount());
ltx->second->setPaid(); ltx->setPaid();
} }
} }
} }