From 30407a3a239f5fe069ccebbb812bdc89c2ef2a34 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 22 May 2012 12:42:13 -0700 Subject: [PATCH 1/7] Work on transit fees. --- src/LedgerFormats.cpp | 29 ++++---- src/RPCServer.cpp | 10 +++ src/RPCServer.h | 1 - src/SerializedObject.h | 6 +- src/TransactionEngine.cpp | 147 ++++++++++++++++++++++++++++++++++++-- src/TransactionEngine.h | 9 +-- 6 files changed, 176 insertions(+), 26 deletions(-) diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index 490a0af40c..b0321ad991 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -6,18 +6,23 @@ LedgerEntryFormat LedgerFormats[]= { { "AccountRoot", ltACCOUNT_ROOT, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(AuthorizedKey),STI_HASH160, SOE_IFFLAG, 1 }, - { S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 }, - { S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 4 }, - { S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 }, + { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 }, + { S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 }, + { S_FIELD(AuthorizedKey), STI_HASH160, SOE_IFFLAG, 1 }, + { S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 }, + { S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 }, + { S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 }, + { S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 16 }, + { S_FIELD(TransitExpire), STI_UINT32, SOE_IFFLAG, 32 }, + { S_FIELD(NextTransitRate), STI_UINT32, SOE_IFFLAG, 64 }, + { S_FIELD(NextTransitStart), STI_UINT32, SOE_IFFLAG, 128 }, + { S_FIELD(NextTransitExpire), STI_UINT32, SOE_IFFLAG, 256 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { "GeneratorMap", ltGENERATOR_MAP, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index cbc87357ce..e3b63cf40b 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -130,6 +130,16 @@ int RPCServer::getParamCount(const Json::Value& params) return 1; } + +// now, expire, n +bool RPCServer::parseBorrowRate(const std::string& sBorrowRate) +{ + if (!sBorrowRate.compare("expire")) + 0; + + return true; +} + bool RPCServer::extractString(std::string& param, const Json::Value& params, int index) { if (params.isNull()) return false; diff --git a/src/RPCServer.h b/src/RPCServer.h index 56458321ab..1076a75224 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -37,7 +37,6 @@ class RPCServer : public boost::enable_shared_from_this SerializedLedgerEntry::pointer& sleSrc); Json::Value doAccountInfo(Json::Value& params); - Json::Value doBorrowSet(Json::Value& params); Json::Value doConnect(Json::Value& params); Json::Value doCreditSet(Json::Value& params); Json::Value doLedger(Json::Value& params); diff --git a/src/SerializedObject.h b/src/SerializedObject.h index d321b6870b..aacffc11f8 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -56,9 +56,9 @@ enum SOE_Field sfLimitAmount, sfMessageKey, sfMinimumOffer, - sfNextRate, - sfNextRateExp, - sfNextRateLgr, + sfNextTransitExpire, + sfNextTransitRate, + sfNextTransitStart, sfNickname, sfOfferCurrency, sfPaths, diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 432fcc3bec..a1251e92f2 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -53,6 +53,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran case ttINVOICE: case ttOFFER: + case ttCREDIT_SET: + case ttTRANSIT_SET: result = terSUCCESS; break; @@ -236,11 +238,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran return result; } -TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction&, std::vector&) -{ - return tenINVALID; -} - TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn, std::vector& accounts) { @@ -331,6 +328,11 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& return terSUCCESS; } +TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction&, std::vector&) +{ + return tenINVALID; +} + TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, std::vector& accounts, uint160 srcAccountID) @@ -425,8 +427,141 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction return terSUCCESS; } -TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction&, std::vector&) +TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector&) { + std::cerr << "doTransitSet>" << std::endl; + + SerializedLedgerEntry::pointer sleSrc = accounts[0].second; + + bool bTxnTransitRate = st->getIFieldPresent(sfTransitRate); + bool bTxnTransitStart = st->getIFieldPresent(sfTransitStart); + bool bTxnTransitExpire = st->getIFieldPresent(sfTransitExpire); + uint32 uTxnTransitRate = bTxnTransitRate ? st->getIFieldU32(sfTransitRate) : 0; + uint32 uTxnTransitStart = bTxnTransitStart ? st->getIFieldU32(sfTransitStart) : 0; + uint32 uTxnTransitExpire = bTxnTransitExpire ? st->getIFieldU32(sfTransitExpire) : 0; + + bool bActTransitRate = sleSrc->getIFieldPresent(sfTransitRate); + bool bActTransitExpire = sleSrc->getIFieldPresent(sfTransitExpire); + bool bActNextTransitRate = sleSrc->getIFieldPresent(sfNextTransitRate); + bool bActNextTransitStart = sleSrc->getIFieldPresent(sfNextTransitStart); + bool bActNextTransitExpire = sleSrc->getIFieldPresent(sfNextTransitExpire); + uint32 uActTransitRate = bActTransitRate ? sleSrc->getIFieldU32(sfTransitRate) : 0; + uint32 uActTransitExpire = bActTransitExpire ? sleSrc->getIFieldU32(sfTransitExpire) : 0; + uint32 uActNextTransitRate = bActNextTransitRate ? sleSrc->getIFieldU32(sfNextTransitRate) : 0; + uint32 uActNextTransitStart = bActNextTransitStart ? sleSrc->getIFieldU32(sfNextTransitStart) : 0; + uint32 uActNextTransitExpire = bActNextTransitExpire ? sleSrc->getIFieldU32(sfNextTransitExpire) : 0; + + // Try to overwrite next rate. + + bool bBetterNextExpire = + (!bTxnTransitExpire // Txn does not expire (same or extends) + || (bActNextTransitExpire && uTxnTransitExpire >= uActTransitExpire)); // Same or longer the next. + + bool bBetterNextRate = + !bActNextTransitRate // No next rate, txn is better. + || (uTxnTransitRate <= uActNextTransitRate); // Charge is the same or less. + + // Must start at the same time or sooner. + bool bBetterNextStart = + + // If starting sooner, must be better than current, or current must not protect range. + + + if (!bActNextTransitRate) + { + // No next. Overwrite next. + } + else if (uTxnTransitRate <= uActNextTransitRate && bBetterNextExpire) + { + // Better than + } + + // True if no rate is active or going to be active; + bool bNoRate = !bActTransitRate && !bActNextTransitRate; + + bool bStartNow = bTxnTransitStart + ? uTxnTransitStart < uLedger + : bActTransitRate + ? bActTransitExpire + ? + : true // Current never expires. + : true; // Nothing is running. + + // True if new rate does not apply immediately. + boo bRateIsLater = bTxnTransitStart + ? uTxnTransitStart < uLedger + + : bActNextTransitRate && bTxnTransitExpire; + + if (no_rate || rate_is_better || rate_is_later) + { + // Install. + if (starting) + { + // install now + } + else + { + // install next + } + } + else + { + return tenTRANSIT_WORSE; + } + if (no_rate && starting) + + if (!bActTransitRate && !bActNextTransitRate) { + // No rate + bProtected = false; + } if (bActTransitRate && !bTx + + if (bTxnTransitStart && uTxnTransitStart > uLedger) + { + // Start at a particular time. + + } + else + { + // No start or start in the past, start now. + if (!bActTransitRate && !bActNextTransitRate) + { + // No current or future rate. + + uDstTransitRate = uTxnTransitRate; + uDstTransitExpire = uTxnTransitExpire; // 0 for never expire. + } + else if (bActTransitRate && !bActNextTransitRate) + { + // Have a current rate and none pending. + if (!bActTransitExpire) { + // Current rate does not expire + + } + } + else + { + // Have a future rate. + + } + } + if (!bActTransitRate && !bActNextTransitRate) + { + + } + + // Set current. + uDstTransitRate = uTxnTransitRate; + uDstTransitExpire = uTxnTransitExpire; // 0 for never expire. + + // Set future. + uDstNextTransitRate = uTxnTransitRate; + uDstNextTransitStart = uTxnTransitStart; + uDstNextTransitExpire = uTxnTransitExpire; // 0 for never expire. + + if (txn.getITFieldPresent(sfCurrency)) + + std::cerr << "doTransitSet<" << std::endl; return tenINVALID; } diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index c05ecee86d..bd2f3bdd55 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -14,14 +14,15 @@ enum TransactionEngineResult { // tenCAN_NEVER_SUCCEED = <0 - // Malformed - tenGEN_IN_USE = -300, // Generator already in use. + // Malformed: Fee claimed + tenGEN_IN_USE = -300, // Generator already in use. tenCREATEXNC, // Can not specify non XNC for Create. tenEXPLICITXNC, // XNC is used by default, don't specify it. - // Not possible due to ledger database. + // Not possible due to ledger database: Fee claimed tenCREATED = -200, // Can not create a previously created account. tenCLAIMED, // Can not claim a previously claimed account. + tenTRANSIT_WORSE, // Can not override a better promise. // Other tenFAILED = -100, // Something broke horribly @@ -29,7 +30,7 @@ enum TransactionEngineResult tenINSUF_FEE_P, // fee totally insufficient tenINVALID, // The transaction is ill-formed - terSUCCESS = 0, // The transaction was applied + terSUCCESS = 0, // The transaction was applied // terFAILED_BUT_COULD_SUCEED = >0 terALREADY, // The transaction was already in the ledger From 0b9c762f995cdff729c68ff714f0bce5ae096457 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:51:10 -0700 Subject: [PATCH 2/7] Add STValue256 type. --- src/SerializedObject.cpp | 27 +++++++++++++++++++++++++++ src/SerializedObject.h | 19 +++++++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 672c17fd4f..bf1a873f05 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -33,6 +33,9 @@ std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, c case STI_HASH256: return std::auto_ptr(new STHash256(name)); + case STI_VECTOR256: + return std::auto_ptr(new STVector256(name)); + case STI_VL: return std::auto_ptr(new STVariableLength(name)); @@ -79,6 +82,9 @@ std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID case STI_HASH256: return STHash256::deserialize(sit, name); + case STI_VECTOR256: + return STVector256::deserialize(sit, name); + case STI_VL: return STVariableLength::deserialize(sit, name); @@ -464,6 +470,17 @@ STAmount STObject::getValueFieldAmount(SOE_Field field) const return *cf; } +STVector256 STObject::getValueFieldV256(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_NOTPRESENT) return STVector256(); // optional field not present + const STVector256 *cf = dynamic_cast(rf); + if (!cf) throw std::runtime_error("Wrong field type"); + return *cf; +} + void STObject::setValueFieldU8(SOE_Field field, unsigned char v) { SerializedType* rf = getPField(field); @@ -524,6 +541,16 @@ void STObject::setValueFieldH256(SOE_Field field, const uint256& v) cf->setValue(v); } +void STObject::setValueFieldV256(SOE_Field field, const STVector256& v) +{ + SerializedType* rf = getPField(field); + if (!rf) throw std::runtime_error("Field not found"); + if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field); + STVector256* cf = dynamic_cast(rf); + if (!cf) throw std::runtime_error("Wrong field type"); + cf->setValue(v); +} + void STObject::setValueFieldAccount(SOE_Field field, const uint160& v) { SerializedType* rf = getPField(field); diff --git a/src/SerializedObject.h b/src/SerializedObject.h index aacffc11f8..da778fe8e0 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -24,6 +24,9 @@ enum SOE_Field sfGeneric = 0, // common fields + sfAcceptExpire, + sfAcceptRate, + sfAcceptStart, sfAccount, sfAccountID, sfAmount, @@ -38,24 +41,31 @@ enum SOE_Field sfCurrency, sfCurrencyIn, sfCurrencyOut, - sfCurrentRate, sfDestination, sfEmailHash, sfExpireLedger, sfExtensions, + sfFirstNode, sfFlags, sfGenerator, sfGeneratorID, + sfHighID, + sfHighLimit, sfIdentifier, + sfIndexes, sfInvoiceID, + sfLastNode, sfLastReceive, sfLastTxn, sfLedgerHash, - sfLender, - sfLimit, sfLimitAmount, + sfLowID, + sfLowLimit, sfMessageKey, sfMinimumOffer, + sfNextAcceptExpire, + sfNextAcceptRate, + sfNextAcceptStart, sfNextTransitExpire, sfNextTransitRate, sfNextTransitStart, @@ -63,7 +73,6 @@ enum SOE_Field sfOfferCurrency, sfPaths, sfPubKey, - sfRateLock, sfSendMax, sfSequence, sfSignature, @@ -155,6 +164,7 @@ public: std::vector getValueFieldVL(SOE_Field field) const; std::vector getValueFieldTL(SOE_Field field) const; STAmount getValueFieldAmount(SOE_Field field) const; + STVector256 getValueFieldV256(SOE_Field field) const; void setValueFieldU8(SOE_Field field, unsigned char); void setValueFieldU16(SOE_Field field, uint16); @@ -169,6 +179,7 @@ public: { setValueFieldAccount(field, addr.getAccountID()); } void setValueFieldAmount(SOE_Field field, const STAmount&); void setValueFieldPathSet(SOE_Field field, const STPathSet&); + void setValueFieldV256(SOE_Field field, const STVector256& v); bool isFieldPresent(SOE_Field field) const; SerializedType* makeFieldPresent(SOE_Field field); From e03f452a054e7c73d031f220a275aedbed5e7e0d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:52:03 -0700 Subject: [PATCH 3/7] Add createAccountID() to NewcoinAddress. --- src/NewcoinAddress.cpp | 9 +++++++++ src/NewcoinAddress.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/NewcoinAddress.cpp b/src/NewcoinAddress.cpp index 60de45be07..6f7d597db9 100644 --- a/src/NewcoinAddress.cpp +++ b/src/NewcoinAddress.cpp @@ -322,6 +322,15 @@ bool NewcoinAddress::accountPublicVerify(const uint256& uHash, const std::vector return bVerified; } +NewcoinAddress NewcoinAddress::createAccountID(const uint160& uiAccountID) +{ + NewcoinAddress na; + + na.setAccountID(uiAccountID); + + return na; +} + // // AccountPrivate // diff --git a/src/NewcoinAddress.h b/src/NewcoinAddress.h index a5eedb5f77..387ef614c1 100644 --- a/src/NewcoinAddress.h +++ b/src/NewcoinAddress.h @@ -65,6 +65,8 @@ public: bool setAccountID(const std::string& strAccountID); void setAccountID(const uint160& hash160In); + static NewcoinAddress createAccountID(const uint160& uiAccountID); + // // Accounts Public // From 48d3099c001c3d911b0b32a8fdff75f3e0bd2e26 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:54:03 -0700 Subject: [PATCH 4/7] Add ledger support for directories and ripple state. --- src/Ledger.h | 54 ++++++++++++++++++++---------- src/LedgerFormats.cpp | 62 ++++++++++++++++++---------------- src/LedgerFormats.h | 31 +++++++++++++---- src/LedgerIndex.cpp | 17 +++++++--- src/LedgerNode.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++ src/SerializedLedger.h | 7 ++++ 6 files changed, 190 insertions(+), 57 deletions(-) diff --git a/src/Ledger.h b/src/Ledger.h index 42e32bdf87..61b4e47aaa 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -18,17 +18,17 @@ enum LedgerStateParms { - lepNONE = 0, // no special flags + lepNONE = 0, // no special flags // input flags - lepCREATE = 1, // Create if not present + lepCREATE = 1, // Create if not present // output flags - lepOKAY = 2, // success - lepMISSING = 4, // No node in that slot - lepWRONGTYPE = 8, // Node of different type there - lepCREATED = 16, // Node was created - lepERROR = 32, // error + lepOKAY = 2, // success + lepMISSING = 4, // No node in that slot + lepWRONGTYPE = 8, // Node of different type there + lepCREATED = 16, // Node was created + lepERROR = 32, // error }; class Ledger : public boost::enable_shared_from_this @@ -132,8 +132,6 @@ public: SerializedLedgerEntry::pointer getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID); SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const std::string& nickname); SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const uint256& nickHash); -// SerializedLedgerEntry::pointer getRippleState(LedgerStateParms parms, const uint160& offeror, -// const uint160& borrower, const Currency& currency); // database functions static void saveAcceptedLedger(Ledger::pointer); @@ -142,7 +140,7 @@ public: // index calculation functions static uint256 getAccountRootIndex(const uint160& account) - { return uint160extend256(account, 0); } // Index is accountID extended to 256 bits + { return uint160extend256(account, lnsAccounts); } // Index is accountID extended to 256 bits static uint256 getAccountRootIndex(const NewcoinAddress& account) { return getAccountRootIndex(account.getAccountID()); } @@ -154,28 +152,48 @@ public: SerializedLedgerEntry::pointer getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID); static uint256 getGeneratorIndex(const uint160& uGeneratorID) - { return uint160extend256(uGeneratorID, 1); } // Index is the generator ID extended to 256 bits in namespace 1 + { return uint160extend256(uGeneratorID, lnsGenerator); } // Index is the generator ID extended to 256 bits in namespace 1 // // Ripple functions // - static uint256 getRippleIndex(const uint160& account, const uint160& extendTo, const uint160& currency); + static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency); + static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency) + { return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); } - 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); } + static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB) + { return getRippleStateIndex(naA, naB, uint160()); } static uint160 getOfferBase(const uint160& currencyIn, const uint160& accountIn, const uint160& currencyOut, const uint160& accountOut); + // + // Offer functions + // + static uint256 getOfferIndex(const uint160& offerBase, uint64 rate, int skip = 0); static int getOfferSkip(const uint256& offerId); + SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency); + SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const uint160& uiA, const uint160& uiB, const uint160& uCurrency) + { + return getRippleState(parms, NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); + } + + // + // Directory functions + // + + static uint256 getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir=0); + + SerializedLedgerEntry::pointer getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex); + SerializedLedgerEntry::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex); + + // + // Misc + // bool isCompatible(boost::shared_ptr other); // bool signLedger(std::vector &signature, const LocalHanko &hanko); diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index b0321ad991..2481d80186 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -17,42 +17,48 @@ LedgerEntryFormat LedgerFormats[]= { S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 }, { S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 }, { S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 16 }, - { S_FIELD(TransitExpire), STI_UINT32, SOE_IFFLAG, 32 }, - { S_FIELD(NextTransitRate), STI_UINT32, SOE_IFFLAG, 64 }, - { S_FIELD(NextTransitStart), STI_UINT32, SOE_IFFLAG, 128 }, - { S_FIELD(NextTransitExpire), STI_UINT32, SOE_IFFLAG, 256 }, { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, + { "DirectoryRoot", ltDIR_ROOT, { + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(FirstNode), STI_UINT64, SOE_REQUIRED, 0 }, + { S_FIELD(LastNode), STI_UINT64, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + }, + { "DirectoryNode", ltDIR_NODE, { + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Indexes), STI_VECTOR256, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + }, { "GeneratorMap", ltGENERATOR_MAP, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 }, - { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 }, + { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { "Nickname", ltNICKNAME, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, - { S_FIELD(OfferCurrency),STI_HASH160, SOE_IFFLAG, 2 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 }, + { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, + { S_FIELD(OfferCurrency), STI_HASH160, SOE_IFFLAG, 2 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { "RippleState", ltRIPPLE_STATE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Borrower), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Lender), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Limit), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(CurrentRate), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(RateLock), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(NextRate), STI_UINT32, SOE_IFFLAG, 4 }, - { S_FIELD(NextRateLgr), STI_UINT32, SOE_IFFLAG, 8 }, - { S_FIELD(NextRateExp), STI_UINT32, SOE_IFFLAG, 16 }, - { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(LowID), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(HighID), STI_ACCOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, + { S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, { NULL, ltINVALID } }; diff --git a/src/LedgerFormats.h b/src/LedgerFormats.h index 931f359a3e..6adc19bc67 100644 --- a/src/LedgerFormats.h +++ b/src/LedgerFormats.h @@ -5,18 +5,37 @@ enum LedgerEntryType { - ltINVALID =-1, - ltACCOUNT_ROOT =0, - ltRIPPLE_STATE =1, - ltGENERATOR_MAP =2, - ltNICKNAME =3 + ltINVALID = -1, + ltACCOUNT_ROOT, + ltDIR_ROOT, + ltDIR_NODE, + ltGENERATOR_MAP, + ltRIPPLE_STATE, + ltNICKNAME +}; + +// In the format 160 + namespace + other. +enum LedgerNameSpace +{ + lnsGenerator = -1, + lnsAccounts, + lnsRipple, + lnsBonds, + lnsInvoices, + lnsMultiSig +}; + +enum LedgerSpecificFlags +{ + lsfLowIndexed = 0x00010000, + lsfHighIndexed = 0x00020000, }; struct LedgerEntryFormat { const char *t_name; LedgerEntryType t_type; - SOElement elements[16]; + SOElement elements[20]; }; extern LedgerEntryFormat LedgerFormats[]; diff --git a/src/LedgerIndex.cpp b/src/LedgerIndex.cpp index 8fd3b65708..a00f708344 100644 --- a/src/LedgerIndex.cpp +++ b/src/LedgerIndex.cpp @@ -1,11 +1,18 @@ #include "Ledger.h" -uint256 Ledger::getRippleIndex(const uint160& accountID, const uint160& extendTo, const uint160& currency) -{ // Index is 160-bit account credit extended to, 96-bit XOR of extending account and currency - uint256 base = getAccountRootIndex(extendTo); - memcpy(base.begin() + (160 / 8), (accountID ^ currency).begin(), (256 / 8) - (160 / 8)); - return base; +uint256 Ledger::getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) +{ + uint160 uAID = naA.getAccountID(); + uint160 uBID = naB.getAccountID(); + bool bAltB = uAID < uBID; + Serializer s; + + s.add160(bAltB ? uAID : uBID); + s.add160(bAltB ? uBID : uAID); + s.add160(uCurrency); + + return s.getSHA512Half(); } uint160 Ledger::getOfferBase(const uint160& currencyIn, const uint160& accountIn, diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index dc932ccbd9..5b079fedc7 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -137,4 +137,80 @@ SerializedLedgerEntry::pointer Ledger::getGenerator(LedgerStateParms& parms, con } } +// +// Ripple State +// + +SerializedLedgerEntry::pointer Ledger::getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) +{ + uint256 nodeID=getRippleStateIndex(naA, naB, uCurrency); + + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, nodeID, ltRIPPLE_STATE); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + +// +// Directory +// + +uint256 Ledger::getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir) +{ + // Indexes are stored in little endian format. + // The low bytes are indexed first, so when printed as a hex stream the hex is in byte order. + // Therefore, we place uNodeDir in the 8 right most bytes. + Serializer sKey; + + sKey.add256(uBase); + sKey.add8(letKind); + + uint256 uResult = sKey.getSHA512Half(); + + Serializer sNode; // Put in a fixed byte order: BIG. YYY + + sNode.add64(uNodeDir); + + std::copy(sNode.getData().end()-8, sNode.getData().end(), uResult.begin()+((256-64)/8)); + + return uResult; +} + +SerializedLedgerEntry::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, uRootIndex, ltDIR_ROOT); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + +SerializedLedgerEntry::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) +{ + ScopedLock l(mAccountStateMap->Lock()); + + try + { + return getASNode(parms, uNodeIndex, ltDIR_NODE); + } + catch (...) + { + parms = lepERROR; + return SerializedLedgerEntry::pointer(); + } +} + // vim:ts=4 diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index f858629e28..da0eb6ad3a 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -32,6 +32,10 @@ public: void add(Serializer& s) const { mVersion.add(s); mObject.add(s); } virtual bool isEquivalent(const SerializedType& t) const; + bool setFlag(uint32 uSet) { return mObject.setFlag(uSet); } + bool clearFlag(uint32 uClear) { return mObject.clearFlag(uClear); } + uint32 getFlags() const { return mObject.getFlags(); } + const uint256& getIndex() const { return mIndex; } void setIndex(const uint256& i) { mIndex = i; } @@ -55,6 +59,8 @@ public: std::vector getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); } NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); } STAmount getIValueFieldAmount(SOE_Field field) const { return mObject.getValueFieldAmount(field); } + STVector256 getIFieldV256(SOE_Field field) { return mObject.getValueFieldV256(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); } @@ -71,6 +77,7 @@ public: { return mObject.setValueFieldAccount(field, account); } void setIFieldAmount(SOE_Field field, const STAmount& amount) { return mObject.setValueFieldAmount(field, amount); } + void setIFieldV256(SOE_Field field, const STVector256& v) { return mObject.setValueFieldV256(field, v); } bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); } void makeIFieldPresent(SOE_Field field) { mObject.makeFieldPresent(field); } From 451df8141113d590452fb635ebc02c2b26463f9a Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:55:36 -0700 Subject: [PATCH 5/7] Add support for STVector256. --- src/SerializedTypes.cpp | 44 ++++++++++++++++++++++++++----- src/SerializedTypes.h | 58 +++++++++++++++++++++++++++++++++++++---- src/Serializer.h | 6 ++--- 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index c5fd60b8a9..6bbb2b7122 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -1,4 +1,5 @@ +#include #include #include "SerializedTypes.h" @@ -173,15 +174,44 @@ std::string STAccount::getText() const STAccount* STAccount::construct(SerializerIterator& u, const char *name) { - STAccount *ret = new STAccount(name, u.getVL()); - if (!ret->isValueH160()) - { - delete ret; - throw std::runtime_error("invalid account in transaction"); - } - return ret; + return new STAccount(name, u.getVL()); } +// +// STVector256 +// + +// Return a new object from a SerializerIterator. +STVector256* STVector256::construct(SerializerIterator& u, const char *name) +{ + return new STVector256(name, u.getVL()); +} + +void STVector256::add(Serializer& s) const +{ + s.add32(mValue.size()); + BOOST_FOREACH(const uint256& v, mValue) + { + s.add256(v); + } +} + +void STVector256::setValue(const std::vector& vucData) +{ + Serializer s(vucData); + SerializerIterator it(s); + uint64 uSize = it.get32(); + uint64 uIndex = 0; + + mValue.resize(uSize); + while (uSize--) + mValue[uIndex++] = it.get256(); +} + +// +// STAccount +// + bool STAccount::isValueH160() const { return peekValue().size() == (160/8); diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 1e4c9c92a2..957e868ab2 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -12,15 +12,28 @@ enum SerializedTypeID { // special types - STI_DONE=-1, STI_NOTPRESENT=0, + STI_DONE = -1, + STI_NOTPRESENT = 0, // standard types - STI_OBJECT=1, STI_UINT8=2, STI_UINT16=3, STI_UINT32=4, STI_UINT64=5, - STI_HASH128=6, STI_HASH160=7, STI_HASH256=8, STI_VL=9, STI_TL=10, - STI_AMOUNT=11, STI_PATHSET=12, + STI_OBJECT = 1, + STI_UINT8 = 2, + STI_UINT16 = 3, + STI_UINT32 = 4, + STI_UINT64 = 5, + STI_HASH128 = 6, + STI_HASH160 = 7, + STI_HASH256 = 8, + STI_VL = 9, + STI_TL = 10, + STI_AMOUNT = 11, + STI_PATHSET = 12, + STI_VECTOR256 = 13, // high level types - STI_ACCOUNT=100, STI_TRANSACTION=101, STI_LEDGERENTRY=102 + STI_ACCOUNT = 100, + STI_TRANSACTION = 101, + STI_LEDGERENTRY = 102 }; class SerializedType @@ -561,5 +574,40 @@ public: virtual bool isEquivalent(const SerializedType& t) const; }; +class STVector256 : public SerializedType +{ +protected: + std::vector mValue; + + STVector256* duplicate() const { return new STVector256(name, mValue); } + static STVector256* construct(SerializerIterator&, const char* name = NULL); + +public: + STVector256() { ; } + STVector256(const char* n) : SerializedType(n) { ; } + STVector256(const char* n, const std::vector& v) : SerializedType(n), mValue(v) { ; } + STVector256(const std::vector& vector) : mValue(vector) { ; } + STVector256(const char* n, const std::vector& vucSerial) : SerializedType(n) + { setValue(vucSerial); } + + SerializedTypeID getSType() const { return STI_VECTOR256; } + int getLength() const { return mValue.size()*(256/8)+(64/8); } + void add(Serializer& s) const; + + static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + { return std::auto_ptr(construct(sit, name)); } + + const std::vector& peekValue() const { return mValue; } + std::vector& peekValue() { return mValue; } + + std::vector getValue() const { return mValue; } + + bool isEmpty() const { return mValue.empty(); } + + void setValue(const STVector256& v) { mValue = v.mValue; } + void setValue(const std::vector& v) { mValue = v; } + void setValue(const std::vector& vucData); +}; + #endif // vim:ts=4 diff --git a/src/Serializer.h b/src/Serializer.h index 6000c4e89b..95fbbaa02e 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -14,13 +14,13 @@ typedef std::pair > TaggedListItem; class Serializer { - public: +public: typedef boost::shared_ptr pointer; - protected: +protected: std::vector mData; - public: +public: Serializer(int n=256) { mData.reserve(n); } Serializer(const std::vector &data) : mData(data) { ; } Serializer(const std::string& data) : mData(data.data(), (data.data()) + data.size()) { ; } From cb56ad036dbba321ce77bbf60044ea64cd155e00 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 02:57:00 -0700 Subject: [PATCH 6/7] Implement credit_set and directory support. --- src/RPCServer.cpp | 43 +-- src/Transaction.cpp | 18 +- src/Transaction.h | 8 +- src/TransactionEngine.cpp | 546 ++++++++++++++++++++++++++++--------- src/TransactionEngine.h | 53 +++- src/TransactionFormats.cpp | 6 +- src/main.cpp | 2 +- 7 files changed, 471 insertions(+), 205 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index e3b63cf40b..02343da2d8 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -130,15 +130,16 @@ int RPCServer::getParamCount(const Json::Value& params) return 1; } - +#if 0 // now, expire, n -bool RPCServer::parseBorrowRate(const std::string& sBorrowRate) +bool RPCServer::parseAcceptRate(const std::string& sAcceptRate) { - if (!sBorrowRate.compare("expire")) + if (!sAcceptRate.compare("expire")) 0; return true; } +#endif bool RPCServer::extractString(std::string& param, const Json::Value& params, int index) { @@ -373,30 +374,16 @@ Json::Value RPCServer::doPeers(Json::Value& params) return theApp->getConnectionPool().getPeersJson(); } -// credit_set [] [] [] +// credit_set [] Json::Value RPCServer::doCreditSet(Json::Value& params) { NewcoinAddress naSeed; NewcoinAddress naSrcAccountID; NewcoinAddress naDstAccountID; STAmount saLimitAmount; - std::string sBorrowRate; - std::string sBorrowStart; - std::string sBorrowExpire; - uint32 uBorrowRate; - uint32 uBorrowStart; - uint32 uBorrowExpire; + uint32 uAcceptRate = params.size() >= 6 ? boost::lexical_cast(params[5u].asString()) : 0; - if (params.size() >= 6) - sBorrowRate = params[6u].asString(); - - if (params.size() >= 7) - sBorrowStart = params[7u].asString(); - - if (params.size() >= 8) - sBorrowExpire = params[8u].asString(); - - if (params.size() < 5 || params.size() > 8) + if (params.size() < 5 || params.size() > 6) { return JSONRPCError(500, "invalid parameters"); } @@ -412,7 +399,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) { return JSONRPCError(500, "destination account id needed"); } - else if (!saLimitAmount.setValue(params[5u].asString(), params[6u].asString())) + else if (!saLimitAmount.setValue(params[3u].asString(), params[4u].asString())) { return JSONRPCError(500, "bad src amount/currency"); } @@ -427,16 +414,10 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) Json::Value obj = authorize(naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, sleSrc); if (!obj.empty()) - { return obj; - } STAmount saSrcBalance = sleSrc->getIValueFieldAmount(sfBalance); - uBorrowRate = 0; - uBorrowStart = 0; - uBorrowExpire = 0; - if (saSrcBalance < theConfig.FEE_DEFAULT) { return JSONRPCError(500, "insufficent funds"); @@ -451,9 +432,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) 0, // YYY No source tag naDstAccountID, saLimitAmount, - uBorrowRate, - uBorrowStart, - uBorrowExpire); + uAcceptRate); (void) theApp->getOPs().processTransaction(trans); @@ -463,9 +442,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) obj["srcAccountID"] = naSrcAccountID.humanAccountID(); obj["dstAccountID"] = naDstAccountID.humanAccountID(); obj["limitAmount"] = saLimitAmount.getText(); - obj["borrowRate"] = uBorrowRate; - obj["borrowStart"] = uBorrowStart; - obj["borrowExpire"] = uBorrowExpire; + obj["acceptRate"] = uAcceptRate; return obj; } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 5872fdbf27..0816b30d8e 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -190,18 +190,12 @@ Transaction::pointer Transaction::setCreditSet( const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire) + uint32 uAcceptRate) { mTransaction->setITFieldAccount(sfDestination, naDstAccountID); mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount); - if (uBorrowRate) - mTransaction->setITFieldU32(sfBorrowRate, uBorrowRate); - if (uBorrowStart) - mTransaction->setITFieldU32(sfBorrowStart, uBorrowStart); - if (uBorrowExpire) - mTransaction->setITFieldU32(sfBorrowExpire, uBorrowExpire); + if (uAcceptRate) + mTransaction->setITFieldU32(sfAcceptRate, uAcceptRate); sign(naPrivateKey); @@ -216,15 +210,13 @@ Transaction::pointer Transaction::sharedCreditSet( uint32 uSourceTag, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire) + uint32 uAcceptRate) { pointer tResult = boost::make_shared(ttCREDIT_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); - return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uBorrowRate, uBorrowStart, uBorrowExpire); + return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uAcceptRate); } // diff --git a/src/Transaction.h b/src/Transaction.h index e148270468..5f5789b328 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -61,9 +61,7 @@ private: const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire); + uint32 uAcceptRate); Transaction::pointer setPayment( const NewcoinAddress& naPrivateKey, @@ -119,9 +117,7 @@ public: uint32 uSourceTag, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire); + uint32 uAcceptRate); // Make a payment. static Transaction::pointer sharedPayment( diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index a1251e92f2..2dbb393575 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -2,9 +2,216 @@ #include "Config.h" #include "TransactionFormats.h" +#include "utils.h" #include +typedef SerializedLedgerEntry SLE; + +#define DIR_NODE_MAX 32 + +// We return the uNodeDir so that on delete we can quickly know where the element is mentioned in the directory. +TransactionEngineResult TransactionEngine::dirAdd( + std::vector& accounts, + uint64& uNodeDir, + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex) +{ + // Get the root. + uint256 uRootIndex = Ledger::getDirIndex(uBase, letKind); + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, uRootIndex); + bool bRootNew; + + // Get the last node index. + if (sleRoot) + { + bRootNew = false; + uNodeDir = sleRoot->getIFieldU64(sfLastNode); + } + else + { + bRootNew = true; + uNodeDir = 1; + + sleRoot = boost::make_shared(ltDIR_ROOT); + sleRoot->setIndex(uRootIndex); + sleRoot->setIFieldU64(sfFirstNode, uNodeDir); + sleRoot->setIFieldU64(sfLastNode, uNodeDir); + + accounts.push_back(std::make_pair(taaCREATE, sleRoot)); + } + + // Get the last node. + uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeDir); + LedgerStateParms lspNode = lepNONE; + SLE::pointer sleNode = bRootNew ? SLE::pointer() : mLedger->getDirNode(lspNode, uNodeIndex); + + if (sleNode) + { + STVector256 svIndexes; + + svIndexes = sleNode->getIFieldV256(sfIndexes); + if (DIR_NODE_MAX != svIndexes.peekValue().size()) + { + // Last node is not full, append. + + svIndexes.peekValue().push_back(uLedgerIndex); + sleNode->setIFieldV256(sfIndexes, svIndexes); + + accounts.push_back(std::make_pair(taaMODIFY, sleNode)); + } + // Last node is full, add a new node. + else if (!++uNodeDir) + { + return terDIR_FULL; + } + else + { + // Record new last node. + sleNode = SLE::pointer(); + + sleRoot->setIFieldU64(sfLastNode, uNodeDir); + accounts.push_back(std::make_pair(taaMODIFY, sleRoot)); + } + } + + if (!sleNode) + { + // Add to last node, which is empty. + sleNode = boost::make_shared(ltDIR_NODE); + sleNode->setIndex(uNodeIndex); + + STVector256 svIndexes; + + svIndexes.peekValue().push_back(uLedgerIndex); + sleNode->setIFieldV256(sfIndexes, svIndexes); + + accounts.push_back(std::make_pair(taaCREATE, sleNode)); + } + + return terSUCCESS; +} + +TransactionEngineResult TransactionEngine::dirDelete( + std::vector& accounts, + const uint64& uNodeDir, + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex) +{ + uint64 uNodeCur = uNodeDir; + uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeCur); + LedgerStateParms lspNode = lepNONE; + SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeIndex); + + if (!sleNode) + { + std::cerr << "dirDelete: no such node" << std::endl; + return terNODE_NOT_FOUND; + } + else + { + STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); + std::vector& vuiIndexes = svIndexes.peekValue(); + std::vector::iterator it; + + it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex); + if (vuiIndexes.end() == it) + { + std::cerr << "dirDelete: node not mentioned" << std::endl; + return terNODE_NOT_MENTIONED; + } + else + { + // Get root information + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, Ledger::getDirIndex(uBase, letKind)); + + if (!sleRoot) + { + std::cerr << "dirDelete: root node is missing" << std::endl; + return terNODE_NO_ROOT; + } + + uint64 uFirstNodeOrig = sleRoot->getIFieldU64(sfFirstNode); + uint64 uLastNodeOrig = sleRoot->getIFieldU64(sfLastNode); + uint64 uFirstNode = uFirstNodeOrig; + uint64 uLastNode = uLastNodeOrig; + + // Remove the element. + if (vuiIndexes.size() > 1) + { + *it = vuiIndexes[vuiIndexes.size()-1]; + } + vuiIndexes.resize(vuiIndexes.size()-1); + + sleNode->setIFieldV256(sfIndexes, svIndexes); + + if (!vuiIndexes.empty() || (uFirstNode != uNodeCur && uLastNode != uNodeCur)) + { + // Node is not being deleted. + accounts.push_back(std::make_pair(taaMODIFY, sleNode)); + } + + while (uFirstNode && svIndexes.peekValue().empty() + && (uFirstNode == uNodeCur || uLastNode == uNodeCur)) + { + // Current node is empty and first or last, delete it. + accounts.push_back(std::make_pair(taaDELETE, sleNode)); + + if (uFirstNode == uLastNode) + { + // Complete deletion. + uFirstNode = 0; + } + else + { + if (uFirstNode == uNodeCur) + { + // Advance first node + ++uNodeCur; + ++uFirstNode; + } + else + { + // Rewind last node + --uNodeCur; + --uLastNode; + } + + // Get replacement node. + lspNode = lepNONE; + sleNode = mLedger->getDirNode(lspNode, Ledger::getDirIndex(uBase, letKind, uNodeCur)); + svIndexes = sleNode->getIFieldV256(sfIndexes); + } + } + + if (uFirstNode == uFirstNodeOrig && uLastNode == uLastNodeOrig) + { + // Dir is fine. + nothing(); + } + else if (uFirstNode) + { + // Update root's pointer pointers. + sleRoot->setIFieldU64(sfFirstNode, uFirstNode); + sleRoot->setIFieldU64(sfLastNode, uLastNode); + + accounts.push_back(std::make_pair(taaMODIFY, sleRoot)); + } + else + { + // Delete the root. + accounts.push_back(std::make_pair(taaDELETE, sleRoot)); + } + } + + return terSUCCESS; + } +} + TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { @@ -106,8 +313,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // find source account // If we are only verifying some transactions, this would be probablistic. - LedgerStateParms qry = lepNONE; - SerializedLedgerEntry::pointer sleSrc = mLedger->getAccountRoot(qry, srcAccountID); + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleSrc = mLedger->getAccountRoot(lspRoot, srcAccountID); if (!sleSrc) { std::cerr << str(boost::format("applyTransaction: Delay transaction: source account does not exisit: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; @@ -178,7 +385,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran break; case ttCREDIT_SET: - result = doCreditSet(txn, accounts); + result = doCreditSet(txn, accounts, srcAccountID); break; case ttINVALID: @@ -256,34 +463,34 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& return tenINVALID; } - LedgerStateParms qry = lepNONE; - SerializedLedgerEntry::pointer dest = accounts[0].second; + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = accounts[0].second; - if (!dest) + if (!sleDst) { // Source account does not exist. Could succeed if it was created first. std::cerr << str(boost::format("doClaim: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; return terNO_ACCOUNT; } - std::cerr << str(boost::format("doClaim: %s") % dest->getFullText()) << std::endl; + std::cerr << str(boost::format("doClaim: %s") % sleDst->getFullText()) << std::endl; - if (dest->getIFieldPresent(sfAuthorizedKey)) + if (sleDst->getIFieldPresent(sfAuthorizedKey)) { // Source account already claimed. std::cerr << "doClaim: source already claimed" << std::endl; - return tenCLAIMED; + return terCLAIMED; } // // Verify claim is authorized for public key. // - std::vector vucCipher = txn.getITFieldVL(sfGenerator); - std::vector vucPubKey = txn.getITFieldVL(sfPubKey); - std::vector vucSignature = txn.getITFieldVL(sfSignature); + std::vector vucCipher = txn.getITFieldVL(sfGenerator); + std::vector vucPubKey = txn.getITFieldVL(sfPubKey); + std::vector vucSignature = txn.getITFieldVL(sfSignature); - NewcoinAddress naAccountPublic; + NewcoinAddress naAccountPublic; naAccountPublic.setAccountPublic(vucPubKey); @@ -297,11 +504,11 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& // Verify generator not already in use. // - uint160 hGeneratorID = naAccountPublic.getAccountID(); + uint160 hGeneratorID = naAccountPublic.getAccountID(); - qry = lepNONE; - SerializedLedgerEntry::pointer gen = mLedger->getGenerator(qry, hGeneratorID); - if (gen) + qry = lepNONE; + SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID); + if (sleGen) { // Generator is already in use. Regular passphrases limited to one wallet. std::cerr << "doClaim: generator already in use" << std::endl; @@ -313,41 +520,132 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& // // Set the public key needed to use the account. - dest->setIFieldH160(sfAuthorizedKey, hGeneratorID); + sleDst->setIFieldH160(sfAuthorizedKey, hGeneratorID); // Construct a generator map entry. - gen = boost::make_shared(ltGENERATOR_MAP); + sleGen = boost::make_shared(ltGENERATOR_MAP); - gen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); - gen->setIFieldH160(sfGeneratorID, hGeneratorID); - gen->setIFieldVL(sfGenerator, vucCipher); + sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); + sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); + sleGen->setIFieldVL(sfGenerator, vucCipher); - accounts.push_back(std::make_pair(taaCREATE, gen)); + accounts.push_back(std::make_pair(taaCREATE, sleGen)); std::cerr << "doClaim<" << std::endl; + return terSUCCESS; } -TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction&, std::vector&) +TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction& txn, + std::vector&accounts, + const uint160& uSrcAccountID) { - return tenINVALID; + TransactionEngineResult terResult = terSUCCESS; + std::cerr << "doCreditSet>" << std::endl; + + // Check if destination makes sense. + uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); + + if (!uDstAccountID) + { + std::cerr << "doCreditSet: Invalid transaction: Payment destination account not specifed." << std::endl; + return tenDST_NEEDED; + } + else if (uSrcAccountID == uDstAccountID) + { + std::cerr << "doCreditSet: Invalid transaction: Source account is the same as destination." << std::endl; + return tenDST_IS_SRC; + } + + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID); + if (!sleDst) + { + std::cerr << "doCreditSet: Delay transaction: Destination account does not exist." << std::endl; + + return terNO_DST; + } + + STAmount saLimitAmount = txn.getITFieldAmount(sfLimitAmount); + uint160 uCurrency = saLimitAmount.getCurrency(); + bool bSltD = uSrcAccountID < uDstAccountID; + uint32 uFlags = bSltD ? lsfLowIndexed : lsfHighIndexed; + STAmount saBalance(uCurrency); + bool bAddIndex; + + qry = lepNONE; + SLE::pointer sleRippleState = mLedger->getRippleState(qry, uSrcAccountID, uDstAccountID, uCurrency); + if (sleRippleState) + { + std::cerr << "doCreditSet: Modifying ripple line." << std::endl; + + bAddIndex = !(sleRippleState->getFlags() & uFlags); + + sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighID, saLimitAmount); + + accounts.push_back(std::make_pair(taaMODIFY, sleRippleState)); + + if (bAddIndex) + sleRippleState->setFlag(uFlags); + } + // Line does not exist. + else if (!saLimitAmount.getValue()) + { + std::cerr << "doCreditSet: Setting non-existant ripple line to 0." << std::endl; + + return terNO_LINE_NO_ZERO; + } + else + { + std::cerr << "doCreditSet: Creating ripple line." << std::endl; + STAmount saZero(uCurrency); + + bAddIndex = true; + sleRippleState = boost::make_shared(ltRIPPLE_STATE); + + sleRippleState->setIndex(Ledger::getRippleStateIndex(uSrcAccountID, uDstAccountID, uCurrency)); + + sleRippleState->setFlag(uFlags); + sleRippleState->setIFieldAmount(sfBalance, saZero); // Zero balance in currency. + sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighLimit, saLimitAmount); + sleRippleState->setIFieldAmount(bSltD ? sfHighLimit : sfLowLimit, saZero); + sleRippleState->setIFieldAccount(bSltD ? sfLowID : sfHighID, uSrcAccountID); + sleRippleState->setIFieldAccount(bSltD ? sfHighID : sfLowID, uDstAccountID); + + accounts.push_back(std::make_pair(taaCREATE, sleRippleState)); + } + + if (bAddIndex) + { + // Add entries so clients can find lines. + // - Client needs to be able to walk who account has given credit to and who has account's credit. + // - Client doesn't need to know every account who has extended credit but it owed nothing. + uint64 uSrcRef; // Ignored, ripple_state dirs never delete. + + // XXX Verify extend is passing the right bits, not the zero bits. + // XXX Make dirAdd more flexiable to take vector. + terResult = dirAdd(accounts, uSrcRef, ltRIPPLE_STATE, uint160extend256(uSrcAccountID, 0), sleRippleState->getIndex()); + } + + std::cerr << "doCreditSet<" << std::endl; + + return terResult; } TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, std::vector& accounts, - uint160 srcAccountID) + const uint160& srcAccountID) { uint32 txFlags = txn.getFlags(); - uint160 dstAccountID = txn.getITFieldAccount(sfDestination); + uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); - // Does the destination account exist? - if (!dstAccountID) + if (!uDstAccountID) { std::cerr << "doPayment: Invalid transaction: Payment destination account not specifed." << std::endl; return tenINVALID; } // XXX Only bad if no currency conversion in between through other people's offer. - else if (srcAccountID == dstAccountID) + else if (srcAccountID == uDstAccountID) { std::cerr << "doPayment: Invalid transaction: Source account is the same as destination." << std::endl; return tenINVALID; @@ -355,24 +653,23 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction bool bCreate = !!(txFlags & tfCreateAccount); - uint160 currency; + uint160 uCurrency; if (txn.getITFieldPresent(sfCurrency)) { - currency = txn.getITFieldH160(sfCurrency); - if (!currency) + uCurrency = txn.getITFieldH160(sfCurrency); + if (!uCurrency) { - std::cerr << "doPayment: Invalid transaction: XNC explicitly specified." << std::endl; + std::cerr << "doPayment: Invalid transaction: " SYSTEM_CURRENCY_CODE " explicitly specified." << std::endl; return tenEXPLICITXNC; } } - LedgerStateParms qry = lepNONE; - - SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, dstAccountID); - if (!dest) + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID); + if (!sleDst) { // Destination account does not exist. - if (bCreate && !!currency) + if (bCreate && !!uCurrency) { std::cerr << "doPayment: Invalid transaction: Create account may only fund XBC." << std::endl; return tenCREATEXNC; @@ -380,32 +677,32 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction else if (!bCreate) { std::cerr << "doPayment: Delay transaction: Destination account does not exist." << std::endl; - return terNO_TARGET; + return terNO_DST; } // Create the account. - dest = boost::make_shared(ltACCOUNT_ROOT); + sleDst = boost::make_shared(ltACCOUNT_ROOT); - dest->setIndex(Ledger::getAccountRootIndex(dstAccountID)); - dest->setIFieldAccount(sfAccount, dstAccountID); - dest->setIFieldU32(sfSequence, 1); + sleDst->setIndex(Ledger::getAccountRootIndex(uDstAccountID)); + sleDst->setIFieldAccount(sfAccount, uDstAccountID); + sleDst->setIFieldU32(sfSequence, 1); - accounts.push_back(std::make_pair(taaCREATE, dest)); + accounts.push_back(std::make_pair(taaCREATE, sleDst)); } // Destination exists. else if (bCreate) { std::cerr << "doPayment: Invalid transaction: Account already created." << std::endl; - return tenCREATED; + return terCREATED; } else { - accounts.push_back(std::make_pair(taaMODIFY, dest)); + accounts.push_back(std::make_pair(taaMODIFY, sleDst)); } STAmount saAmount = txn.getITFieldAmount(sfAmount); - if (!currency) + if (!uCurrency) { STAmount saSrcBalance = accounts[0].second->getIValueFieldAmount(sfBalance); @@ -430,8 +727,8 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector&) { std::cerr << "doTransitSet>" << std::endl; - - SerializedLedgerEntry::pointer sleSrc = accounts[0].second; +#if 0 + SLE::pointer sleSrc = accounts[0].second; bool bTxnTransitRate = st->getIFieldPresent(sfTransitRate); bool bTxnTransitStart = st->getIFieldPresent(sfTransitStart); @@ -451,104 +748,85 @@ TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransact uint32 uActNextTransitStart = bActNextTransitStart ? sleSrc->getIFieldU32(sfNextTransitStart) : 0; uint32 uActNextTransitExpire = bActNextTransitExpire ? sleSrc->getIFieldU32(sfNextTransitExpire) : 0; - // Try to overwrite next rate. + // + // Update view + // - bool bBetterNextExpire = - (!bTxnTransitExpire // Txn does not expire (same or extends) - || (bActNextTransitExpire && uTxnTransitExpire >= uActTransitExpire)); // Same or longer the next. + bool bNoCurrent = !bActTransitRate; + bool bCurrentExpired = + bActTransitExpire // Current can expire + && bActNextTransitStart // Have a replacement + && uActTransitExpire <= uLedger; // Current is expired - bool bBetterNextRate = - !bActNextTransitRate // No next rate, txn is better. - || (uTxnTransitRate <= uActNextTransitRate); // Charge is the same or less. - - // Must start at the same time or sooner. - bool bBetterNextStart = - - // If starting sooner, must be better than current, or current must not protect range. - - - if (!bActNextTransitRate) + // Replace current with next if need. + if (bNoCurrent // No current. + && bActNextTransitRate // Have next. + && uActNextTransitStart <= uLedger) // Next has started. { - // No next. Overwrite next. - } - else if (uTxnTransitRate <= uActNextTransitRate && bBetterNextExpire) - { - // Better than + // Make next current. + uActTransitRate = uActNextTransitRate; + bActTransitExpire = bActNextTransitStart; + uActTransitExpire = uActNextTransitExpire; + + // Remove next. + uActNextTransitStart = 0; } - // True if no rate is active or going to be active; - bool bNoRate = !bActTransitRate && !bActNextTransitRate; + // + // Determine new transaction deposition. + // - bool bStartNow = bTxnTransitStart - ? uTxnTransitStart < uLedger - : bActTransitRate - ? bActTransitExpire - ? - : true // Current never expires. - : true; // Nothing is running. + bool bBetterThanCurrent = + !no current + || ( + Expires same or later than current + Start before or same as current + Fee same or less than current + ) - // True if new rate does not apply immediately. - boo bRateIsLater = bTxnTransitStart - ? uTxnTransitStart < uLedger + bool bBetterThanNext = + !no next + || ( + Expires same or later than next + Start before or same as next + Fee same or less than next + ) - : bActNextTransitRate && bTxnTransitExpire; + bool bBetterThanBoth = + bBetterThanCurrent && bBetterThanNext - if (no_rate || rate_is_better || rate_is_later) + bool bCurrentBlocks = + !bBetterThanCurrent + && overlaps with current + + bool bNextBlocks = + !bBetterThanNext + && overlaps with next + + if (bBetterThanBoth) { - // Install. - if (starting) - { - // install now - } - else - { - // install next - } + // Erase both and install. + + // If not starting now, install as next. + } + else if (bCurrentBlocks || bNextBlocks) + { + // Invalid ignore + } + else if (bBetterThanCurrent) + { + // Install over current + } + else if (bBetterThanNext) + { + // Install over next } else { - return tenTRANSIT_WORSE; + // Error. } - if (no_rate && starting) - if (!bActTransitRate && !bActNextTransitRate) { - // No rate - bProtected = false; - } if (bActTransitRate && !bTx - - if (bTxnTransitStart && uTxnTransitStart > uLedger) - { - // Start at a particular time. - - } - else - { - // No start or start in the past, start now. - if (!bActTransitRate && !bActNextTransitRate) - { - // No current or future rate. - - uDstTransitRate = uTxnTransitRate; - uDstTransitExpire = uTxnTransitExpire; // 0 for never expire. - } - else if (bActTransitRate && !bActNextTransitRate) - { - // Have a current rate and none pending. - if (!bActTransitExpire) { - // Current rate does not expire - - } - } - else - { - // Have a future rate. - - } - } - if (!bActTransitRate && !bActNextTransitRate) - { - - } + return tenTRANSIT_WORSE; // Set current. uDstTransitRate = uTxnTransitRate; @@ -560,7 +838,7 @@ TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransact uDstNextTransitExpire = uTxnTransitExpire; // 0 for never expire. if (txn.getITFieldPresent(sfCurrency)) - +#endif std::cerr << "doTransitSet<" << std::endl; return tenINVALID; } diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index bd2f3bdd55..2679b9dbfe 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -18,11 +18,9 @@ enum TransactionEngineResult tenGEN_IN_USE = -300, // Generator already in use. tenCREATEXNC, // Can not specify non XNC for Create. tenEXPLICITXNC, // XNC is used by default, don't specify it. + tenDST_NEEDED, // Destination not specified. + tenDST_IS_SRC, // Destination may not be source. - // Not possible due to ledger database: Fee claimed - tenCREATED = -200, // Can not create a previously created account. - tenCLAIMED, // Can not claim a previously claimed account. - tenTRANSIT_WORSE, // Can not override a better promise. // Other tenFAILED = -100, // Something broke horribly @@ -32,18 +30,27 @@ enum TransactionEngineResult terSUCCESS = 0, // The transaction was applied - // terFAILED_BUT_COULD_SUCEED = >0 + // terFAILED_BUT_COULD_SUCCEED = >0 + // Conflict with ledger database: Fee claimed + // Might succeed if not conflict is not caused by transaction ordering. 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) - 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 terBAD_SEQ, // This sequence number should be zero for prepaid transactions. - terPRE_SEQ, // Missing/inapplicable prior transaction + terCLAIMED, // Can not claim a previously claimed account. + terCREATED, // Can not create a previously created account. + terDIR_FULL, // Can not add entry to full dir. + terINSUF_FEE_B, // Account balance can't pay fee + terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load) + terNODE_NOT_FOUND, // Can not delete a dir node. + terNODE_NOT_MENTIONED, + terNODE_NO_ROOT, + terNO_ACCOUNT, // The source account does not exist + terNO_DST, // The destination does not exist + terNO_PATH, // No path existed or met transaction/balance requirements terPAST_LEDGER, // The transaction expired and can't be applied + terPAST_SEQ, // This sequence number has already past + terPRE_SEQ, // Missing/inapplicable prior transaction + terUNFUNDED, // Source account had insufficient balance for transactin + terNO_LINE_NO_ZERO, // Can't zero non-existant line, destination might make it. }; enum TransactionEngineParams @@ -65,17 +72,33 @@ typedef std::pair Affe class TransactionEngine { +private: + TransactionEngineResult dirAdd( + std::vector& accounts, + uint64& uNodeDir, // Node of entry. + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex); + + TransactionEngineResult dirDelete( + std::vector& accounts, + const uint64& uNodeDir, // Node item is mentioned in. + const LedgerEntryType letKind, + const uint256& uBase, // Key of item. + const uint256& uLedgerIndex); // Item being deleted + protected: Ledger::pointer mLedger; - TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector&); TransactionEngineResult doCancel(const SerializedTransaction&, std::vector&); TransactionEngineResult doClaim(const SerializedTransaction&, std::vector&); + TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector&, + const uint160& srcAccountID); TransactionEngineResult doDelete(const SerializedTransaction&, std::vector&); TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector&); TransactionEngineResult doOffer(const SerializedTransaction&, std::vector&); TransactionEngineResult doPayment(const SerializedTransaction&, std::vector&, - uint160 srcAccountID); + const uint160& srcAccountID); TransactionEngineResult doStore(const SerializedTransaction&, std::vector&); TransactionEngineResult doTake(const SerializedTransaction&, std::vector&); TransactionEngineResult doTransitSet(const SerializedTransaction&, std::vector&); diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index 42af4a4c12..10d435f26c 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -18,9 +18,9 @@ TransactionFormat InnerTxnFormats[]= { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(LimitAmount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(BorrowRate), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(BorrowStart), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(BorrowExpire), STI_UINT32, SOE_IFFLAG, 4 }, + { S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(AcceptStart), STI_UINT32, SOE_IFFLAG, 2 }, + { S_FIELD(AcceptExpire), STI_UINT32, SOE_IFFLAG, 4 }, { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 8 }, { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } diff --git a/src/main.cpp b/src/main.cpp index 8c8177cec5..21256e672a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,7 @@ void printHelp(const po::options_description& desc) cout << " account_info |" << endl; cout << " account_info || []" << endl; cout << " connect []" << endl; - cout << " credit_set [] [] []" << endl; + cout << " credit_set []" << endl; cout << " ledger" << endl; cout << " peers" << endl; cout << " send [] [] []" << endl; From d54c1acdfd3532972f3c10aaee046138af9d28bd Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Sat, 26 May 2012 17:25:05 -0700 Subject: [PATCH 7/7] Fix dir index creation and make currency specification optional for credit_set. --- src/LedgerNode.cpp | 5 ++++- src/RPCServer.cpp | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index 5b079fedc7..61418484ca 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -178,7 +178,10 @@ uint256 Ledger::getDirIndex(const uint256& uBase, const LedgerEntryType letKind, sNode.add64(uNodeDir); - std::copy(sNode.getData().end()-8, sNode.getData().end(), uResult.begin()+((256-64)/8)); + // YYY SLOPPY + std::vector vucData = sNode.getData(); + + std::copy(vucData.begin(), vucData.end(), uResult.end()-(64/8)); return uResult; } diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 02343da2d8..8b50485d75 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -374,7 +374,7 @@ Json::Value RPCServer::doPeers(Json::Value& params) return theApp->getConnectionPool().getPeersJson(); } -// credit_set [] +// credit_set [] [] Json::Value RPCServer::doCreditSet(Json::Value& params) { NewcoinAddress naSeed; @@ -383,7 +383,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) STAmount saLimitAmount; uint32 uAcceptRate = params.size() >= 6 ? boost::lexical_cast(params[5u].asString()) : 0; - if (params.size() < 5 || params.size() > 6) + if (params.size() < 4 || params.size() > 6) { return JSONRPCError(500, "invalid parameters"); } @@ -399,7 +399,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) { return JSONRPCError(500, "destination account id needed"); } - else if (!saLimitAmount.setValue(params[3u].asString(), params[4u].asString())) + else if (!saLimitAmount.setValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "")) { return JSONRPCError(500, "bad src amount/currency"); }