diff --git a/LocalTransaction.cpp b/LocalTransaction.cpp index 7f51b188c9..195f750c88 100644 --- a/LocalTransaction.cpp +++ b/LocalTransaction.cpp @@ -32,7 +32,7 @@ bool LocalTransaction::makeTransaction() return true; } -void LocalTransaction::applyTransaction() +void LocalTransaction::performTransaction() { mTransaction=theApp->getOPs().processTransaction(mTransaction); } diff --git a/LocalTransaction.h b/LocalTransaction.h index ce16c0fe7f..1d5eb7c927 100644 --- a/LocalTransaction.h +++ b/LocalTransaction.h @@ -22,23 +22,30 @@ protected: uint64 mAmount; uint32 mTag; std::string mComment; + bool mPaid; Transaction::pointer mTransaction; public: LocalTransaction(const uint160 &dest, uint64 amount, uint32 tag) : - mDestAcctID(dest), mAmount(amount), mTag(tag) { ; } + mDestAcctID(dest), mAmount(amount), mTag(tag), mPaid(false) { ; } void setComment(const std::string& comment) { mComment=comment; } const uint160& getDestinationAccount() const { return mDestAcctID; } uint64 getAmount() const { return mAmount; } uint32 getTag() const { return mTag; } const std::string& getComment() const { return mComment; } - Transaction::pointer getTransaction() { return mTransaction; } - void applyTransaction(); - bool makeTransaction(); + Transaction::pointer getTransaction() { return mTransaction; } + void setTransaction(Transaction::pointer t) { mTransaction=t; } + + bool isPaid() const { return mPaid; } + void setPaid() { mPaid=true; } + void setUnpaid() { mPaid=false; } + + void performTransaction(); // perform this transaction as if we received it from the network + bool makeTransaction(); // create a transaction object according to these rules }; #endif diff --git a/NetworkOPs.cpp b/NetworkOPs.cpp index 332ed511a4..2e22b70213 100644 --- a/NetworkOPs.cpp +++ b/NetworkOPs.cpp @@ -56,8 +56,9 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans) if(r==Ledger::TR_SUCCESS) { - // WRITEME: send to others trans->setStatus(INCLUDED); + // WRITEME: send to others + theApp->getWallet().applyTransaction(trans); return trans; } diff --git a/RPCServer.cpp b/RPCServer.cpp index 25b68a129f..1beadb7854 100644 --- a/RPCServer.cpp +++ b/RPCServer.cpp @@ -365,7 +365,7 @@ Json::Value RPCServer::doSendTo(Json::Value& params) LocalTransaction::pointer lt(new LocalTransaction(destAccount, iAmount, iTag)); if(!lt->makeTransaction()) return JSONRPCError(500, "Insufficient funds in unlocked accounts"); - lt->applyTransaction(); + lt->performTransaction(); return lt->getTransaction()->getJson(true); } diff --git a/Wallet.cpp b/Wallet.cpp index 620110e77d..85b274c7cf 100644 --- a/Wallet.cpp +++ b/Wallet.cpp @@ -812,3 +812,53 @@ void Wallet::syncToLedger(bool force, Ledger* ledger) } if(mLedgergetLedgerSeq()) mLedger=ledger->getLedgerSeq(); } + +void Wallet::applyTransaction(Transaction::pointer txn) +{ + TransStatus st=txn->getStatus(); + bool shouldBePaid=(st==INCLUDED) || (st==HELD) || (st==NEW); + + boost::recursive_mutex::scoped_lock sl(mLock); + + std::map::iterator lac=mAccounts.find(txn->getFromAccount()); + if(lac==mAccounts.end()) return; + + if ( (st!=INVALID) && (lac->second->getTxnSeq()==txn->getFromAccountSeq()) ) + lac->second->incTxnSeq(); + + std::map::iterator ltx=mTransactions.find(txn->getID()); + if(ltx==mTransactions.end()) + { // we don't have this transactions + if(shouldBePaid) + { // we need it + LocalTransaction::pointer nlt(new + LocalTransaction(txn->getToAccount(), txn->getAmount(), txn->getIdent())); + nlt->setTransaction(txn); + mTransactions.insert(std::make_pair(txn->getID(), nlt)); + lac->second->debit(txn->getAmount()); + ltx->second->setPaid(); + } + } + else + { // we have this transaction in some form (ltx->second) + if( (st==COMMITTED) || (st==INVALID) ) + { // we need to remove it + if(ltx->second->isPaid()) + { + lac->second->credit(txn->getAmount()); + ltx->second->setUnpaid(); + } + mTransactions.erase(txn->getID()); + } + else if(ltx->second->isPaid() && !shouldBePaid) + { // we paid for this transaction and it didn't happen + lac->second->credit(txn->getAmount()); + ltx->second->setUnpaid(); + } + else if(!ltx->second->isPaid() && shouldBePaid) + { // this transaction happened, and we haven't paid locally + lac->second->debit(txn->getAmount()); + ltx->second->setPaid(); + } + } +} diff --git a/Wallet.h b/Wallet.h index 7423231e7e..6866d05d08 100644 --- a/Wallet.h +++ b/Wallet.h @@ -80,6 +80,7 @@ public: static uint256 textToPrivKey(const std::string&); void syncToLedger(bool force, Ledger* ledger); + void applyTransaction(Transaction::pointer); static bool unitTest(); };