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);