From 271283b930ff532280dbc1fa9856f11151846a41 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 19 Apr 2012 03:45:15 -0700 Subject: [PATCH 01/38] Update comments. --- src/SHAMap.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/SHAMap.h b/src/SHAMap.h index 9cc20ff06d..d1b9c6ccb7 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -95,12 +95,11 @@ private: public: - // for transactions + SHAMapItem(const uint256& tag) : mTag(tag) { ; } SHAMapItem(const uint256& tag, const std::vector& data); SHAMapItem(const std::vector& data); // tag by hash - // for account balances - SHAMapItem(const uint160& tag, const std::vector& data); + SHAMapItem(const uint160& tag, const std::vector& data); // deprecated const uint256& getTag() const { return mTag; } std::vector getData() const { return mData.getData(); } From 7c7ee23c646e42d4c58c80369e5972f4927c7f21 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 19 Apr 2012 03:45:23 -0700 Subject: [PATCH 02/38] Cleanup. --- src/ScopedLock.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ScopedLock.h b/src/ScopedLock.h index f9abc51ecb..e0e65ddfac 100644 --- a/src/ScopedLock.h +++ b/src/ScopedLock.h @@ -4,6 +4,11 @@ #include #include #include +#include +#include + +// A lock holder that can be returned and copied by value +// When the last reference goes away, the lock is released class ScopedLock { @@ -11,9 +16,9 @@ protected: mutable boost::shared_ptr > mHolder; public: - ScopedLock(boost::recursive_mutex &mutex) : - mHolder(new boost::interprocess::scoped_lock(mutex)) - { ; } + ScopedLock(boost::recursive_mutex& mutex) : + mHolder(boost::make_shared >(boost::ref(mutex))) + { ; } void lock() const { mHolder->lock(); From 693df8bb8aff4d003984aae8bad30db3a00f0221 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 19 Apr 2012 03:45:33 -0700 Subject: [PATCH 03/38] Missing function Ledger::writeBack --- src/LedgerNode.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index 05156e657a..21238792ea 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -3,6 +3,27 @@ #include "boost/make_shared.hpp" +LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SerializedLedgerEntry::pointer entry) +{ + ScopedLock l(mAccountStateMap->Lock()); + bool create = false; + + if (!mAccountStateMap->hasItem(entry->getIndex())) + { + if ((parms & lepCREATE) == 0) + return lepMISSING; + create = true; + } + + SHAMapItem::pointer item = boost::make_shared(entry->getIndex()); + entry->add(item->peekSerializer()); + + if (!mAccountStateMap->updateGiveItem(item, false)) + return lepERROR; + + return create ? lepCREATED : lepOKAY; +} + SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const uint160& accountID) { uint256 nodeID=getAccountRootIndex(accountID); From 3b6fca362b6394ecebc0efcba236fa320ae7a4ed Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Thu, 19 Apr 2012 06:16:02 -0700 Subject: [PATCH 04/38] Add nickname node functions. Simplify. --- src/Ledger.h | 3 +++ src/LedgerNode.cpp | 64 +++++++++++++++++++++++++++++++++------------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/Ledger.h b/src/Ledger.h index 96c9347e34..7c670c1c41 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -77,6 +77,9 @@ protected: static Ledger::pointer getSQL(const std::string& sqlStatement); + SerializedLedgerEntry::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID, + LedgerEntryType let); + public: Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash, diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index 21238792ea..0669ca8c7d 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -24,12 +24,9 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SerializedLedgerEntry return create ? lepCREATED : lepOKAY; } -SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const uint160& accountID) +SerializedLedgerEntry::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, + LedgerEntryType let ) { - uint256 nodeID=getAccountRootIndex(accountID); - - ScopedLock l(mAccountStateMap->Lock()); - SHAMapItem::pointer account = mAccountStateMap->peekItem(nodeID); if (!account) { @@ -39,26 +36,57 @@ SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, c return SerializedLedgerEntry::pointer(); } - parms = lepCREATED; - SerializedLedgerEntry::pointer sle=boost::make_shared(ltACCOUNT_ROOT); + parms = parms | lepCREATED | lepOKAY; + SerializedLedgerEntry::pointer sle=boost::make_shared(let); sle->setIndex(nodeID); return sle; } + SerializedLedgerEntry::pointer sle = + boost::make_shared(account->peekSerializer(), nodeID); + + if(sle->getType() != let) + { // maybe it's a currency or something + parms = parms | lepWRONGTYPE; + return SerializedLedgerEntry::pointer(); + } + + parms = parms | lepOKAY; + return sle; + +} + +SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const uint160& accountID) +{ + uint256 nodeID=getAccountRootIndex(accountID); + + ScopedLock l(mAccountStateMap->Lock()); + try { - SerializedLedgerEntry::pointer sle = - boost::make_shared(account->peekSerializer(), nodeID); - - if(sle->getType() != ltACCOUNT_ROOT) - { // maybe it's a currency or something - parms = lepWRONGTYPE; - return SerializedLedgerEntry::pointer(); - } - parms = lepOKAY; - return sle; + return getASNode(parms, nodeID, ltACCOUNT_ROOT); } - catch(...) + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + +SerializedLedgerEntry::pointer Ledger::getNickname(LedgerStateParms& parms, const std::string& nickname) +{ + return getNickname(parms, Serializer::getSHA512Half(nickname)); +} + +SerializedLedgerEntry::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& nickHash) +{ + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, nickHash, ltNICKNAME); + } + catch (...) { parms = lepERROR; return SerializedLedgerEntry::pointer(); From ad8ff1280316d31e168275eee241e4818683d57d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 13:30:18 -0700 Subject: [PATCH 05/38] Fix mishandling of signing account. Fix failure to set transaction type. --- src/SerializedTransaction.cpp | 27 +++++++++++------ src/SerializedTransaction.h | 14 +++++---- src/Transaction.cpp | 55 +++++++++++++++++------------------ 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index a4a94b3675..2282f051d4 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -1,9 +1,9 @@ #include "SerializedTransaction.h" -SerializedTransaction::SerializedTransaction(TransactionType type) +SerializedTransaction::SerializedTransaction(TransactionType type) : mType(type) { - mFormat=getTxnFormat(type); + mFormat = getTxnFormat(type); if (mFormat == NULL) throw std::runtime_error("invalid transaction type"); mMiddleTxn.giveObject(new STUInt32("Magic", TransactionMagic)); @@ -31,13 +31,21 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length mMiddleTxn.giveObject(new STVariableLength("SigningAccount", sit.getVL())); mMiddleTxn.giveObject(new STUInt32("Sequence", sit.get32())); - int type = sit.get32(); - mMiddleTxn.giveObject(new STUInt32("Type", type)); - mFormat = getTxnFormat(static_cast(type)); + mType = static_cast(sit.get32()); + mMiddleTxn.giveObject(new STUInt32("Type", static_cast(mType))); + mFormat = getTxnFormat(mType); if (!mFormat) throw std::runtime_error("Transaction has invalid type"); mMiddleTxn.giveObject(new STUInt64("Fee", sit.get64())); mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction"); + updateSigningAccount(); +} + +void SerializedTransaction::updateSigningAccount() +{ + NewcoinAddress a; + a.setAccountPublic(peekRawSigningAccount()); + mSigningAccount = a.getAccountID(); } int SerializedTransaction::getLength() const @@ -81,7 +89,7 @@ bool SerializedTransaction::isEquivalent(const SerializedType& t) const { // Signatures are not compared const SerializedTransaction* v = dynamic_cast(&t); if (!v) return false; - if (type != v->type) return false; + if (mType != v->mType) return false; if (mMiddleTxn != v->mMiddleTxn) return false; if (mInnerTxn != v->mInnerTxn) return false; return true; @@ -171,7 +179,7 @@ void SerializedTransaction::setSequence(uint32 seq) v->setValue(seq); } -std::vector SerializedTransaction::getSigningAccount() const +std::vector SerializedTransaction::getRawSigningAccount() const { const STVariableLength* v = dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningAccount)); @@ -179,7 +187,7 @@ std::vector SerializedTransaction::getSigningAccount() const return v->getValue(); } -const std::vector& SerializedTransaction::peekSigningAccount() const +const std::vector& SerializedTransaction::peekRawSigningAccount() const { const STVariableLength* v= dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningAccount)); @@ -187,7 +195,7 @@ const std::vector& SerializedTransaction::peekSigningAccount() co return v->peekValue(); } -std::vector& SerializedTransaction::peekSigningAccount() +std::vector& SerializedTransaction::peekRawSigningAccount() { STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningAccount)); if (!v) throw std::runtime_error("corrupt transaction"); @@ -199,6 +207,7 @@ void SerializedTransaction::setSigningAccount(const std::vector& STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningAccount)); if (!v) throw std::runtime_error("corrupt transaction"); v->setValue(s); + updateSigningAccount(); } int SerializedTransaction::getITFieldIndex(SOE_Field field) const diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 142e93f200..3ebe854240 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -15,11 +15,14 @@ public: typedef boost::shared_ptr pointer; protected: - TransactionType type; + uint160 mSigningAccount; + TransactionType mType; STVariableLength mSignature; STObject mMiddleTxn, mInnerTxn; TransactionFormat* mFormat; + void updateSigningAccount(); + public: SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit SerializedTransaction(TransactionType type); @@ -42,12 +45,13 @@ public: // middle transaction functions uint32 getVersion() const; void setVersion(uint32); - TransactionType getTxnType() const { return type; } + TransactionType getTxnType() const { return mType; } uint64 getTransactionFee() const; void setTransactionFee(uint64); - std::vector getSigningAccount() const; - const std::vector& peekSigningAccount() const; - std::vector& peekSigningAccount(); + uint160 getSigningAccount() const; + std::vector getRawSigningAccount() const; + const std::vector& peekRawSigningAccount() const; + std::vector& peekRawSigningAccount(); void setSigningAccount(const std::vector& s); std::string getTransactionType() const { return mFormat->t_name; } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index bd54e6b1c2..a999e2dc8e 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -14,53 +14,52 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAddress& toAccount, uint64 amount, uint32 ident, uint32 ledger) : mInLedger(0), mStatus(NEW) { - mAccountFrom=fromLocalAccount->getAddress(); - mAccountTo=toAccount; + mAccountFrom = fromLocalAccount->getAddress(); + mAccountTo = toAccount; - mTransaction=boost::make_shared(ttMAKE_PAYMENT); + mTransaction = boost::make_shared(ttMAKE_PAYMENT); - mFromPubKey=fromLocalAccount->getPublicKey(); + mFromPubKey = fromLocalAccount->getPublicKey(); assert(mFromPubKey); mTransaction->setSigningAccount(mFromPubKey->GetPubKey()); mTransaction->setSequence(fromLocalAccount->getTxnSeq()); - assert(mTransaction->getSequence()!=0); + assert(mTransaction->getSequence() != 0); mTransaction->setTransactionFee(100); // for now mTransaction->setITFieldVL(sfDestination, toAccount.getAccountPublic()); mTransaction->setITFieldU64(sfAmount, amount); - if(ledger!=0) + if (ledger != 0) { mTransaction->makeITFieldPresent(sfTargetLedger); mTransaction->setITFieldU32(sfTargetLedger, ledger); } - if(ident!=0) + if (ident != 0) { mTransaction->makeITFieldPresent(sfSourceTag); mTransaction->setITFieldU32(sfSourceTag, ident); } assert(mFromPubKey); - if(!sign(fromLocalAccount)) + if (!sign(fromLocalAccount)) { #ifdef DEBUG std::cerr << "Unable to sign transaction" << std::endl; #endif - mStatus=INCOMPLETE; + mStatus = INCOMPLETE; } } Transaction::Transaction(SerializedTransaction::pointer sit, bool validate) : mStatus(INVALID), mTransaction(sit) { - uint160 toAccountID; - uint160 fromAccountID; + uint160 toAccountID, fromAccountID; std::vector pubKey; try { - toAccountID=mTransaction->getITFieldH160(sfDestination); - pubKey=mTransaction->getSigningAccount(); - mTransactionID=mTransaction->getTransactionID(); + toAccountID = mTransaction->getITFieldH160(sfDestination); + pubKey = mTransaction->getRawSigningAccount(); + mTransactionID = mTransaction->getTransactionID(); } catch(...) { @@ -70,13 +69,13 @@ Transaction::Transaction(SerializedTransaction::pointer sit, bool validate) : mS mAccountTo.setAccountID(toAccountID); mAccountFrom.setAccountID(fromAccountID); - mFromPubKey=boost::make_shared(); - if(!mFromPubKey->SetPubKey(pubKey)) return; + mFromPubKey = boost::make_shared(); + if (!mFromPubKey->SetPubKey(pubKey)) return; mAccountFrom.setAccountPublic(pubKey); - mFromPubKey=theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); + mFromPubKey = theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); - if(!validate || checkSign()) - mStatus=NEW; + if (!validate || checkSign()) + mStatus = NEW; } Transaction::Transaction(const std::vector& raw, bool validate) : mStatus(INVALID) @@ -89,22 +88,22 @@ Transaction::Transaction(const std::vector& raw, bool validate) : { Serializer s(raw); SerializerIterator sit(s); - mTransaction=boost::make_shared(boost::ref(sit), -1); + mTransaction = boost::make_shared(boost::ref(sit), -1); - mFromPubKey=boost::make_shared(); - if(!mFromPubKey->SetPubKey(pubKey)) return; + mFromPubKey = boost::make_shared(); + if (!mFromPubKey->SetPubKey(pubKey)) return; mAccountFrom.setAccountPublic(pubKey); - mFromPubKey=theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); - if(!mFromPubKey->SetPubKey(pubKey)) return; + mFromPubKey = theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); + if (!mFromPubKey->SetPubKey(pubKey)) return; mAccountFrom.setAccountPublic(pubKey); - mFromPubKey=theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); + mFromPubKey = theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); } - catch(...) + catch (...) { return; } - if(!validate || checkSign()) - mStatus=NEW; + if (!validate || checkSign()) + mStatus = NEW; } Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID, From 31d65b222e3aa5f796cc89a084281e7e0f14676e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 17:42:17 -0700 Subject: [PATCH 06/38] Missing from previous commit. --- src/SerializedTransaction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 3ebe854240..12dc81a59e 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -48,7 +48,7 @@ public: TransactionType getTxnType() const { return mType; } uint64 getTransactionFee() const; void setTransactionFee(uint64); - uint160 getSigningAccount() const; + uint160 getSigningAccount() const { return mSigningAccount; } std::vector getRawSigningAccount() const; const std::vector& peekRawSigningAccount() const; std::vector& peekRawSigningAccount(); From 8372b0d57268643aa31517f1d3db33053b58b487 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 17:42:37 -0700 Subject: [PATCH 07/38] Some additional return codes for the transaction engine. --- src/TransactionEngine.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index b454c20f06..fc8774e53a 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -12,11 +12,13 @@ enum TransactionEngineResult { // <0 = Can never succeed, 0 = success, >0 = failed, but could succeed + terFAILED = -4, // Something broke horribly terUNKNOWN = -3, // The transactions requires logic not implemented yet terINSUF_FEE_P = -2, // fee totally insufficient terINVALID = -1, // The transaction is ill-formed terSUCCESS = 0, // The transaction was applied terALREADY, // The transaction was already in the ledger + terNO_ACCOUNT, // The source account does not exist terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load) terUNFUNDED, // Source account had insufficient balance terNO_PATH, // No path existed or met transaction/balance requirements From f6f9ba4d08c41cb7c472a51f28a8b85f6acf6dc0 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 17:42:54 -0700 Subject: [PATCH 08/38] Missing functions, and an easy way to specify no special parameters. --- src/Ledger.cpp | 6 ++++++ src/Ledger.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index b22fdcd2b7..abac688f71 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -160,6 +160,12 @@ bool Ledger::addTransaction(Transaction::pointer trans) return mTransactionMap->addGiveItem(item, true); } +bool Ledger::addTransaction(const uint256& txID, const Serializer& txn) +{ // low-level - just add to table + SHAMapItem::pointer item = boost::make_shared(txID, txn.peekData()); + return mTransactionMap->addGiveItem(item, true); +} + bool Ledger::delTransaction(const uint256& transID) { assert(!mAccepted); diff --git a/src/Ledger.h b/src/Ledger.h index 7c670c1c41..f23d796304 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -20,6 +20,8 @@ enum LedgerStateParms { + lepNONE = 0, // no special flags + // input flags lepCREATE, // Create if not present @@ -33,6 +35,7 @@ enum LedgerStateParms class Ledger : public boost::enable_shared_from_this { // The basic Ledger structure, can be opened, closed, or synching + friend class TransactionEngine; public: typedef boost::shared_ptr pointer; @@ -73,6 +76,7 @@ protected: bool addAccountState(AccountState::pointer); bool updateAccountState(AccountState::pointer); bool addTransaction(Transaction::pointer); + bool addTransaction(const uint256& id, const Serializer& txn); bool delTransaction(const uint256& id); static Ledger::pointer getSQL(const std::string& sqlStatement); From 7b82cbcbe8a193673f79afeadbbb55197cfffcc1 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 20:09:04 -0700 Subject: [PATCH 09/38] This function is completed -- applyTransaction. It needs helper functions. --- src/TransactionEngine.cpp | 83 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/TransactionEngine.cpp diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp new file mode 100644 index 0000000000..34a77ace8d --- /dev/null +++ b/src/TransactionEngine.cpp @@ -0,0 +1,83 @@ + +#include "TransactionEngine.h" +#include "TransactionFormats.h" + +TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, + TransactionEngineParams params) +{ + uint256 txID = txn.getTransactionID(); + if(!txID) return terINVALID; + + // extract signing key + CKey acctKey; + if (!acctKey.SetPubKey(txn.getRawSigningAccount())) return terINVALID; + + // check signature + if (!txn.checkSign(acctKey)) return terINVALID; + + // WRITEME: Check fee + + // get source account ID + uint160 srcAccount = txn.getSigningAccount(); + if (!srcAccount) return terINVALID; + + boost::recursive_mutex::scoped_lock sl(mLedger->mLock); + + // find source account + LedgerStateParms qry = lepNONE; + SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount); + if(!src) return terNO_ACCOUNT; + + // validate sequence + uint32 t_seq = txn.getSequence(); + uint32 a_seq = src->getIFieldU32(sfSequence); + if (t_seq != a_seq) + { + // WRITEME: Special case code for changing transaction key + if (a_seq < t_seq) return terPRE_SEQ; + if (mLedger->hasTransaction(txID)) + return terALREADY; + return terPAST_SEQ; + } + + TransactionEngineResult result = terUNKNOWN; + switch(txn.getTxnType()) + { + case ttINVALID: + result = terINVALID; + break; + + case ttMAKE_PAYMENT: + result = doPayment(txn, *src); + break; + + case ttINVOICE: + result = doInvoice(txn, *src); + break; + + case ttEXCHANGE_OFFER: + result = doOffer(txn, *src); + break; + + default: + result = terUNKNOWN; + break; + } + + if (result == terSUCCESS) + { // Write back the source account state and add the transaction to the ledger + // WRITEME: Special case code for changing transaction key + src->setIFieldU32(sfSequence, t_seq); + if(mLedger->writeBack(lepNONE, src) & lepERROR) + { + assert(false); + return terFAILED; + } + + Serializer s; + txn.add(s); + mLedger->addTransaction(txID, s); + } + + return result; +} From 9a50a0e4f1364a33adaa53bff31ffcd6352525d9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 20:21:27 -0700 Subject: [PATCH 10/38] Helper function for STAccount->uint160 inside an object. --- src/SerializedTransaction.cpp | 12 ++++++++++++ src/SerializedTransaction.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 2282f051d4..fc785f4e36 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -210,6 +210,18 @@ void SerializedTransaction::setSigningAccount(const std::vector& updateSigningAccount(); } +uint160 SerializedTransaction::GetITFieldAccount(SOE_Field field) +{ + uint160 r; + SerializedType* st = mInnerTxn.getPField(field); + if (!st) return r; + + STAccount *ac = dynamic_cast(ac); + if (!ac) return r; + ac->getValueH160(r); + return r; +} + int SerializedTransaction::getITFieldIndex(SOE_Field field) const { return mInnerTxn.getFieldIndex(field); diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 12dc81a59e..452ba283f3 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -76,6 +76,7 @@ public: uint32 getITFieldU32(SOE_Field field) const { return mInnerTxn.getValueFieldU32(field); } uint64 getITFieldU64(SOE_Field field) const { return mInnerTxn.getValueFieldU64(field); } uint160 getITFieldH160(SOE_Field field) const { return mInnerTxn.getValueFieldH160(field); } + uint160 getITFieldAccount(SOE_Field field) const; uint256 getITFieldH256(SOE_Field field) const { return mInnerTxn.getValueFieldH256(field); } std::vector getITFieldVL(SOE_Field field) const { return mInnerTxn.getValueFieldVL(field); } std::vector getITFieldTL(SOE_Field field) const { return mInnerTxn.getValueFieldTL(field); } From 5a9050aa696146393e8584848707b2a07c41e883 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Fri, 20 Apr 2012 20:21:42 -0700 Subject: [PATCH 11/38] Bugfix. --- src/SerializedTypes.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 64b3ab7e3e..088c0c6083 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -199,7 +199,7 @@ void STAccount::setValueH160(const uint160& v) bool STAccount::getValueH160(uint160& v) const { if (!isValueH160()) return false; - memcpy(v.begin(), &(peekValue().front()), 32); + memcpy(v.begin(), &(peekValue().front()), 20); return true; } From 585d800fb4fce67694ecdc016922a1d4e62661c7 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 21 Apr 2012 02:20:09 -0700 Subject: [PATCH 12/38] Bug fixes. --- src/SerializedTransaction.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index fc785f4e36..497c9aac9f 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -210,13 +210,13 @@ void SerializedTransaction::setSigningAccount(const std::vector& updateSigningAccount(); } -uint160 SerializedTransaction::GetITFieldAccount(SOE_Field field) +uint160 SerializedTransaction::getITFieldAccount(SOE_Field field) const { uint160 r; - SerializedType* st = mInnerTxn.getPField(field); + const SerializedType* st = mInnerTxn.peekAtPField(field); if (!st) return r; - STAccount *ac = dynamic_cast(ac); + const STAccount* ac = dynamic_cast(st); if (!ac) return r; ac->getValueH160(r); return r; From adf0313ab85ad0afb850eeee2af009f0beeb767a Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 22 Apr 2012 16:27:55 -0700 Subject: [PATCH 13/38] Transaction fee handling. --- src/TransactionEngine.cpp | 52 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 34a77ace8d..7d5d8b62d0 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -15,7 +15,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // check signature if (!txn.checkSign(acctKey)) return terINVALID; - // WRITEME: Check fee + uint64 txnFee = txn.getTransactionFee(); + if ( (params & tepNO_CHECK_FEE) != tepNONE) + { + // WRITEME: Check if fee is adequate + if (txnFee == 0) return terINSUF_FEE_P; + } // get source account ID uint160 srcAccount = txn.getSigningAccount(); @@ -26,7 +31,14 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // find source account LedgerStateParms qry = lepNONE; SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount); - if(!src) return terNO_ACCOUNT; + if (!src) return terNO_ACCOUNT; + + // deduct the fee, so it's not available during the transaction + // we only write the account back if the transaction succeeds + uint64 balance = src->getIFieldU64(sfBalance); + if (balance < txnFee) + return terINSUF_FEE_B; + src->setIFieldU64(sfBalance, balance - txnFee); // validate sequence uint32 t_seq = txn.getSequence(); @@ -81,3 +93,39 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return result; } + +TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doOffer(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doCancel(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doStore(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction&, SerializedLedgerEntry& source) +{ + return terUNKNOWN; +} + From 82644c4c00f4f4b51dd25dd2b2e722cf7ff4d6b6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 22 Apr 2012 16:28:24 -0700 Subject: [PATCH 14/38] Additional error codes. "No param" parameter for TransactionEngineParms. TEP helper functions. --- src/TransactionEngine.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index fc8774e53a..80fd3c0ec8 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -19,8 +19,10 @@ enum TransactionEngineResult terSUCCESS = 0, // The transaction was applied terALREADY, // The transaction was already in the ledger terNO_ACCOUNT, // The source account does not exist + terNO_TARGET, // The destination does not exist terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load) - terUNFUNDED, // Source account had insufficient balance + terINSUF_FEE_B, // Account balance can't pay fee + terUNFUNDED, // Source account had insufficient balance for transactin terNO_PATH, // No path existed or met transaction/balance requirements terPAST_SEQ, // This sequence number has already past terPRE_SEQ, // Missing/inapplicable prior transaction @@ -29,6 +31,7 @@ enum TransactionEngineResult enum TransactionEngineParams { + tepNONE = 0, tepNO_CHECK_SIGN = 1, // Signature already checked tepNO_CHECK_FEE = 2, // It was voted into a ledger anyway }; @@ -56,4 +59,14 @@ public: TransactionEngineResult applyTransaction(const SerializedTransaction&, TransactionEngineParams); }; +inline TransactionEngineParams operator|(const TransactionEngineParams& l1, const TransactionEngineParams& l2) +{ + return static_cast(static_cast(l1) | static_cast(l2)); +} + +inline TransactionEngineParams operator&(const TransactionEngineParams& l1, const TransactionEngineParams& l2) +{ + return static_cast(static_cast(l1) & static_cast(l2)); +} + #endif From 003ec1af1ee2706c7bb69a7cb12340b1eda06ec9 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 22 Apr 2012 18:47:59 -0700 Subject: [PATCH 15/38] Missing helper functions. --- src/SerializedLedger.h | 2 ++ src/SerializedObject.cpp | 16 ++++++++++++++++ src/SerializedObject.h | 1 + 3 files changed, 19 insertions(+) diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 3634c74881..af462de6b5 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -60,6 +60,8 @@ public: { return mObject.setValueFieldVL(field, v); } void setIFieldTL(SOE_Field field, const std::vector& v) { return mObject.setValueFieldTL(field, v); } + void setIFieldAccount(SOE_Field field, const uint160& account) + { return mObject.setValueFieldAccount(field, account); } bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); } void makeIFieldPresent(SOE_Field field) { return mObject.makeFieldPresent(field); } diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 7498cdf46d..18117d29a2 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -452,6 +452,22 @@ void STObject::setValueFieldH160(SOE_Field field, const uint160& v) cf->setValue(v); } +void STObject::setValueFieldAccount(SOE_Field field, const uint160& v) +{ + SerializedType* rf = getPField(field); + if (!rf) throw std::runtime_error("Field not found"); + SerializedTypeID id = rf->getSType(); + if (id == STI_OBJECT) + { + makeFieldPresent(field); + rf = getPField(field); + id = rf->getSType(); + } + STAccount* cf = dynamic_cast(rf); + if (!cf) throw std::runtime_error("Wrong field type"); + cf->setValueH160(v); +} + void STObject::setValueFieldVL(SOE_Field field, const std::vector& v) { SerializedType* rf = getPField(field); diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 06bd3bcd29..ce2bbb9f8b 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -113,6 +113,7 @@ public: void setValueFieldH256(SOE_Field field, const uint256&); void setValueFieldVL(SOE_Field field, const std::vector&); void setValueFieldTL(SOE_Field field, const std::vector&); + void setValueFieldAccount(SOE_Field field, const uint160&); bool isFieldPresent(SOE_Field field) const; void makeFieldPresent(SOE_Field field); From a5e8ab6943c806068a01384400cde95f82e64fdf Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 22 Apr 2012 19:14:06 -0700 Subject: [PATCH 16/38] Handle make payment for native currencies. Keep a vector of affected account state nodes to make atomicity easier. --- src/TransactionEngine.cpp | 98 +++++++++++++++++++++++++++++++-------- src/TransactionEngine.h | 24 +++++++--- 2 files changed, 95 insertions(+), 27 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 7d5d8b62d0..74cbe12e0e 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -1,5 +1,6 @@ #include "TransactionEngine.h" + #include "TransactionFormats.h" TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, @@ -51,7 +52,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return terALREADY; return terPAST_SEQ; } + else src->setIFieldU32(sfSequence, t_seq); + std::vector accounts; + accounts.push_back(std::make_pair(taaMODIFY, src)); TransactionEngineResult result = terUNKNOWN; switch(txn.getTxnType()) { @@ -60,15 +64,15 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran break; case ttMAKE_PAYMENT: - result = doPayment(txn, *src); + result = doPayment(txn, accounts); break; case ttINVOICE: - result = doInvoice(txn, *src); + result = doInvoice(txn, accounts); break; case ttEXCHANGE_OFFER: - result = doOffer(txn, *src); + result = doOffer(txn, accounts); break; default: @@ -77,13 +81,21 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran } if (result == terSUCCESS) - { // Write back the source account state and add the transaction to the ledger + { // Write back the account states and add the transaction to the ledger // WRITEME: Special case code for changing transaction key - src->setIFieldU32(sfSequence, t_seq); - if(mLedger->writeBack(lepNONE, src) & lepERROR) + for(std::vector::iterator it=accounts.begin(), end=accounts.end(); + it != end; ++it) { - assert(false); - return terFAILED; + if ( (it->first==taaMODIFY) || (it->first==taaCREATE) ) + { + if(mLedger->writeBack(lepNONE, it->second) & lepERROR) + assert(false); + } + else if (it->first == taaDELETE) + { + if(!mLedger->peekAccountStateMap()->delItem(it->second->getIndex())) + assert(false); + } } Serializer s; @@ -94,38 +106,84 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return result; } -TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, + std::vector& accounts) +{ + uint32 txFlags = txn.getFlags(); + uint160 destAccount = txn.getITFieldAccount(sfDestination); + + // Does the destination account exist? + if (!destAccount) return terINVALID; + LedgerStateParms qry = lepNONE; + SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, destAccount); + if (!dest) + { // can this transaction create an account + if ((txFlags & 0x00010000) == 0) // no + return terNO_TARGET; + + dest = boost::make_shared(ltACCOUNT_ROOT); + dest->setIndex(Ledger::getAccountRootIndex(destAccount)); + dest->setIFieldAccount(sfAccount, destAccount); + dest->setIFieldU32(sfSequence, 1); + accounts.push_back(std::make_pair(taaCREATE, dest)); + } + else accounts.push_back(std::make_pair(taaMODIFY, dest)); + + uint64 amount = txn.getITFieldU64(sfAmount); + + uint160 currency; + if(txn.getITFieldPresent(sfCurrency)) + currency = txn.getITFieldH160(sfCurrency); + bool native = !!currency; + + if (native) + { + uint64 balance = accounts[0].second->getIFieldU64(sfBalance); + if (balance < amount) return terUNFUNDED; + accounts[0].second->setIFieldU64(sfBalance, balance - amount); + accounts[1].second->setIFieldU64(sfBalance, accounts[1].second->getIFieldU64(sfBalance) + amount); + } + else + { + // WRITEME: Handle non-native currencies, paths + return terUNKNOWN; + } + + return terUNKNOWN; +} + +TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } -TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction&, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doOffer(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } -TransactionEngineResult TransactionEngine::doOffer(const SerializedTransaction&, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } -TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction&, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doCancel(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } -TransactionEngineResult TransactionEngine::doCancel(const SerializedTransaction&, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doStore(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } -TransactionEngineResult TransactionEngine::doStore(const SerializedTransaction&, SerializedLedgerEntry& source) +TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction& txn, + std::vector& accounts) { return terUNKNOWN; } - -TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction&, SerializedLedgerEntry& source) -{ - return terUNKNOWN; -} - diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 80fd3c0ec8..f729a5a0cd 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -36,18 +36,28 @@ enum TransactionEngineParams tepNO_CHECK_FEE = 2, // It was voted into a ledger anyway }; +enum TransactionAccountAction +{ + taaACCESS, + taaCREATE, + taaMODIFY, + taaDELETE +}; + +typedef std::pair AffectedAccount; + class TransactionEngine { protected: Ledger::pointer mLedger; - TransactionEngineResult doPayment(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doInvoice(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doOffer(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doTake(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doCancel(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doStore(const SerializedTransaction&, SerializedLedgerEntry& source); - TransactionEngineResult doDelete(const SerializedTransaction&, SerializedLedgerEntry& source); + TransactionEngineResult doPayment(const SerializedTransaction&, std::vector&); + TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector&); + TransactionEngineResult doOffer(const SerializedTransaction&, std::vector&); + TransactionEngineResult doTake(const SerializedTransaction&, std::vector&); + TransactionEngineResult doCancel(const SerializedTransaction&, std::vector&); + TransactionEngineResult doStore(const SerializedTransaction&, std::vector&); + TransactionEngineResult doDelete(const SerializedTransaction&, std::vector&); public: TransactionEngine() { ; } From a641149834d1011cbc6b3918aa1537a06ae37f7f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sun, 22 Apr 2012 21:11:14 -0700 Subject: [PATCH 17/38] Wrong return value. --- src/TransactionEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 74cbe12e0e..ab71738199 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -149,7 +149,7 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction return terUNKNOWN; } - return terUNKNOWN; + return terSUCCESS; } TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction& txn, From cd73263f2f0d3b316e2fbd602c1a2a7294365b51 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:54:56 -0700 Subject: [PATCH 18/38] Rework AccountState to fit new model. --- src/AccountState.cpp | 48 ++++++++++++++++++-------------------------- src/AccountState.h | 38 ++++++++++------------------------- 2 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/AccountState.cpp b/src/AccountState.cpp index 166ab530f3..a3a61d2675 100644 --- a/src/AccountState.cpp +++ b/src/AccountState.cpp @@ -1,42 +1,32 @@ -#include - #include "AccountState.h" + +#include +#include + +#include "Ledger.h" #include "Serializer.h" -AccountState::AccountState(const std::vector& v) +AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mValid(false) { - Serializer s(v); - mValid=false; - uint160 acct160 = mAccountID.getAccountID(); - - if(!s.get160(acct160, 0)) { assert(false); return; } - if(!s.get64(mBalance, 20)) { assert(false); return; } - if(!s.get32(mAccountSeq, 28)) { assert(false); return; } - mValid=true; + if (!id.IsValid()) return; + mLedgerEntry = boost::make_shared(ltACCOUNT_ROOT); + mLedgerEntry->setIndex(Ledger::getAccountRootIndex(id)); + mLedgerEntry->setIFieldAccount(sfAccount, id); + mValid = true; } -AccountState::AccountState(const NewcoinAddress& id) : mAccountID(id), mBalance(0), mAccountSeq(0), mValid(true) -{ ; } - -std::vector AccountState::getRaw() const -{ // 20-byte acct ID, 8-byte balance, 4-byte sequence - Serializer s(32); - s.add160(mAccountID.getAccountID()); - s.add64(mBalance); - s.add32(mAccountSeq); - return s.getData(); +AccountState::AccountState(SerializedLedgerEntry::pointer ledgerEntry) : mLedgerEntry(ledgerEntry), mValid(false) +{ + if (!mLedgerEntry) return; + if (mLedgerEntry->getType()!=ltACCOUNT_ROOT) return; + mAccountID = mLedgerEntry->getValueFieldAccount(sfAccount); + if (mAccountID.IsValid()) mValid = true; } void AccountState::addJson(Json::Value& val) { - Json::Value as(Json::objectValue); - - as["AccountID"]=mAccountID.humanAccountID(); - as["Balance"]=boost::lexical_cast(mBalance); - as["SendSequence"]=mAccountSeq; - if(!mValid) as["Invalid"]=true; - - val[mAccountID.humanAccountID()]=as; + val = mLedgerEntry->getJson(0); + if(!mValid) val["Invalid"]=true; } // vim:ts=4 diff --git a/src/AccountState.h b/src/AccountState.h index f8a15c1680..f08a8c80b6 100644 --- a/src/AccountState.h +++ b/src/AccountState.h @@ -1,7 +1,8 @@ #ifndef __ACCOUNTSTATE__ #define __ACCOUNTSTATE__ -// An account's state in one or more accepted ledgers +// An account's state +// Used to track information about a local account #include @@ -10,8 +11,8 @@ #include "../json/value.h" #include "types.h" -#include "uint256.h" #include "NewcoinAddress.h" +#include "SerializedLedger.h" class AccountState { @@ -20,37 +21,20 @@ public: private: NewcoinAddress mAccountID; - uint64 mBalance; - uint32 mAccountSeq; + SerializedLedgerEntry::pointer mLedgerEntry; bool mValid; public: - AccountState(const NewcoinAddress& mAccountID); // new account - AccountState(const std::vector&); // raw form + AccountState(const NewcoinAddress& AccountID); // For new accounts + AccountState(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger const NewcoinAddress& getAccountID() const { return mAccountID; } - uint64 getBalance() const { return mBalance; } - uint32 getSeq() const { return mAccountSeq; } + uint64 getBalance() const { return mLedgerEntry->getIFieldU64(sfBalance); } + uint32 getSeq() const { return mLedgerEntry->getIFieldU32(sfSequence); } - void credit(const uint64& a) - { - mBalance+=a; - if(!mAccountSeq) mAccountSeq=1; // an account with non-0 balance cannot have 0 sequence - } - void charge(const uint64& a) - { - assert(mBalance>=a); - mBalance-=a; - } - void incSeq() - { - mAccountSeq++; - } - void decSeq() - { - assert(mAccountSeq!=0); - mAccountSeq--; - } + SerializedLedgerEntry::pointer getSLE() { return mLedgerEntry; } + const SerializedLedgerEntry& peekSLE() const { return *mLedgerEntry; } + SerializedLedgerEntry& peekSLE() { return *mLedgerEntry; } std::vector getRaw() const; void addJson(Json::Value& value); From b3773f1d52b23d9fce30ce5374d5b13ad49702f6 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:55:19 -0700 Subject: [PATCH 19/38] Typo. --- src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cpp b/src/Application.cpp index e092151cbe..eb1f53bde4 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -128,7 +128,7 @@ void Application::run() Application::~Application() { - delete mTxnDB;; + delete mTxnDB; delete mLedgerDB; delete mWalletDB; delete mHashNodeDB; From 59872be189ddeedd2d82fa7ccc29ab93910b1996 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:55:58 -0700 Subject: [PATCH 20/38] Remove obsolete ledger functionality. Update to use new code. --- src/Ledger.cpp | 186 ++++--------------------------------------------- src/Ledger.h | 21 +++--- 2 files changed, 24 insertions(+), 183 deletions(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index abac688f71..eb95633f6e 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -22,10 +22,11 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTransactionMap = boost::make_shared(); mAccountStateMap = boost::make_shared(); + // special case: put coins in root account AccountState::pointer startAccount = boost::make_shared(masterID); - startAccount->credit(startAmount); - if (!addAccountState(startAccount)) - assert(false); + startAccount->peekSLE().setIFieldU64(sfBalance, startAmount); + startAccount->peekSLE().setIFieldU32(sfSequence, 1); + writeBack(lepCREATE, startAccount->getSLE()); } Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash, @@ -116,7 +117,7 @@ AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID) std::cerr << "Ledger:getAccountState(" << accountID.humanAccountID() << ")" << std::endl; #endif ScopedLock l(mTransactionMap->Lock()); - SHAMapItem::pointer item = mAccountStateMap->peekItem(accountID.getAccountID().to256()); + SHAMapItem::pointer item = mAccountStateMap->peekItem(Ledger::getAccountRootIndex(accountID)); if (!item) { #ifdef DEBUG @@ -124,30 +125,10 @@ AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID) #endif return AccountState::pointer(); } - return boost::make_shared(item->getData()); -} - -uint64 Ledger::getBalance(const NewcoinAddress& accountID) const -{ - ScopedLock l(mTransactionMap->Lock()); - SHAMapItem::pointer item = mAccountStateMap->peekItem(accountID.getAccountID().to256()); - if (!item) return 0; - return AccountState(item->getData()).getBalance(); -} - -bool Ledger::updateAccountState(AccountState::pointer state) -{ - assert(!mAccepted); - return mAccountStateMap->updateGiveItem(boost::make_shared(state->getAccountID().getAccountID(), - state->getRaw()), false); -} - -bool Ledger::addAccountState(AccountState::pointer state) -{ - assert(!mAccepted); - assert( (state->getBalance()==0) || (state->getSeq()>0) ); - SHAMapItem::pointer item = boost::make_shared(state->getAccountID().getAccountID(), state->getRaw()); - return mAccountStateMap->addGiveItem(item, false); + SerializedLedgerEntry::pointer sle = + boost::make_shared(item->peekSerializer(), item->getTag()); + if (sle->getType() != ltACCOUNT_ROOT) return AccountState::pointer(); + return boost::make_shared(sle); } bool Ledger::addTransaction(Transaction::pointer trans) @@ -193,145 +174,6 @@ Transaction::pointer Ledger::getTransaction(const uint256& transID) const return txn; } -Ledger::TransResult Ledger::applyTransaction(Transaction::pointer trans) -{ - assert(!mAccepted); - boost::recursive_mutex::scoped_lock sl(mLock); - if (trans->getSourceLedger() > mLedgerSeq) return TR_BADLSEQ; - - if (trans->getAmount()getFee()) - { -#ifdef DEBUG - std::cerr << "Transaction for " << trans->getAmount() << ", but fee is " << - trans->getFee() << std::endl; -#endif - return TR_TOOSMALL; - } - - if(!mTransactionMap || !mAccountStateMap) return TR_ERROR; - try - { - // already applied? - Transaction::pointer dupTrans=getTransaction(trans->getID()); - if(dupTrans) return TR_ALREADY; - - // accounts exist? - AccountState::pointer fromAccount=getAccountState(trans->getFromAccount()); - AccountState::pointer toAccount=getAccountState(trans->getToAccount()); - - // temporary code -- if toAccount doesn't exist but fromAccount does, create it - if(!!fromAccount && !toAccount) - { - toAccount=boost::make_shared(trans->getToAccount()); - toAccount->incSeq(); // an account in a ledger has a sequence of 1 - updateAccountState(toAccount); - } - - if(!fromAccount || !toAccount) return TR_BADACCT; - - // pass sanity checks? - if(fromAccount->getBalance()getAmount()) - { -#ifdef DEBUG - std::cerr << "Transaction for " << trans->getAmount() << ", but account has " << - fromAccount->getBalance() << std::endl; -#endif - return TR_INSUFF; - } -#ifdef DEBUG - if(fromAccount->getSeq()!=trans->getFromAccountSeq()) - std::cerr << "aSeq=" << fromAccount->getSeq() << ", tSeq=" << trans->getFromAccountSeq() << std::endl; -#endif - if(fromAccount->getSeq()>trans->getFromAccountSeq()) return TR_PASTASEQ; - if(fromAccount->getSeq()getFromAccountSeq()) return TR_PREASEQ; - - // apply - fromAccount->charge(trans->getAmount()); - fromAccount->incSeq(); - toAccount->credit(trans->getAmount()-trans->getFee()); - mFeeHeld+=trans->getFee(); - trans->setStatus(INCLUDED, mLedgerSeq); - - updateAccountState(fromAccount); - updateAccountState(toAccount); - addTransaction(trans); - - return TR_SUCCESS; - } - catch (SHAMapException) - { - return TR_ERROR; - } -} - -Ledger::TransResult Ledger::removeTransaction(Transaction::pointer trans) -{ // high-level - reverse application of transaction - assert(!mAccepted); - boost::recursive_mutex::scoped_lock sl(mLock); - if(!mTransactionMap || !mAccountStateMap) return TR_ERROR; - try - { - Transaction::pointer ourTrans=getTransaction(trans->getID()); - if(!ourTrans) return TR_NOTFOUND; - - // accounts exist - AccountState::pointer fromAccount=getAccountState(trans->getFromAccount()); - AccountState::pointer toAccount=getAccountState(trans->getToAccount()); - if(!fromAccount || !toAccount) return TR_BADACCT; - - // pass sanity checks? - if(toAccount->getBalance()getAmount()) return TR_INSUFF; - if(fromAccount->getSeq()!=(trans->getFromAccountSeq()+1)) return TR_PASTASEQ; - - // reverse - fromAccount->credit(trans->getAmount()); - fromAccount->decSeq(); - toAccount->charge(trans->getAmount()-trans->getFee()); - mFeeHeld-=trans->getFee(); - trans->setStatus(REMOVED, mLedgerSeq); - - if(!delTransaction(trans->getID())) - { - assert(false); - return TR_ERROR; - } - updateAccountState(fromAccount); - updateAccountState(toAccount); - return TR_SUCCESS; - } - catch (SHAMapException) - { - return TR_ERROR; - } -} - -Ledger::TransResult Ledger::hasTransaction(Transaction::pointer trans) -{ // Is this transaction in this ledger? If not, could it go in it? - boost::recursive_mutex::scoped_lock sl(mLock); - if(mTransactionMap==NULL) return TR_ERROR; - try - { - Transaction::pointer t=getTransaction(trans->getID()); - if(!!t) return TR_ALREADY; - - if(trans->getSourceLedger()>mLedgerSeq) return TR_BADLSEQ; - - AccountState::pointer fromAccount=getAccountState(trans->getFromAccount()); - if(!fromAccount) return TR_BADACCT; // cannot send from non-existent account - - // may be in a previous ledger - if(fromAccount->getSeq()>trans->getFromAccountSeq()) return TR_PASTASEQ; - - if(fromAccount->getSeq()getFromAccountSeq()) return TR_PREASEQ; - if(fromAccount->getBalance()getAmount()) return TR_INSUFF; - return TR_NOTFOUND; - } - catch (SHAMapException) - { - return TR_ERROR; - } -} - Ledger::pointer Ledger::closeLedger(uint64 timeStamp) { // close this ledger, return a pointer to the next ledger // CAUTION: New ledger needs its SHAMap's connected to storage @@ -342,13 +184,13 @@ Ledger::pointer Ledger::closeLedger(uint64 timeStamp) void LocalAccount::syncLedger() { - AccountState::pointer as=theApp->getMasterLedger().getAccountState(getAddress()); - if(!as) mLgrBalance=0; + AccountState::pointer as = theApp->getMasterLedger().getCurrentLedger()->getAccountState(getAddress()); + if(!as) mLgrBalance = 0; else { - mLgrBalance=as->getBalance(); - if( (mLgrBalance!=0) && (mTxnSeq==0) ) mTxnSeq=1; - if(mTxnSeqgetSeq()) mTxnSeq=as->getSeq(); + mLgrBalance = as->getBalance(); + if ( (mLgrBalance != 0) && (mTxnSeq == 0) ) mTxnSeq = 1; + if (mTxnSeq < as->getSeq()) mTxnSeq = as->getSeq(); } } diff --git a/src/Ledger.h b/src/Ledger.h index f23d796304..2cca9b3b1c 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -10,12 +10,10 @@ #include "../json/value.h" #include "Transaction.h" +#include "AccountState.h" #include "types.h" #include "BitcoinUtil.h" -#include "Hanko.h" -#include "AccountState.h" #include "SHAMap.h" -#include "SerializedLedger.h" enum LedgerStateParms @@ -73,8 +71,6 @@ protected: Ledger(Ledger& previous, uint64 timestamp); // ledger after this one void updateHash(); - bool addAccountState(AccountState::pointer); - bool updateAccountState(AccountState::pointer); bool addTransaction(Transaction::pointer); bool addTransaction(const uint256& id, const Serializer& txn); bool delTransaction(const uint256& id); @@ -121,15 +117,10 @@ public: bool hasTransaction(const uint256& TransID) const; Transaction::pointer getTransaction(const uint256& transID) const; - // OLD high level functions - uint64 getBalance(const NewcoinAddress& acctID) const; - AccountState::pointer getAccountState(const NewcoinAddress& acctID); - TransResult applyTransaction(Transaction::pointer trans); - TransResult removeTransaction(Transaction::pointer trans); - TransResult hasTransaction(Transaction::pointer trans); Ledger::pointer switchPreviousLedger(Ledger::pointer oldPrevious, Ledger::pointer newPrevious, int limit); // high-level functions + AccountState::pointer getAccountState(const NewcoinAddress& acctID); LedgerStateParms writeBack(LedgerStateParms parms, SerializedLedgerEntry::pointer); SerializedLedgerEntry::pointer getAccountRoot(LedgerStateParms& parms, const uint160& accountID); SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const std::string& nickname); @@ -144,7 +135,15 @@ public: // index calculation functions static uint256 getAccountRootIndex(const uint160& account); + static uint256 getAccountRootIndex(const NewcoinAddress& account) + { return getAccountRootIndex(account.getAccountID()); } + static uint256 getRippleIndex(const uint160& account, const uint160& extendTo, const uint160& currency); + static uint256 getRippleIndex(const uint160& account, const uint160& extendTo) + { return getRippleIndex(account, extendTo, uint160()); } + static uint256 getRippleIndex(const NewcoinAddress& account, const NewcoinAddress& extendTo, + const uint160& currency) + { return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); } Ledger::pointer closeLedger(uint64 timestamp); bool isCompatible(boost::shared_ptr other); From 9a94752da17745edcfcd76721fefab5e3649aa30 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:56:29 -0700 Subject: [PATCH 21/38] Remove dead code. Add tie in to TransactionEngine code. --- src/LedgerMaster.cpp | 19 +++---------------- src/LedgerMaster.h | 13 ++++++++----- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/LedgerMaster.cpp b/src/LedgerMaster.cpp index a37d96fe6f..3c96727282 100644 --- a/src/LedgerMaster.cpp +++ b/src/LedgerMaster.cpp @@ -14,20 +14,6 @@ uint32 LedgerMaster::getCurrentLedgerIndex() return mCurrentLedger->getLedgerSeq(); } -uint64 LedgerMaster::getBalance(const NewcoinAddress& acctID) -{ - return mCurrentLedger->getBalance(acctID); -} - -uint64 LedgerMaster::getBalance(std::string& strAcctID) -{ - NewcoinAddress acctID; - - acctID.setAccountID(strAcctID); - - return mCurrentLedger->getBalance(acctID); -} - bool LedgerMaster::addHeldTransaction(Transaction::pointer transaction) { // returns true if transaction was added boost::recursive_mutex::scoped_lock ml(mLock); @@ -43,8 +29,9 @@ void LedgerMaster::pushLedger(Ledger::pointer newLedger) mFinalizingLedger->setAccepted(); mLedgerHistory.addAcceptedLedger(mFinalizingLedger); } - mFinalizingLedger=mCurrentLedger; - mCurrentLedger=newLedger; + mFinalizingLedger = mCurrentLedger; + mCurrentLedger = newLedger; + mEngine.setLedger(newLedger); } #if 0 diff --git a/src/LedgerMaster.h b/src/LedgerMaster.h index 49fe36783a..9a8cdcd5aa 100644 --- a/src/LedgerMaster.h +++ b/src/LedgerMaster.h @@ -6,6 +6,7 @@ #include "Peer.h" #include "types.h" #include "Transaction.h" +#include "TransactionEngine.h" // Tracks the current ledger and any ledgers in the process of closing // Tracks ledger history @@ -16,6 +17,8 @@ class LedgerMaster boost::recursive_mutex mLock; bool mIsSynced; + TransactionEngine mEngine; + Ledger::pointer mCurrentLedger; Ledger::pointer mFinalizingLedger; @@ -38,6 +41,9 @@ public: Ledger::pointer getCurrentLedger() { return mCurrentLedger; } Ledger::pointer getClosingLedger() { return mFinalizingLedger; } + TransactionEngineResult doTransaction(const SerializedTransaction& txn, TransactionEngineParams params) + { return mEngine.applyTransaction(txn, params); } + void pushLedger(Ledger::pointer newLedger); Ledger::pointer getLedgerBySeq(uint32 index) @@ -54,12 +60,9 @@ public: return mLedgerHistory.getLedgerByHash(hash); } - uint64 getBalance(std::string& strAcctID); - uint64 getBalance(const NewcoinAddress& acctID); - AccountState::pointer getAccountState(const NewcoinAddress& addr) - { return mCurrentLedger->getAccountState(addr); } - bool addHeldTransaction(Transaction::pointer trans); + uint64 getBalance(std::string& strAcctID, const uint160 currency = 0); + uint64 getBalance(const NewcoinAddress& acctID, const uint160 currency = 0); }; #endif From 790a7599275d0d1d56f8da7f4d94148d3e46e5b2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:57:29 -0700 Subject: [PATCH 22/38] Cleanups. --- src/LocalAccount.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LocalAccount.h b/src/LocalAccount.h index 3f10d8ae3b..482c39898b 100644 --- a/src/LocalAccount.h +++ b/src/LocalAccount.h @@ -52,10 +52,10 @@ public: uint32 getTxnSeq() const { return mTxnSeq; } uint32 incTxnSeq() { return mTxnSeq++; } - int64 getEffectiveBalance() const { return static_cast(mLgrBalance)+mTxnDelta; } - void credit(uint64 amount) { mTxnDelta+=amount; } - void debit(uint64 amount) { mTxnDelta-=amount; } - void setLedgerBalance(uint64_t lb) { mLgrBalance=lb; if(mTxnSeq==0) mTxnSeq=1; } + int64 getEffectiveBalance() const { return static_cast(mLgrBalance) + mTxnDelta; } + void credit(uint64 amount) { mTxnDelta += amount; } + void debit(uint64 amount) { mTxnDelta -= amount; } + void setLedgerBalance(uint64_t lb) { mLgrBalance = lb; if (mTxnSeq == 0) mTxnSeq = 1; } void syncLedger(); }; From 238b2d16f87b30643c4a5d9cd3b1ef5ba3e85254 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:57:42 -0700 Subject: [PATCH 23/38] Cleanups. --- src/PeerDoor.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/PeerDoor.cpp b/src/PeerDoor.cpp index 5ecfc93ed5..c12f7d2b26 100644 --- a/src/PeerDoor.cpp +++ b/src/PeerDoor.cpp @@ -1,8 +1,13 @@ + #include "PeerDoor.h" -#include "Config.h" + +#include + #include //#include -#include + +#include "Config.h" + using namespace std; using namespace boost::asio::ip; From 3a09455e6c1c5b1e7fc02b25704767b8ca01331c Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:58:05 -0700 Subject: [PATCH 24/38] Remove dead code. Change unit tests to compensate. --- src/SHAMap.cpp | 4 ---- src/SHAMap.h | 5 ----- src/SHAMapNodes.cpp | 8 ++++---- src/SHAMapSync.cpp | 2 +- 4 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/SHAMap.cpp b/src/SHAMap.cpp index 18f6a0e237..745c0980d7 100644 --- a/src/SHAMap.cpp +++ b/src/SHAMap.cpp @@ -155,10 +155,6 @@ SHAMapItem::SHAMapItem(const uint256& tag, const std::vector& dat : mTag(tag), mData(data) { ; } -SHAMapItem::SHAMapItem(const uint160& tag, const std::vector& data) - : mTag(tag.to256()), mData(data) -{ ; } - SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode::pointer node) { // Return the first item below this node diff --git a/src/SHAMap.h b/src/SHAMap.h index d1b9c6ccb7..9ee2ffc962 100644 --- a/src/SHAMap.h +++ b/src/SHAMap.h @@ -99,8 +99,6 @@ public: SHAMapItem(const uint256& tag, const std::vector& data); SHAMapItem(const std::vector& data); // tag by hash - SHAMapItem(const uint160& tag, const std::vector& data); // deprecated - const uint256& getTag() const { return mTag; } std::vector getData() const { return mData.getData(); } const std::vector& peekData() const { return mData.peekData(); } @@ -286,9 +284,6 @@ public: SHAMapItem::pointer peekNextItem(const uint256&); SHAMapItem::pointer peekPrevItem(const uint256&); - SHAMapItem::pointer peekPrevItem(const uint160& u) { return peekPrevItem(u.to256()); } - SHAMapItem::pointer peekNextItem(const uint160& u) { return peekNextItem(u.to256()); } - // comparison/sync functions void getMissingNodes(std::vector& nodeIDs, std::vector& hashes, int max); bool getNodeFat(const SHAMapNode& node, std::vector& nodeIDs, diff --git a/src/SHAMapNodes.cpp b/src/SHAMapNodes.cpp index 8f22ffbdd1..6c53bb8676 100644 --- a/src/SHAMapNodes.cpp +++ b/src/SHAMapNodes.cpp @@ -192,9 +192,9 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector(u, s.peekData()); mType=tnACCOUNT_STATE; @@ -236,7 +236,7 @@ void SHAMapTreeNode::addRaw(Serializer &s) if(mType==tnACCOUNT_STATE) { mItem->addRaw(s); - s.add160(mItem->getTag().to160()); + s.add256(mItem->getTag()); s.add8(1); return; } diff --git a/src/SHAMapSync.cpp b/src/SHAMapSync.cpp index f9f19b1dad..6fd19361b4 100644 --- a/src/SHAMapSync.cpp +++ b/src/SHAMapSync.cpp @@ -313,7 +313,7 @@ static SHAMapItem::pointer makeRandomAS() Serializer s; for(int d=0; d<3; d++) s.add32(rand()); - return boost::make_shared(s.getRIPEMD160(), s.peekData()); + return boost::make_shared(s.getRIPEMD160().to256(), s.peekData()); } static bool confuseMap(SHAMap &map, int count) From 44afa8fcf970acd99ead08211ef6a866f766cc0f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:58:27 -0700 Subject: [PATCH 25/38] Tie the STAccount class to the NewcoinAddress code. --- src/SerializedObject.cpp | 11 +++++++++++ src/SerializedObject.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 18117d29a2..2f8ea20a38 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -350,6 +350,17 @@ uint256 STObject::getValueFieldH256(SOE_Field field) const return cf->getValue(); } +NewcoinAddress STObject::getValueFieldAccount(SOE_Field field) const +{ + const SerializedType* rf = peekAtPField(field); + if (!rf) throw std::runtime_error("Field not found"); + SerializedTypeID id = rf->getSType(); + if (id == STI_OBJECT) return NewcoinAddress(); // optional field not present + const STAccount* cf = dynamic_cast(rf); + if (!cf) throw std::runtime_error("Wrong field type"); + return cf->getValueNCA(); +} + std::vector STObject::getValueFieldVL(SOE_Field field) const { const SerializedType* rf = peekAtPField(field); diff --git a/src/SerializedObject.h b/src/SerializedObject.h index ce2bbb9f8b..b97fd286f2 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -102,6 +102,7 @@ public: uint64 getValueFieldU64(SOE_Field field) const; uint160 getValueFieldH160(SOE_Field field) const; uint256 getValueFieldH256(SOE_Field field) const; + NewcoinAddress getValueFieldAccount(SOE_Field field) const; std::vector getValueFieldVL(SOE_Field field) const; std::vector getValueFieldTL(SOE_Field field) const; @@ -114,6 +115,8 @@ public: void setValueFieldVL(SOE_Field field, const std::vector&); void setValueFieldTL(SOE_Field field, const std::vector&); void setValueFieldAccount(SOE_Field field, const uint160&); + void setValueFieldAccount(SOE_Field field, const NewcoinAddress& addr) + { setValueFieldAccount(field, addr.getAccountID()); } bool isFieldPresent(SOE_Field field) const; void makeFieldPresent(SOE_Field field); From 454f47fa991808b79bcf791280218430e540b1c8 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:59:02 -0700 Subject: [PATCH 26/38] Tie SerializedTransacion code to NewcoinAddress code. --- src/SerializedTransaction.cpp | 8 ++++---- src/SerializedTransaction.h | 13 ++++++++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 497c9aac9f..3b1f7fdc8f 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -38,14 +38,14 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length mMiddleTxn.giveObject(new STUInt64("Fee", sit.get64())); mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction"); - updateSigningAccount(); + updateSourceAccount(); } -void SerializedTransaction::updateSigningAccount() +void SerializedTransaction::updateSourceAccount() { NewcoinAddress a; a.setAccountPublic(peekRawSigningAccount()); - mSigningAccount = a.getAccountID(); + mSourceAccount.setAccountID(a.getAccountID()); } int SerializedTransaction::getLength() const @@ -207,7 +207,7 @@ void SerializedTransaction::setSigningAccount(const std::vector& STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningAccount)); if (!v) throw std::runtime_error("corrupt transaction"); v->setValue(s); - updateSigningAccount(); + updateSourceAccount(); } uint160 SerializedTransaction::getITFieldAccount(SOE_Field field) const diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 452ba283f3..bdcae423d2 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -8,6 +8,7 @@ #include "uint256.h" #include "SerializedObject.h" #include "TransactionFormats.h" +#include "NewcoinAddress.h" class SerializedTransaction : public STObject { @@ -15,13 +16,13 @@ public: typedef boost::shared_ptr pointer; protected: - uint160 mSigningAccount; + NewcoinAddress mSourceAccount; TransactionType mType; STVariableLength mSignature; STObject mMiddleTxn, mInnerTxn; TransactionFormat* mFormat; - void updateSigningAccount(); + void updateSourceAccount(); public: SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit @@ -45,10 +46,12 @@ public: // middle transaction functions uint32 getVersion() const; void setVersion(uint32); + TransactionType getTxnType() const { return mType; } uint64 getTransactionFee() const; void setTransactionFee(uint64); - uint160 getSigningAccount() const { return mSigningAccount; } + + const NewcoinAddress& getSourceAccount() const { return mSourceAccount; } std::vector getRawSigningAccount() const; const std::vector& peekRawSigningAccount() const; std::vector& peekRawSigningAccount(); @@ -90,6 +93,10 @@ public: { return mInnerTxn.setValueFieldVL(field, v); } void setITFieldTL(SOE_Field field, const std::vector& v) { return mInnerTxn.setValueFieldTL(field, v); } + void setITFieldAccount(SOE_Field field, const uint160& v) + { return mInnerTxn.setValueFieldAccount(field, v); } + void setITFieldAccount(SOE_Field field, const NewcoinAddress& v) + { return mInnerTxn.setValueFieldAccount(field, v); } // optional field functions bool getITFieldPresent(SOE_Field field) const; From bf4becf4363cd5ec1a39272d6124ac8624ba9c8f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:59:39 -0700 Subject: [PATCH 27/38] Get STAccount value as NewcoinAddress. --- src/SerializedTypes.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 088c0c6083..419797b761 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -203,6 +203,20 @@ bool STAccount::getValueH160(uint160& v) const return true; } +NewcoinAddress STAccount::getValueNCA() const +{ + NewcoinAddress a; + uint160 v; + if (getValueH160(v)) + a.setAccountID(v); + return a; +} + +void STAccount::setValueNCA(const NewcoinAddress& nca) +{ + setValueH160(nca.getAccountID()); +} + std::string STTaggedList::getText() const { std::string ret; From 00f06feae0b03b0dcf8955d472a5599f1b607592 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 15:59:55 -0700 Subject: [PATCH 28/38] Tie to NewcoinAddress code. --- src/SerializedLedger.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index af462de6b5..dd28b18846 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -3,6 +3,7 @@ #include "SerializedObject.h" #include "LedgerFormats.h" +#include "NewcoinAddress.h" class SerializedLedgerEntry : public STObject { @@ -50,7 +51,8 @@ public: uint256 getIFieldH256(SOE_Field field) const { return mObject.getValueFieldH256(field); } std::vector getIFieldVL(SOE_Field field) const { return mObject.getValueFieldVL(field); } std::vector getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); } - void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); } + NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); } + void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); } void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); } void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); } void setIFieldU64(SOE_Field field, uint32 v) { return mObject.setValueFieldU64(field, v); } @@ -62,12 +64,12 @@ public: { return mObject.setValueFieldTL(field, v); } void setIFieldAccount(SOE_Field field, const uint160& account) { return mObject.setValueFieldAccount(field, account); } + void setIFieldAccount(SOE_Field field, const NewcoinAddress& account) + { return mObject.setValueFieldAccount(field, account); } bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); } void makeIFieldPresent(SOE_Field field) { return mObject.makeFieldPresent(field); } void makeIFieldAbsent(SOE_Field field) { return mObject.makeFieldAbsent(field); } - - }; #endif From 18c1b104a08636b44ae0850c6007d3e1d43d436d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:00:09 -0700 Subject: [PATCH 29/38] NewcoinAddress functions. --- src/SerializedTypes.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index ba7b6e03d8..0a70f432c6 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -362,6 +362,9 @@ public: virtual STAccount* duplicate() const { return new STAccount(name, value); } std::string getText() const; + NewcoinAddress getValueNCA() const; + void setValueNCA(const NewcoinAddress& nca); + void setValueH160(const uint160& v); bool getValueH160(uint160&) const; bool isValueH160() const; From a15549a7977fc804868016cf2187c465acc1b1b2 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:00:24 -0700 Subject: [PATCH 30/38] Remove obsolete assumptions. (Not every transaction has an amount, not every transaction has a destination). --- src/Transaction.cpp | 30 ++++++++++-------------------- src/Transaction.h | 3 +-- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index a999e2dc8e..d44d3b5b8b 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -15,7 +15,6 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd uint32 ident, uint32 ledger) : mInLedger(0), mStatus(NEW) { mAccountFrom = fromLocalAccount->getAddress(); - mAccountTo = toAccount; mTransaction = boost::make_shared(ttMAKE_PAYMENT); @@ -27,7 +26,7 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd assert(mTransaction->getSequence() != 0); mTransaction->setTransactionFee(100); // for now - mTransaction->setITFieldVL(sfDestination, toAccount.getAccountPublic()); + mTransaction->setITFieldAccount(sfDestination, toAccount); mTransaction->setITFieldU64(sfAmount, amount); if (ledger != 0) { @@ -52,26 +51,21 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd Transaction::Transaction(SerializedTransaction::pointer sit, bool validate) : mStatus(INVALID), mTransaction(sit) { - uint160 toAccountID, fromAccountID; std::vector pubKey; try { - toAccountID = mTransaction->getITFieldH160(sfDestination); pubKey = mTransaction->getRawSigningAccount(); mTransactionID = mTransaction->getTransactionID(); + mAccountFrom = mTransaction->getSourceAccount(); } catch(...) { return; } - mAccountTo.setAccountID(toAccountID); - mAccountFrom.setAccountID(fromAccountID); - mFromPubKey = boost::make_shared(); if (!mFromPubKey->SetPubKey(pubKey)) return; - mAccountFrom.setAccountPublic(pubKey); mFromPubKey = theApp->getPubKeyCache().store(mAccountFrom, mFromPubKey); if (!validate || checkSign()) @@ -109,7 +103,7 @@ Transaction::Transaction(const std::vector& raw, bool validate) : Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID, CKey::pointer pubKey, uint64 amount, uint64 fee, uint32 fromSeq, uint32 fromLedger, uint32 ident, const std::vector& signature, uint32 ledgerSeq, TransStatus st) : - mAccountFrom(fromID), mAccountTo(toID), mFromPubKey(pubKey), mInLedger(ledgerSeq), mStatus(st) + mAccountFrom(fromID), mFromPubKey(pubKey), mInLedger(ledgerSeq), mStatus(st) { mTransaction=boost::make_shared(ttMAKE_PAYMENT); mTransaction->setSignature(signature); @@ -127,6 +121,7 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI mTransaction->setITFieldU32(sfSourceTag, ident); } mTransaction->setValueFieldU64(sfAmount, amount); + mTransaction->setValueFieldAccount(sfDestination, toID.getAccountID()); updateID(); } @@ -141,7 +136,7 @@ bool Transaction::sign(LocalAccount::pointer fromLocalAccount) return false; } - if( (mTransaction->getITFieldU64(sfAmount)==0) || !mAccountTo.IsValid() ) + if( (mTransaction->getITFieldU64(sfAmount)==0) ) { #ifdef DEBUG std::cerr << "Bad amount or destination" << std::endl; @@ -354,7 +349,9 @@ bool Transaction::isHexTxID(const std::string& txid) Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const { Json::Value ret(mTransaction->getJson(0)); + if(mInLedger) ret["InLedger"]=mInLedger; + if(paid) ret["Paid"]=true; switch(mStatus) { @@ -370,12 +367,7 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const default: ret["Status"]="unknown"; } - Json::Value source(Json::objectValue); - source["AccountID"]=mAccountFrom.humanAccountID(); - - Json::Value destination(Json::objectValue); - destination["AccountID"]=mAccountTo.humanAccountID(); - +#if 0 if(decorate) { LocalAccount::pointer lac=theApp->getWallet().getLocalAccount(mAccountFrom); @@ -383,9 +375,7 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const lac=theApp->getWallet().getLocalAccount(mAccountTo); if(!!lac) destination=lac->getJson(); } - if(paid) source["Paid"]=true; - if(credited) destination["Credited"]=true; - ret["Source"]=source; - ret["Destination"]=destination; +#endif + return ret; } diff --git a/src/Transaction.h b/src/Transaction.h index 66c490eede..d1fbe4a89d 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -39,7 +39,7 @@ public: private: uint256 mTransactionID; - NewcoinAddress mAccountFrom, mAccountTo; + NewcoinAddress mAccountFrom; CKey::pointer mFromPubKey; uint32 mInLedger; @@ -66,7 +66,6 @@ public: const uint256& getID() const { return mTransactionID; } const NewcoinAddress& getFromAccount() const { return mAccountFrom; } - const NewcoinAddress& getToAccount() const { return mAccountTo; } uint64 getAmount() const { return mTransaction->getITFieldU64(sfAmount); } uint64 getFee() const { return mTransaction->getTransactionFee(); } uint32 getFromAccountSeq() const { return mTransaction->getSequence(); } From 012ac4a20b77e54a83054f9509a1fcec8bf5397e Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:00:55 -0700 Subject: [PATCH 31/38] Bugfix. --- src/TransactionEngine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index ab71738199..38624d4045 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -24,7 +24,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran } // get source account ID - uint160 srcAccount = txn.getSigningAccount(); + uint160 srcAccount = txn.getSourceAccount().getAccountID(); if (!srcAccount) return terINVALID; boost::recursive_mutex::scoped_lock sl(mLedger->mLock); From 2d24d05174b5817405f26d540ae2ca3477add977 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:01:02 -0700 Subject: [PATCH 32/38] Mark a FIXME. BOOST_FOREACH caches the end. --- src/ValidationCollection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ValidationCollection.cpp b/src/ValidationCollection.cpp index 95d28d3030..340ac6457a 100644 --- a/src/ValidationCollection.cpp +++ b/src/ValidationCollection.cpp @@ -127,7 +127,7 @@ void ValidationCollection::addToGroup(newcoin::Validation& newValid) // see if this hash is already on the list. If so add it there. vector< Group >& groups=mIndexGroups[newValid.ledgerindex()]; BOOST_FOREACH(Group& group,groups) - { + { // FIXME: Cannot modify *at* *all* inside a BOOST_FOREACH BOOST_FOREACH(newcoin::Validation& valid,group.mValidations) { if(valid.hash()==newValid.hash()) From 39fbc0fb626d5d28fe47762d16c72b898d3f7d42 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:01:23 -0700 Subject: [PATCH 33/38] Tie to new code. --- src/NetworkOPs.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 5ef3a0e8c9..28afbdf081 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -38,10 +38,10 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, return trans; } - Ledger::TransResult r=theApp->getMasterLedger().getCurrentLedger()->applyTransaction(trans); - if(r==Ledger::TR_ERROR) throw Fault(IO_ERROR); + TransactionEngineResult r=theApp->getMasterLedger().doTransaction(*trans->getSTransaction(), tepNONE); + if(r==terFAILED) throw Fault(IO_ERROR); - if((r==Ledger::TR_PREASEQ) || (r==Ledger::TR_BADLSEQ)) + if(r == terPRE_SEQ) { // transaction should be held #ifdef DEBUG std::cerr << "Transaction should be held" << std::endl; @@ -51,7 +51,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, theApp->getMasterLedger().addHeldTransaction(trans); return trans; } - if( (r==Ledger::TR_PASTASEQ) || (r==Ledger::TR_ALREADY) ) + if ( (r==terPAST_SEQ || r==terPAST_LEDGER) ) { // duplicate or conflict #ifdef DEBUG std::cerr << "Transaction is obsolete" << std::endl; @@ -60,14 +60,18 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, return trans; } - if(r==Ledger::TR_SUCCESS) + if(r==terSUCCESS) { #ifdef DEBUG std::cerr << "Transaction is now included, synching to wallet" << std::endl; #endif trans->setStatus(INCLUDED); theApp->getMasterTransaction().canonicalize(trans, true); - theApp->getWallet().applyTransaction(trans); + +// FIXME: Need code to get all accounts affected by a transaction and re-synch +// any of them that affect local accounts cached in memory. Or, we need to +// no cache the account balance information and always get it from the current ledger +// theApp->getWallet().applyTransaction(trans); newcoin::TMTransaction *tx=new newcoin::TMTransaction(); From f4639058f0d7e7f153b9733df0a3537e56852be5 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Mon, 23 Apr 2012 16:01:35 -0700 Subject: [PATCH 34/38] Tie to new code. --- src/Wallet.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/Wallet.cpp b/src/Wallet.cpp index b50d73d935..ac163888f8 100644 --- a/src/Wallet.cpp +++ b/src/Wallet.cpp @@ -762,6 +762,12 @@ void Wallet::syncToLedger(bool force, Ledger* ledger) if(mLedgergetLedgerSeq()) mLedger=ledger->getLedgerSeq(); } +#if 0 + +// We can't replicate the transaction logic in the wallet +// The right way is to apply the transactions to the ledger +// And then sync all affected accounts to the ledger + void Wallet::applyTransaction(Transaction::pointer txn) { TransStatus st=txn->getStatus(); @@ -775,7 +781,7 @@ void Wallet::applyTransaction(Transaction::pointer txn) if(lti!=mTransactions.end()) ltx=lti->second; std::map::iterator lac=mAccounts.find(txn->getToAccount()); - if(lac!=mAccounts.end()) + 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 @@ -788,8 +794,8 @@ void Wallet::applyTransaction(Transaction::pointer txn) } } - lac=mAccounts.find(txn->getFromAccount()); - if(lac==mAccounts.end()) return; + lac = mAccounts.find(txn->getFromAccount()); + if(lac == mAccounts.end()) return; if ( (st!=INVALID) && (lac->second->getTxnSeq()==txn->getFromAccountSeq()) ) lac->second->incTxnSeq(); @@ -830,6 +836,8 @@ void Wallet::applyTransaction(Transaction::pointer txn) } } +#endif + void Wallet::addLocalTransactions(Json::Value& ret) { boost::recursive_mutex::scoped_lock sl(mLock); @@ -841,9 +849,9 @@ void Wallet::addLocalTransactions(Json::Value& ret) bool Wallet::getTxJson(const uint256& txn, Json::Value& ret) { boost::recursive_mutex::scoped_lock sl(mLock); - std::map::iterator it=mTransactions.find(txn); - if(it==mTransactions.end()) return false; - ret=it->second->getJson(); + std::map::iterator it = mTransactions.find(txn); + if (it == mTransactions.end()) return false; + ret = it->second->getJson(); return true; } @@ -851,12 +859,12 @@ bool Wallet::getTxJson(const uint256& txn, Json::Value& ret) bool Wallet::getTxsJson(const NewcoinAddress& account, Json::Value& ret) { boost::recursive_mutex::scoped_lock sl(mLock); - for(std::map::iterator it=mTransactions.begin(); - it!=mTransactions.end(); ++it) + for(std::map::iterator it = mTransactions.begin(), + end = mTransactions.end(); it != end; ++it) { - Transaction::pointer txn=it->second->getTransaction(); - if(txn && ((account==txn->getFromAccount())||(account==txn->getToAccount())) ) - ret[it->first.GetHex()]=it->second->getJson(); + Transaction::pointer txn = it->second->getTransaction(); + if(txn && (account == txn->getFromAccount())) // FIXME: Need a way to get all accounts a txn affects + ret[it->first.GetHex()] = it->second->getJson(); } return true; From f36d1fdc08a137d9dabb1db61e84edf9414d0b21 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 24 Apr 2012 03:32:12 -0700 Subject: [PATCH 35/38] Remove a FIXME by fixing it. --- src/Peer.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Peer.cpp b/src/Peer.cpp index 14e1900048..b7cdb675d7 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -340,14 +340,13 @@ void Peer::recvTransaction(newcoin::TMTransaction& packet) Transaction::pointer tx; try { - std::string rawTx=packet.rawtransaction(); + std::string rawTx = packet.rawtransaction(); Serializer s(std::vector(rawTx.begin(), rawTx.end())); SerializerIterator sit(s); - SerializedTransaction::pointer stx=boost::make_shared(boost::ref(sit), -1); + SerializedTransaction::pointer stx = boost::make_shared(boost::ref(sit), -1); - if(stx->getTxnType()!=ttMAKE_PAYMENT) throw(0); // FIXME to support other transaction - tx=boost::make_shared(stx, true); - if(tx->getStatus()==INVALID) throw(0); + tx = boost::make_shared(stx, true); + if (tx->getStatus() == INVALID) throw(0); } catch (...) { @@ -359,7 +358,7 @@ void Peer::recvTransaction(newcoin::TMTransaction& packet) return; } - tx=theApp->getOPs().processTransaction(tx, this); + tx = theApp->getOPs().processTransaction(tx, this); if(tx->getStatus()!=INCLUDED) { // transaction wasn't accepted into ledger From 0392d8ddcb879ebfea6062a485a6374a9cafb66b Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 24 Apr 2012 04:24:14 -0700 Subject: [PATCH 36/38] Local accounts now have their balances and sequences managed from the active ledger, not from the wallet. --- src/AccountState.h | 8 +++--- src/Application.cpp | 2 +- src/Ledger.cpp | 12 --------- src/LocalAccount.h | 19 +++---------- src/Transaction.cpp | 6 ++++- src/Wallet.cpp | 65 +++++++++++++++++++-------------------------- 6 files changed, 42 insertions(+), 70 deletions(-) diff --git a/src/AccountState.h b/src/AccountState.h index f08a8c80b6..c2c3190c2b 100644 --- a/src/AccountState.h +++ b/src/AccountState.h @@ -17,12 +17,12 @@ class AccountState { public: - typedef boost::shared_ptr pointer; + typedef boost::shared_ptr pointer; private: - NewcoinAddress mAccountID; - SerializedLedgerEntry::pointer mLedgerEntry; - bool mValid; + NewcoinAddress mAccountID; + SerializedLedgerEntry::pointer mLedgerEntry; + bool mValid; public: AccountState(const NewcoinAddress& AccountID); // For new accounts diff --git a/src/Application.cpp b/src/Application.cpp index eb1f53bde4..f4ebf63fda 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -117,7 +117,7 @@ void Application::run() // temporary mWallet.load(); - mWallet.syncToLedger(true, &(*secondLedger)); +// mWallet.syncToLedger(true, &(*secondLedger)); // temporary mIOService.run(); // This blocks diff --git a/src/Ledger.cpp b/src/Ledger.cpp index eb95633f6e..62b6ee8f99 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -182,18 +182,6 @@ Ledger::pointer Ledger::closeLedger(uint64 timeStamp) return Ledger::pointer(new Ledger(*this, timeStamp)); // can't use make_shared, constructor is protected } -void LocalAccount::syncLedger() -{ - AccountState::pointer as = theApp->getMasterLedger().getCurrentLedger()->getAccountState(getAddress()); - if(!as) mLgrBalance = 0; - else - { - mLgrBalance = as->getBalance(); - if ( (mLgrBalance != 0) && (mTxnSeq == 0) ) mTxnSeq = 1; - if (mTxnSeq < as->getSeq()) mTxnSeq = as->getSeq(); - } -} - bool Ledger::unitTest() { #if 0 diff --git a/src/LocalAccount.h b/src/LocalAccount.h index 482c39898b..ee292625d5 100644 --- a/src/LocalAccount.h +++ b/src/LocalAccount.h @@ -4,6 +4,8 @@ #include #include +#include "AccountState.h" + class LocalAccountFamily; class LocalAccount @@ -21,11 +23,6 @@ protected: boost::shared_ptr mFamily; int mAccountFSeq; - // local usage tracking - uint64 mLgrBalance; // The balance, from the last ledger - int64 mTxnDelta; // The balance changes from local/pending transactions - uint32 mTxnSeq; // The sequence number of the next transaction - public: LocalAccount(boost::shared_ptr family, int accountSeq); @@ -48,16 +45,8 @@ public: CKey::pointer getPrivateKey(); Json::Value getJson() const; - void update(uint64 balance, uint32 seq); - uint32 getTxnSeq() const { return mTxnSeq; } - uint32 incTxnSeq() { return mTxnSeq++; } - - int64 getEffectiveBalance() const { return static_cast(mLgrBalance) + mTxnDelta; } - void credit(uint64 amount) { mTxnDelta += amount; } - void debit(uint64 amount) { mTxnDelta -= amount; } - void setLedgerBalance(uint64_t lb) { mLgrBalance = lb; if (mTxnSeq == 0) mTxnSeq = 1; } - - void syncLedger(); + AccountState::pointer getAccountState() const; + uint64 getEffectiveBalance() const; }; class LocalAccountFamily : public boost::enable_shared_from_this diff --git a/src/Transaction.cpp b/src/Transaction.cpp index d44d3b5b8b..9066391864 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -14,6 +14,9 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAddress& toAccount, uint64 amount, uint32 ident, uint32 ledger) : mInLedger(0), mStatus(NEW) { + AccountState::pointer accountState = fromLocalAccount->getAccountState(); + if (!accountState) throw std::runtime_error("transaction on non-existent account"); + mAccountFrom = fromLocalAccount->getAddress(); mTransaction = boost::make_shared(ttMAKE_PAYMENT); @@ -22,8 +25,9 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd assert(mFromPubKey); mTransaction->setSigningAccount(mFromPubKey->GetPubKey()); - mTransaction->setSequence(fromLocalAccount->getTxnSeq()); + mTransaction->setSequence(accountState->getSeq()); assert(mTransaction->getSequence() != 0); + mTransaction->setTransactionFee(100); // for now mTransaction->setITFieldAccount(sfDestination, toAccount); diff --git a/src/Wallet.cpp b/src/Wallet.cpp index ac163888f8..75056dad8e 100644 --- a/src/Wallet.cpp +++ b/src/Wallet.cpp @@ -24,12 +24,10 @@ // LocalAccount::LocalAccount(boost::shared_ptr family, int familySeq) : - mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq), - mLgrBalance(0), mTxnDelta(0), mTxnSeq(0) + mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq) { mAcctID.setAccountPublic(mPublicKey->GetPubKey()); - - if(theApp!=NULL) mPublicKey=theApp->getPubKeyCache().store(mAcctID, mPublicKey); + if(theApp!=NULL) mPublicKey = theApp->getPubKeyCache().store(mAcctID, mPublicKey); } std::string LocalAccount::getFullName() const @@ -37,7 +35,6 @@ std::string LocalAccount::getFullName() const std::string ret(mFamily->getFamily().humanFamilyGenerator()); ret.append(":"); ret.append(boost::lexical_cast(mAccountFSeq)); - return ret; } @@ -51,21 +48,36 @@ std::string LocalAccount::getFamilyName() const return mFamily->getFamily().humanFamilyGenerator(); } +AccountState::pointer LocalAccount::getAccountState() const +{ + return theApp->getOPs().getAccountState(mAcctID); +} + +uint64 LocalAccount::getEffectiveBalance() const +{ + AccountState::pointer as = getAccountState(); + if (!as) return 0; + return as->getBalance(); +} + Json::Value LocalAccount::getJson() const { Json::Value ret(Json::objectValue); - ret["Family"]=getFamilyName(); - ret["AccountID"]=getAddress().humanAccountID(); - ret["AccountPublic"]=getAddress().humanAccountPublic(); - ret["FullName"]=getFullName(); - ret["Issued"]=Json::Value(isIssued()); - ret["IsLocked"]=mFamily->isLocked(); + ret["Family"] = getFamilyName(); + ret["AccountID"] = getAddress().humanAccountID(); + ret["AccountPublic"] = getAddress().humanAccountPublic(); + ret["FullName"] = getFullName(); + ret["Issued"] = Json::Value(isIssued()); + ret["IsLocked"] = mFamily->isLocked(); - uint64 eb=getEffectiveBalance(); - if(eb!=0) ret["Balance"]=boost::lexical_cast(eb); - - uint32 sq=getTxnSeq(); - if(sq!=0) ret["TxnSeq"]=boost::lexical_cast(sq); + AccountState::pointer as = getAccountState(); + if (as) ret["Account"] = "None"; + else + { + Json::Value acct(Json::objectValue); + as->addJson(acct); + ret["Account"] = acct; + } return ret; } @@ -475,7 +487,6 @@ LocalAccount::pointer Wallet::getNewLocalAccount(const NewcoinAddress& family) mAccounts.insert(std::make_pair(acct, lac)); sl.unlock(); - lac->syncLedger(); return lac; } @@ -495,7 +506,6 @@ LocalAccount::pointer Wallet::getLocalAccount(const NewcoinAddress& family, int mAccounts.insert(std::make_pair(acct, lac)); sl.unlock(); - lac->syncLedger(); return lac; } @@ -743,25 +753,6 @@ bool Wallet::unitTest() return true; } -void Wallet::syncToLedger(bool force, Ledger* ledger) -{ - boost::recursive_mutex::scoped_lock sl(mLock); - if(!force && (mLedger>=ledger->getLedgerSeq())) return; - for(std::map::iterator xit=mTransactions.begin(); - xit!=mTransactions.end(); ++xit) - { // check each transaction, see if it's in the ledger or allowed in the ledger - // WRITEME - } - for(std::map::iterator ait=mAccounts.begin(); ait!=mAccounts.end(); ++ait) - { // check each account, see if our ledger balance matches - LocalAccount::pointer& lac=ait->second; - AccountState::pointer acs=ledger->getAccountState(ait->first); - if(!acs) lac->setLedgerBalance(0); - else lac->setLedgerBalance(acs->getBalance()); - } - if(mLedgergetLedgerSeq()) mLedger=ledger->getLedgerSeq(); -} - #if 0 // We can't replicate the transaction logic in the wallet From 9e2d13ff3efae98e6d00fdb9b483f330dc057dc0 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 24 Apr 2012 04:34:46 -0700 Subject: [PATCH 37/38] SerializedTransaction::getAffectdAccounts So we can know what transactions affect what accounts. --- src/SerializedTransaction.cpp | 15 +++++++++++++++ src/SerializedTransaction.h | 2 ++ 2 files changed, 17 insertions(+) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 3b1f7fdc8f..205ac767e2 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -75,6 +75,21 @@ std::string SerializedTransaction::getText() const return ret; } +std::vector SerializedTransaction::getAffectedAccounts() const +{ + std::vector accounts; + accounts.push_back(mSourceAccount); + + for(boost::ptr_vector::const_iterator it = mInnerTxn.peekData().begin(), + end = mInnerTxn.peekData().end(); it != end ; ++it) + { + const STAccount* sa = dynamic_cast(&*it); + if (sa != NULL) // FIXME: Should we check for duplicates? + accounts.push_back(sa->getValueNCA()); + } + return accounts; +} + int SerializedTransaction::getTransaction(Serializer& s, bool include_length) const { int l = getLength(); diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index bdcae423d2..00c221bef0 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -103,6 +103,8 @@ public: void makeITFieldPresent(SOE_Field field); void makeITFieldAbsent(SOE_Field field); + std::vector getAffectedAccounts() const; + // whole transaction functions int getTransaction(Serializer& s, bool include_length) const; uint256 getTransactionID() const; From 0903f5e433eea42fab8584ae923a28ba2d690022 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 24 Apr 2012 04:42:49 -0700 Subject: [PATCH 38/38] Be clear about what's an account and what's a public key. --- src/SerializedTransaction.cpp | 23 ++++++++++++----------- src/SerializedTransaction.h | 8 ++++---- src/Transaction.cpp | 14 +++++++------- src/TransactionEngine.cpp | 2 +- src/TransactionFormats.h | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 205ac767e2..49c45f1e86 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -7,7 +7,7 @@ SerializedTransaction::SerializedTransaction(TransactionType type) : mType(type) if (mFormat == NULL) throw std::runtime_error("invalid transaction type"); mMiddleTxn.giveObject(new STUInt32("Magic", TransactionMagic)); - mMiddleTxn.giveObject(new STVariableLength("SigningAccount")); + mMiddleTxn.giveObject(new STVariableLength("SigningPubKey")); mMiddleTxn.giveObject(new STUInt32("Sequence")); mMiddleTxn.giveObject(new STUInt8("Type", static_cast(type))); mMiddleTxn.giveObject(new STUInt64("Fee")); @@ -28,7 +28,7 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length throw std::runtime_error("Transaction has invalid magic"); mMiddleTxn.giveObject(new STUInt32("Magic", TransactionMagic)); - mMiddleTxn.giveObject(new STVariableLength("SigningAccount", sit.getVL())); + mMiddleTxn.giveObject(new STVariableLength("SigningPubKey", sit.getVL())); mMiddleTxn.giveObject(new STUInt32("Sequence", sit.get32())); mType = static_cast(sit.get32()); @@ -44,7 +44,7 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length void SerializedTransaction::updateSourceAccount() { NewcoinAddress a; - a.setAccountPublic(peekRawSigningAccount()); + a.setAccountPublic(peekSigningPubKey()); mSourceAccount.setAccountID(a.getAccountID()); } @@ -194,35 +194,36 @@ void SerializedTransaction::setSequence(uint32 seq) v->setValue(seq); } -std::vector SerializedTransaction::getRawSigningAccount() const +std::vector SerializedTransaction::getSigningPubKey() const { const STVariableLength* v = - dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningAccount)); + dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningPubKey)); if (!v) throw std::runtime_error("corrupt transaction"); return v->getValue(); } -const std::vector& SerializedTransaction::peekRawSigningAccount() const +const std::vector& SerializedTransaction::peekSigningPubKey() const { const STVariableLength* v= - dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningAccount)); + dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningPubKey)); if (!v) throw std::runtime_error("corrupt transaction"); return v->peekValue(); } -std::vector& SerializedTransaction::peekRawSigningAccount() +std::vector& SerializedTransaction::peekSigningPubKey() { - STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningAccount)); + STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningPubKey)); if (!v) throw std::runtime_error("corrupt transaction"); return v->peekValue(); } -void SerializedTransaction::setSigningAccount(const std::vector& s) +const NewcoinAddress& SerializedTransaction::setSigningPubKey(const std::vector& s) { - STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningAccount)); + STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningPubKey)); if (!v) throw std::runtime_error("corrupt transaction"); v->setValue(s); updateSourceAccount(); + return mSourceAccount; } uint160 SerializedTransaction::getITFieldAccount(SOE_Field field) const diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index 00c221bef0..fe6609518b 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -52,10 +52,10 @@ public: void setTransactionFee(uint64); const NewcoinAddress& getSourceAccount() const { return mSourceAccount; } - std::vector getRawSigningAccount() const; - const std::vector& peekRawSigningAccount() const; - std::vector& peekRawSigningAccount(); - void setSigningAccount(const std::vector& s); + std::vector getSigningPubKey() const; + const std::vector& peekSigningPubKey() const; + std::vector& peekSigningPubKey(); + const NewcoinAddress& setSigningPubKey(const std::vector& s); std::string getTransactionType() const { return mFormat->t_name; } // inner transaction functions diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 9066391864..0097d736ea 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -23,7 +23,7 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd mFromPubKey = fromLocalAccount->getPublicKey(); assert(mFromPubKey); - mTransaction->setSigningAccount(mFromPubKey->GetPubKey()); + mTransaction->setSigningPubKey(mFromPubKey->GetPubKey()); mTransaction->setSequence(accountState->getSeq()); assert(mTransaction->getSequence() != 0); @@ -59,7 +59,7 @@ Transaction::Transaction(SerializedTransaction::pointer sit, bool validate) : mS try { - pubKey = mTransaction->getRawSigningAccount(); + pubKey = mTransaction->peekSigningPubKey(); mTransactionID = mTransaction->getTransactionID(); mAccountFrom = mTransaction->getSourceAccount(); } @@ -109,17 +109,17 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI uint32 ident, const std::vector& signature, uint32 ledgerSeq, TransStatus st) : mAccountFrom(fromID), mFromPubKey(pubKey), mInLedger(ledgerSeq), mStatus(st) { - mTransaction=boost::make_shared(ttMAKE_PAYMENT); + mTransaction = boost::make_shared(ttMAKE_PAYMENT); mTransaction->setSignature(signature); mTransaction->setTransactionFee(fee); - mTransaction->setSigningAccount(pubKey->GetPubKey()); + mTransaction->setSigningPubKey(pubKey->GetPubKey()); mTransaction->setSequence(fromSeq); - if(fromLedger!=0) + if (fromLedger != 0) { mTransaction->makeITFieldPresent(sfTargetLedger); mTransaction->setITFieldU32(sfTargetLedger, fromLedger); } - if(ident!=0) + if (ident != 0) { mTransaction->makeITFieldPresent(sfSourceTag); mTransaction->setITFieldU32(sfSourceTag, ident); @@ -131,7 +131,7 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI bool Transaction::sign(LocalAccount::pointer fromLocalAccount) { - CKey::pointer privateKey=fromLocalAccount->getPrivateKey(); + CKey::pointer privateKey = fromLocalAccount->getPrivateKey(); if(!privateKey) { #ifdef DEBUG diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 38624d4045..52a3a1abc2 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -11,7 +11,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // extract signing key CKey acctKey; - if (!acctKey.SetPubKey(txn.getRawSigningAccount())) return terINVALID; + if (!acctKey.SetPubKey(txn.peekSigningPubKey())) return terINVALID; // check signature if (!txn.checkSign(acctKey)) return terINVALID; diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h index 08887de169..eb5efaf180 100644 --- a/src/TransactionFormats.h +++ b/src/TransactionFormats.h @@ -20,7 +20,7 @@ struct TransactionFormat const int32 TransactionMagic=0x54584E00; -const int TransactionIVersion=0, TransactionISigningAccount=1, TransactionISequence=2; +const int TransactionIVersion=0, TransactionISigningPubKey=1, TransactionISequence=2; const int TransactionIType=3, TransactionIFee=4; const int TransactionMinLen=32;