From 0f02695f21d2cc9639fd647453560a7941c739c2 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 4 Jun 2012 15:25:01 -0700 Subject: [PATCH 01/17] Add NicknameSet to TransactionFormats. --- src/SerializedObject.h | 1 + src/TransactionFormats.cpp | 9 +++++++++ src/TransactionFormats.h | 1 + 3 files changed, 11 insertions(+) diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 3c322486da..de9f3d2b7f 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -72,6 +72,7 @@ enum SOE_Field sfNextTransitStart, sfNickname, sfOfferCurrency, + sfOfferMin, sfPaths, sfPubKey, sfSendMax, diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index 66995e5a92..c0f2f73a51 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -44,6 +44,15 @@ TransactionFormat InnerTxnFormats[]= { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } }, + { "NicknameSet", ttNICKNAME_SET, { + { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, + { S_FIELD(Nickname), STI_HASH256, SOE_IFFLAG, 8 }, + { S_FIELD(OfferMin), STI_AMOUNT, SOE_IFFLAG, 1 }, + { S_FIELD(Signature), STI_VL, SOE_IFFLAG, 2 }, + { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 }, + { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + }, { "Offer", ttOFFER, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(AmountIn), STI_AMOUNT, SOE_REQUIRED, 0 }, diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h index 6833560696..3f053521f2 100644 --- a/src/TransactionFormats.h +++ b/src/TransactionFormats.h @@ -12,6 +12,7 @@ enum TransactionType ttACCOUNT_SET = 3, ttPASSWORD_FUND = 4, ttPASSWORD_SET = 5, + ttNICKNAME_SET = 6, ttCREDIT_SET = 20, ttTRANSIT_SET = 21, ttINVOICE = 10, From a9876135954a93e85bcbc53893ddb40b90b2091d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 4 Jun 2012 23:28:34 -0700 Subject: [PATCH 02/17] Fix some errors to be temporary. --- src/TransactionEngine.cpp | 7 +++---- src/TransactionEngine.h | 6 +++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 5126bbd4fa..e9e71b2192 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -473,7 +473,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran { std::cerr << "applyTransaction: Source is an unclaimed account." << std::endl; - result = tenUNCLAIMED; + result = terUNCLAIMED; } break; } @@ -514,9 +514,9 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // Verify the transaction's signing public key is the key authorized for signing. if (naSigningPubKey.getAccountID() != sleSrc->getIValueFieldAccount(sfAuthorizedKey).getAccountID()) { - std::cerr << "applyTransaction: Not authorized to use account." << std::endl; + std::cerr << "applyTransaction: Delay: Not authorized to use account." << std::endl; - result = tenBAD_AUTH; + result = terBAD_AUTH; } break; } @@ -651,7 +651,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran if (terSUCCESS == result) { // Write back the account states and add the transaction to the ledger - // WRITEME: Special case code for changing transaction key for (std::vector::iterator it = accounts.begin(), end = accounts.end(); it != end; ++it) { diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 75b79aca07..87aec83de0 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -24,9 +24,7 @@ enum TransactionEngineResult tenBAD_SET_ID, // Malformed. // Invalid: Ledger won't allow. - tenUNCLAIMED = -200, // Can not use an unclaimed account. - tenCLAIMED, // Can not claim a previously claimed account. - tenBAD_AUTH, // Transaction's public key is not authorized. + tenCLAIMED = -200, // Can not claim a previously claimed account. tenCREATED, // Can't add an already created account. tenMSG_SET, // Can't change a message key. @@ -60,6 +58,8 @@ enum TransactionEngineResult terNO_LINE_NO_ZERO, // Can't zero non-existant line, destination might make it. terSET_MISSING_DST, // Can't set password, destination missing. terFUNDS_SPENT, // Can't set password, password set funds already spent. + terUNCLAIMED, // Can not use an unclaimed account. + terBAD_AUTH, // Transaction's public key is not authorized. }; enum TransactionEngineParams From 189b11551351abca2da09530df13644768e4b035 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:03:47 -0700 Subject: [PATCH 03/17] Fix serialized format for nicknames. --- src/LedgerFormats.cpp | 5 ++--- src/SerializedObject.h | 1 - src/TransactionFormats.cpp | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index df6fb2350e..afee90b4c9 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -35,17 +35,16 @@ LedgerEntryFormat LedgerFormats[]= }, { "GeneratorMap", ltGENERATOR_MAP, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 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(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 } } }, diff --git a/src/SerializedObject.h b/src/SerializedObject.h index de9f3d2b7f..3c322486da 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -72,7 +72,6 @@ enum SOE_Field sfNextTransitStart, sfNickname, sfOfferCurrency, - sfOfferMin, sfPaths, sfPubKey, sfSendMax, diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index c0f2f73a51..cddcafcf6c 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -47,7 +47,7 @@ TransactionFormat InnerTxnFormats[]= { "NicknameSet", ttNICKNAME_SET, { { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(Nickname), STI_HASH256, SOE_IFFLAG, 8 }, - { S_FIELD(OfferMin), STI_AMOUNT, SOE_IFFLAG, 1 }, + { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, { S_FIELD(Signature), STI_VL, SOE_IFFLAG, 2 }, { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 }, From ea64ee3e5898160e731891f7559aa731d16e1e18 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:04:42 -0700 Subject: [PATCH 04/17] Implement doNicknameSet. --- src/TransactionEngine.cpp | 62 +++++++++++++++++++++++++++++++++++++-- src/TransactionEngine.h | 2 ++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 39691b3d3d..6a39913884 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -259,7 +259,7 @@ TransactionEngineResult TransactionEngine::setAuthorized(const SerializedTransac sleGen = boost::make_shared(ltGENERATOR_MAP); sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); - sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); +// sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); sleGen->setIFieldVL(sfGenerator, vucCipher); accounts.push_back(std::make_pair(taaCREATE, sleGen)); @@ -548,7 +548,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran { nothing(); } - else if (saCost) + else if (saCost.isZero()) { uint32 a_seq = sleSrc->getIFieldU32(sfSequence); @@ -622,6 +622,10 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran result = doOffer(txn, accounts); break; + case ttNICKNAME_SET: + result = doNicknameSet(txn, accounts, srcAccountID); + break; + case ttPASSWORD_FUND: result = doPasswordFund(txn, accounts, srcAccountID); break; @@ -869,6 +873,60 @@ TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransacti return terResult; } +TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransaction& txn, std::vector& accounts, const uint160& uSrcAccountID) +{ + std::cerr << "doNicknameSet>" << std::endl; + + SLE::pointer sleSrc = accounts[0].second; + + uint256 uNickname = txn.getITFieldH256(sfWalletLocator); + bool bMinOffer = txn.getITFieldPresent(sfMinimumOffer); + STAmount saMinOffer = bMinOffer ? txn.getITFieldAmount(sfAmount) : STAmount(); + + LedgerStateParms qry = lepNONE; + SLE::pointer sleNickname = mLedger->getNickname(qry, uNickname); + + if (sleNickname) + { + // Edit old entry. + sleNickname->setIFieldAccount(sfAccount, uSrcAccountID); + + if (bMinOffer && !saMinOffer.isZero()) + { + sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer); + } + else + { + sleNickname->makeIFieldAbsent(sfMinimumOffer); + } + + accounts.push_back(std::make_pair(taaCREATE, sleNickname)); + } + else + { + // Make a new entry. + // XXX Need to include authorization limiting. + + sleNickname = boost::make_shared(ltNICKNAME); + + sleNickname->setIndex(Ledger::getNicknameIndex(uNickname)); + std::cerr << "doNicknameSet: Creating nickname node: " << sleNickname->getIndex().ToString() << std::endl; + + sleNickname->setIFieldAccount(sfAccount, uSrcAccountID); + + if (bMinOffer && !saMinOffer.isZero()) + sleNickname->setIFieldAmount(sfMinimumOffer, saMinOffer); + +// sleNickname->setIFieldH256(sfNickname, uNickname); + + accounts.push_back(std::make_pair(taaCREATE, sleNickname)); + } + + std::cerr << "doNicknameSet<" << std::endl; + + return terSUCCESS; +} + TransactionEngineResult TransactionEngine::doPasswordFund(const SerializedTransaction& txn, std::vector& accounts, const uint160& uSrcAccountID) { std::cerr << "doPasswordFund>" << std::endl; diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 75b79aca07..9d79ff37f9 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -108,6 +108,8 @@ protected: TransactionEngineResult doDelete(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doInvoice(const SerializedTransaction& txn, std::vector& accounts); TransactionEngineResult doOffer(const SerializedTransaction& txn, std::vector& accounts); + TransactionEngineResult doNicknameSet(const SerializedTransaction& txn, std::vector& accounts, + const uint160& uSrcAccountID); TransactionEngineResult doPasswordFund(const SerializedTransaction& txn, std::vector& accounts, const uint160& uSrcAccountID); TransactionEngineResult doPasswordSet(const SerializedTransaction& txn, std::vector& accounts); From 26d7f0e1a45c5acd1fab2357fbbd5684ae70af30 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:05:42 -0700 Subject: [PATCH 05/17] Add ledger fuctionality for NicknameState. --- src/Ledger.cpp | 15 +++++++++++ src/Ledger.h | 48 +++++++++++++++++++++++------------ src/LedgerIndex.cpp | 33 ++++++++++++++++-------- src/LedgerNode.cpp | 61 +++++++++++++++++++-------------------------- src/RippleState.h | 1 + 5 files changed, 96 insertions(+), 62 deletions(-) diff --git a/src/Ledger.cpp b/src/Ledger.cpp index 1fda2ca217..fd12a7979c 100644 --- a/src/Ledger.cpp +++ b/src/Ledger.cpp @@ -153,6 +153,21 @@ AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID) return boost::make_shared(sle); } +NicknameState::pointer Ledger::getNicknameState(const uint256& uNickname) +{ + ScopedLock l(mAccountStateMap->Lock()); + SHAMapItem::pointer item = mAccountStateMap->peekItem(Ledger::getNicknameIndex(uNickname)); + if (!item) + { + return NicknameState::pointer(); + } + + SerializedLedgerEntry::pointer sle = + boost::make_shared(item->peekSerializer(), item->getTag()); + if (sle->getType() != ltNICKNAME) return NicknameState::pointer(); + return boost::make_shared(sle); +} + RippleState::pointer Ledger::getRippleState(const uint256& uNode) { ScopedLock l(mAccountStateMap->Lock()); diff --git a/src/Ledger.h b/src/Ledger.h index d4fe92f460..8d7c8f5831 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -13,6 +13,7 @@ #include "Transaction.h" #include "AccountState.h" #include "RippleState.h" +#include "NicknameState.h" #include "types.h" #include "BitcoinUtil.h" #include "SHAMap.h" @@ -137,8 +138,6 @@ public: LedgerStateParms writeBack(LedgerStateParms parms, SLE::pointer); SLE::pointer getAccountRoot(LedgerStateParms& parms, const uint160& accountID); SLE::pointer getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID); - SLE::pointer getNickname(LedgerStateParms& parms, const std::string& nickname); - SLE::pointer getNickname(LedgerStateParms& parms, const uint256& nickHash); // database functions static void saveAcceptedLedger(Ledger::pointer); @@ -160,25 +159,21 @@ public: static uint256 getGeneratorIndex(const uint160& uGeneratorID); // - // Ripple functions + // Nickname functions // - 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); } + uint256 getNicknameHash(const std::string& strNickname) + { Serializer s(strNickname); return s.getSHA256(); } - static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB) - { return getRippleStateIndex(naA, naB, uint160()); } - static uint256 getRippleDirIndex(const uint160& uAccountID); + NicknameState::pointer getNicknameState(const uint256& uNickname); + NicknameState::pointer getNicknameState(const std::string& strNickname) + { return getNicknameState(getNicknameHash(strNickname)); } - RippleState::pointer getRippleState(const uint256& uNode); - SLE::pointer getRippleState(LedgerStateParms& parms, const uint256& uNode); + SLE::pointer getNickname(LedgerStateParms& parms, const uint256& uNickname); + SLE::pointer getNickname(LedgerStateParms& parms, const std::string& strNickname) + { return getNickname(parms, getNicknameHash(strNickname)); } - SLE::pointer getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) - { return getRippleState(parms, getRippleStateIndex(naA, naB, uCurrency)); } - - SLE::pointer getRippleState(LedgerStateParms& parms, const uint160& uiA, const uint160& uiB, const uint160& uCurrency) - { return getRippleState(parms, getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency)); } + static uint256 getNicknameIndex(const uint256& uNickname); // // Offer functions @@ -200,6 +195,27 @@ public: SLE::pointer getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex); SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex); + // + // Ripple functions + // + + 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 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB) + { return getRippleStateIndex(naA, naB, uint160()); } + static uint256 getRippleDirIndex(const uint160& uAccountID); + + RippleState::pointer getRippleState(const uint256& uNode); + SLE::pointer getRippleState(LedgerStateParms& parms, const uint256& uNode); + + SLE::pointer getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) + { return getRippleState(parms, getRippleStateIndex(naA, naB, uCurrency)); } + + SLE::pointer getRippleState(LedgerStateParms& parms, const uint160& uiA, const uint160& uiB, const uint160& uCurrency) + { return getRippleState(parms, getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency)); } + // // Misc // diff --git a/src/LedgerIndex.cpp b/src/LedgerIndex.cpp index 89d78ed2a3..0bf18f1c88 100644 --- a/src/LedgerIndex.cpp +++ b/src/LedgerIndex.cpp @@ -11,6 +11,29 @@ uint256 Ledger::getAccountRootIndex(const uint160& uAccountID) return s.getSHA512Half(); } +// What is important: +// --> uNickname: is a Sha256 +// <-- SHA512/2: for consistency and speed in generating indexes. +uint256 Ledger::getNicknameIndex(const uint256& uNickname) +{ + Serializer s; + + s.add16(spaceNickname); + s.add256(uNickname); + + return s.getSHA512Half(); +} + +uint256 Ledger::getGeneratorIndex(const uint160& uGeneratorID) +{ + Serializer s; + + s.add16(spaceGenerator); + s.add160(uGeneratorID); + + return s.getSHA512Half(); +} + uint256 Ledger::getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency) { uint160 uAID = naA.getAccountID(); @@ -36,16 +59,6 @@ uint256 Ledger::getRippleDirIndex(const uint160& uAccountID) return s.getSHA512Half(); } -uint256 Ledger::getGeneratorIndex(const uint160& uGeneratorID) -{ - Serializer s; - - s.add16(spaceGenerator); - s.add160(uGeneratorID); - - return s.getSHA512Half(); -} - uint160 Ledger::getOfferBase(const uint160& currencyIn, const uint160& accountIn, const uint160& currencyOut, const uint160& accountOut) { diff --git a/src/LedgerNode.cpp b/src/LedgerNode.cpp index 9ae466834e..d059b9c3e7 100644 --- a/src/LedgerNode.cpp +++ b/src/LedgerNode.cpp @@ -6,7 +6,7 @@ #include "utils.h" #include "Log.h" -LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SerializedLedgerEntry::pointer entry) +LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry) { ScopedLock l(mAccountStateMap->Lock()); bool create = false; @@ -43,7 +43,7 @@ LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SerializedLedgerEntry return lepOKAY; } -SerializedLedgerEntry::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, +SLE::pointer Ledger::getASNode(LedgerStateParms& parms, const uint256& nodeID, LedgerEntryType let ) { SHAMapItem::pointer account = mAccountStateMap->peekItem(nodeID); @@ -53,23 +53,23 @@ SerializedLedgerEntry::pointer Ledger::getASNode(LedgerStateParms& parms, const if ( (parms & lepCREATE) == 0 ) { parms = lepMISSING; - return SerializedLedgerEntry::pointer(); + return SLE::pointer(); } parms = parms | lepCREATED | lepOKAY; - SerializedLedgerEntry::pointer sle=boost::make_shared(let); + SLE::pointer sle=boost::make_shared(let); sle->setIndex(nodeID); return sle; } - SerializedLedgerEntry::pointer sle = - boost::make_shared(account->peekSerializer(), nodeID); + SLE::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(); + return SLE::pointer(); } parms = parms | lepOKAY; @@ -78,56 +78,45 @@ SerializedLedgerEntry::pointer Ledger::getASNode(LedgerStateParms& parms, const } -SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const uint160& accountID) +SLE::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const uint160& accountID) { uint256 nodeID=getAccountRootIndex(accountID); return getASNode(parms, nodeID, ltACCOUNT_ROOT); } -SerializedLedgerEntry::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID) +SLE::pointer Ledger::getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID) { return getAccountRoot(parms, naAccountID.getAccountID()); } -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()); - - return getASNode(parms, nickHash, ltNICKNAME); -} - // // Generator Map // -SerializedLedgerEntry::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID) +SLE::pointer Ledger::getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID) { - uint256 nodeID=getGeneratorIndex(uGeneratorID); - ScopedLock l(mAccountStateMap->Lock()); - try - { - return getASNode(parms, nodeID, ltGENERATOR_MAP); - } - catch (...) - { - parms = lepERROR; - return SerializedLedgerEntry::pointer(); - } + return getASNode(parms, getGeneratorIndex(uGeneratorID), ltGENERATOR_MAP); +} + +// +// Nickname +// + +SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickname) +{ + ScopedLock l(mAccountStateMap->Lock()); + + return getASNode(parms, uNickname, ltNICKNAME); } // // Ripple State // -SerializedLedgerEntry::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode) +SLE::pointer Ledger::getRippleState(LedgerStateParms& parms, const uint256& uNode) { ScopedLock l(mAccountStateMap->Lock()); @@ -152,14 +141,14 @@ uint256 Ledger::getDirIndex(const uint256& uBase, const uint64 uNodeDir) return uNode; } -SerializedLedgerEntry::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex) +SLE::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex) { ScopedLock l(mAccountStateMap->Lock()); return getASNode(parms, uRootIndex, ltDIR_ROOT); } -SerializedLedgerEntry::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) +SLE::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex) { ScopedLock l(mAccountStateMap->Lock()); diff --git a/src/RippleState.h b/src/RippleState.h index 0f0281a28d..8efbae945f 100644 --- a/src/RippleState.h +++ b/src/RippleState.h @@ -3,6 +3,7 @@ // // A ripple line's state. +// - Isolate ledger entry format. // #include "SerializedLedger.h" From f6e32912bb05774fb44893fa71a39caf08bc5c6c Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:06:20 -0700 Subject: [PATCH 06/17] Implement transaction creation for nickname_set. --- src/Transaction.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/Transaction.h | 17 +++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 72930ef294..c2ac06c86f 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -259,6 +259,44 @@ Transaction::pointer Transaction::sharedCreditSet( return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uAcceptRate); } +// +// NicknameSet +// + +Transaction::pointer Transaction::setNicknameSet( + const NewcoinAddress& naPrivateKey, + const uint256& uNickname, + bool bSetOffer, + const STAmount& saMinimumOffer) +{ + mTransaction->setITFieldH256(sfNickname, uNickname); + + // XXX Make sure field is present even for 0! + if (bSetOffer) + mTransaction->setITFieldAmount(sfMinimumOffer, saMinimumOffer); + + sign(naPrivateKey); + + return shared_from_this(); +} + +// --> bSetOffer: true, change offer +// --> saMinimumOffer: 0 to remove. +Transaction::pointer Transaction::sharedNicknameSet( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + const STAmount& saFee, + uint32 uSourceTag, + const uint256& uNickname, + bool bSetOffer, + const STAmount& saMinimumOffer) +{ + pointer tResult = boost::make_shared(ttNICKNAME_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); + + return tResult->setNicknameSet(naPrivateKey, uNickname, bSetOffer, saMinimumOffer); +} + // // PasswordFund // diff --git a/src/Transaction.h b/src/Transaction.h index 90cb1b934d..bd1c1136ea 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -71,6 +71,12 @@ private: const STAmount& saLimitAmount, uint32 uAcceptRate); + Transaction::pointer setNicknameSet( + const NewcoinAddress& naPrivateKey, + const uint256& uNickname, + bool bSetOffer, + const STAmount& saMinimumOffer); + Transaction::pointer setPasswordFund( const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID); @@ -157,6 +163,17 @@ public: const STAmount& saLimitAmount, uint32 uAcceptRate); + // Set Nickname + static Transaction::pointer sharedNicknameSet( + const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, + const NewcoinAddress& naSourceAccount, + uint32 uSeq, + const STAmount& saFee, + uint32 uSourceTag, + const uint256& uNickname, + bool bSetOffer, + const STAmount& saMinimumOffer); + // Pre-fund password change. static Transaction::pointer sharedPasswordFund( const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, From 3945749b6405e3c69b15dcac4de98369eb6bcd69 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:06:46 -0700 Subject: [PATCH 07/17] Implement NetworkOPs stubs for nickname_set. --- src/NetworkOPs.cpp | 9 +++++++++ src/NetworkOPs.h | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 33838890bd..ef517b5d33 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -210,6 +210,15 @@ STVector256 NetworkOPs::getDirNode(const uint256& uLedger, const uint256& uDirLi return svIndexes; } +// +// Nickname functions +// + +NicknameState::pointer NetworkOPs::getNicknameState(const uint256& uLedger, const std::string& strNickname) +{ + return mLedgerMaster->getLedgerByHash(uLedger)->getNicknameState(strNickname); +} + // // Ripple functions // diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index be1feb1c7c..f7fd4c121b 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -4,6 +4,7 @@ #include "LedgerMaster.h" #include "AccountState.h" #include "RippleState.h" +#include "NicknameState.h" // #include @@ -82,6 +83,12 @@ public: uint256& uDirNodeFirst, uint256& uDirNodeLast); STVector256 getDirNode(const uint256& uLedger, const uint256& uDirLineNode); + // + // Nickname functions + // + + NicknameState::pointer getNicknameState(const uint256& uLedger, const std::string& strNickname); + // // Ripple functions // From ba983ccec3e2de05f7568e87929085d56e7613ea Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 13:07:17 -0700 Subject: [PATCH 08/17] Implement RPC commands nickname_info and nickname_set. --- src/RPCServer.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++++ src/RPCServer.h | 2 ++ src/main.cpp | 2 ++ 3 files changed, 79 insertions(+) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 1460767f1b..56194b20dd 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -22,6 +22,7 @@ #include "Conversion.h" #include "NewcoinAddress.h" #include "AccountState.h" +#include "NicknameState.h" #include "utils.h" #define VALIDATORS_FETCH_SECONDS 30 @@ -826,6 +827,78 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) } } +// nickname_info +Json::Value RPCServer::doNicknameInfo(Json::Value& params) +{ + uint256 uLedger; + + if (params.size() != 1) + { + return JSONRPCError(400, "invalid params"); + } + + std::string strNickname = params[0u].asString(); + boost::trim(strNickname); + + if (strNickname.empty()) + { + return JSONRPCError(400, "invalid nickname (zero length)"); + } + else if (!mNetOps->available()) + { + return JSONRPCError(503, "network not available"); + } + else if ((uLedger = mNetOps->getCurrentLedger()).isZero()) + { + return JSONRPCError(503, "no current ledger"); + } + + NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); + if (!nsSrc) + { + return JSONRPCError(500, "nickname does not exist"); + } + + Json::Value ret(Json::objectValue); + + ret["nickname"] = strNickname; + + nsSrc->addJson(ret); + + return ret; +} + +// nickname_set [] [] +Json::Value RPCServer::doNicknameSet(Json::Value& params) +{ + uint256 uLedger; + + if (params.size() < 2 || params.size() > 3) + { + return JSONRPCError(400, "invalid params"); + } + + std::string strNickname = params[2u].asString(); + boost::trim(strNickname); + + if (strNickname.empty()) + { + return JSONRPCError(400, "invalid nickname (zero length)"); + } + else if (!mNetOps->available()) + { + return JSONRPCError(503, "network not available"); + } + else if ((uLedger = mNetOps->getCurrentLedger()).isZero()) + { + return JSONRPCError(503, "no current ledger"); + } + + NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); + + return "not implemented"; +} + // password_fund [] // YYY Make making account default to first account for seed. Json::Value RPCServer::doPasswordFund(Json::Value ¶ms) @@ -1867,6 +1940,8 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params if (command == "account_wallet_set") return doAccountWalletSet(params); if (command == "connect") return doConnect(params); if (command == "credit_set") return doCreditSet(params); + if (command == "nickname_info") return doNicknameInfo(params); + if (command == "nickname_set") return doNicknameSet(params); if (command == "password_fund") return doPasswordFund(params); if (command == "password_set") return doPasswordSet(params); if (command == "peers") return doPeers(params); diff --git a/src/RPCServer.h b/src/RPCServer.h index 0a2acc8443..a8358235c3 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -56,6 +56,8 @@ private: Json::Value doConnect(Json::Value& params); Json::Value doCreditSet(Json::Value& params); Json::Value doLedger(Json::Value& params); + Json::Value doNicknameInfo(Json::Value& params); + Json::Value doNicknameSet(Json::Value& params); Json::Value doPasswordFund(Json::Value& params); Json::Value doPasswordSet(Json::Value& params); Json::Value doPeers(Json::Value& params); diff --git a/src/main.cpp b/src/main.cpp index 3e05f8be9e..caa32cb01b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -46,6 +46,8 @@ void printHelp(const po::options_description& desc) cout << " connect []" << endl; cout << " credit_set []" << endl; cout << " ledger" << endl; + cout << " nickname_info " << endl; + cout << " nickname_set [] []" << endl; cout << " password_fund []" << endl; cout << " password_set []" << endl; cout << " peers" << endl; From 8e88b1cd8a1c50dc6f3aabed1714ab3b4dc0541d Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 14:13:00 -0700 Subject: [PATCH 09/17] Add fee configuration for creating nicknames. --- src/Config.cpp | 16 +++++++++++----- src/Config.h | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Config.cpp b/src/Config.cpp index a1e767cde1..980c9812d3 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -8,7 +8,8 @@ #include // Fees are in XNS raw. -#define DEFAULT_FEE_CREATE 1000 +#define DEFAULT_FEE_ACCOUNT_CREATE 1000 +#define DEFAULT_FEE_NICKNAME_CREATE 1000 #define DEFAULT_FEE_DEFAULT 100 #define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg @@ -24,7 +25,8 @@ #define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water" #define SECTION_NETWORK_QUORUM "network_quorum" #define SECTION_VALIDATION_QUORUM "validation_quorum" -#define SECTION_FEE_CREATE "fee_create" +#define SECTION_FEE_ACCOUNT_CREATE "fee_account_create" +#define SECTION_FEE_NICKNAME_CREATE "fee_nickname_create" #define SECTION_FEE_DEFAULT "fee_default" #define SECTION_ACCOUNT_PROBE_MAX "account_probe_max" @@ -59,7 +61,8 @@ Config::Config() NETWORK_QUORUM = 0; // Don't need to see other nodes VALIDATION_QUORUM = 1; // Only need one node to vouch - FEE_CREATE = DEFAULT_FEE_CREATE; + FEE_ACCOUNT_CREATE = DEFAULT_FEE_ACCOUNT_CREATE; + FEE_NICKNAME_CREATE = DEFAULT_FEE_NICKNAME_CREATE; FEE_DEFAULT = DEFAULT_FEE_DEFAULT; ACCOUNT_PROBE_MAX = 10; @@ -118,8 +121,11 @@ void Config::load() if (sectionSingleB(secConfig, SECTION_VALIDATION_QUORUM, strTemp)) VALIDATION_QUORUM = MAX(0, boost::lexical_cast(strTemp)); - if (sectionSingleB(secConfig, SECTION_FEE_CREATE, strTemp)) - FEE_CREATE = boost::lexical_cast(strTemp); + if (sectionSingleB(secConfig, SECTION_FEE_ACCOUNT_CREATE, strTemp)) + FEE_ACCOUNT_CREATE = boost::lexical_cast(strTemp); + + if (sectionSingleB(secConfig, SECTION_FEE_NICKNAME_CREATE, strTemp)) + FEE_NICKNAME_CREATE = boost::lexical_cast(strTemp); if (sectionSingleB(secConfig, SECTION_FEE_DEFAULT, strTemp)) FEE_DEFAULT = boost::lexical_cast(strTemp); diff --git a/src/Config.h b/src/Config.h index 51290f0bd8..e6f74a0c6d 100644 --- a/src/Config.h +++ b/src/Config.h @@ -75,8 +75,9 @@ public: std::string VALIDATION_KEY; // Fees - uint64 FEE_CREATE; // Fee to create an account - uint64 FEE_DEFAULT; // Default fee. + uint64 FEE_DEFAULT; // Default fee. + uint64 FEE_ACCOUNT_CREATE; // Fee to create an account. + uint64 FEE_NICKNAME_CREATE; // Fee to create a nickname. // Configuration parameters std::string DATA_DIR; From 1f7abd6a94fa255dad863f99a0e70eff50795f3e Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 14:13:32 -0700 Subject: [PATCH 10/17] Clean up getText for SerializedLedgerEntry. --- src/SerializedLedger.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index b991a25790..beeb69dee5 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -1,6 +1,7 @@ - #include "SerializedLedger.h" +#include + SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index) : SerializedType("LedgerEntry"), mIndex(index) { @@ -47,12 +48,10 @@ std::string SerializedLedgerEntry::getFullText() const std::string SerializedLedgerEntry::getText() const { - std::string ret = "{"; - ret += mIndex.GetHex(); - ret += mVersion.getText(); - ret += mObject.getText(); - ret += "}"; - return ret; + return str(boost::format("{ %s, %s, %s }") + % mIndex.GetHex() + % mVersion.getText() + % mObject.getText()); } Json::Value SerializedLedgerEntry::getJson(int options) const From 41c6ae939a42e59e4ef593db75c28ced9d11b248 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 14:14:03 -0700 Subject: [PATCH 11/17] Fix NicknameSet transaction handling. --- src/TransactionEngine.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index df05307b24..8748f8b336 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -364,7 +364,17 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran case ttPAYMENT: if (txn.getFlags() & tfCreateAccount) { - saCost = theConfig.FEE_CREATE; + saCost = theConfig.FEE_ACCOUNT_CREATE; + } + break; + + case ttNICKNAME_SET: + { + LedgerStateParms qry = lepNONE; + SLE::pointer sleNickname = mLedger->getNickname(qry, txn.getITFieldH256(sfNickname)); + + if (!sleNickname) + saCost = theConfig.FEE_NICKNAME_CREATE; } break; @@ -878,7 +888,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac SLE::pointer sleSrc = accounts[0].second; - uint256 uNickname = txn.getITFieldH256(sfWalletLocator); + uint256 uNickname = txn.getITFieldH256(sfNickname); bool bMinOffer = txn.getITFieldPresent(sfMinimumOffer); STAmount saMinOffer = bMinOffer ? txn.getITFieldAmount(sfAmount) : STAmount(); @@ -899,7 +909,7 @@ TransactionEngineResult TransactionEngine::doNicknameSet(const SerializedTransac sleNickname->makeIFieldAbsent(sfMinimumOffer); } - accounts.push_back(std::make_pair(taaCREATE, sleNickname)); + accounts.push_back(std::make_pair(taaMODIFY, sleNickname)); } else { From 0b02b20003a0d7f6bc9286b8ec9e6320868df810 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 14:50:42 -0700 Subject: [PATCH 12/17] Add support for a signature when creating NicknameSet transactions. --- src/Ledger.h | 2 +- src/Transaction.cpp | 11 ++++++++--- src/Transaction.h | 6 ++++-- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Ledger.h b/src/Ledger.h index d4976d6170..9d82641295 100644 --- a/src/Ledger.h +++ b/src/Ledger.h @@ -165,7 +165,7 @@ public: // Nickname functions // - uint256 getNicknameHash(const std::string& strNickname) + static uint256 getNicknameHash(const std::string& strNickname) { Serializer s(strNickname); return s.getSHA256(); } NicknameState::pointer getNicknameState(const uint256& uNickname); diff --git a/src/Transaction.cpp b/src/Transaction.cpp index c2ac06c86f..328a7aa6fc 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -267,7 +267,8 @@ Transaction::pointer Transaction::setNicknameSet( const NewcoinAddress& naPrivateKey, const uint256& uNickname, bool bSetOffer, - const STAmount& saMinimumOffer) + const STAmount& saMinimumOffer, + const std::vector& vucSignature) { mTransaction->setITFieldH256(sfNickname, uNickname); @@ -275,6 +276,9 @@ Transaction::pointer Transaction::setNicknameSet( if (bSetOffer) mTransaction->setITFieldAmount(sfMinimumOffer, saMinimumOffer); + if (!vucSignature.empty()) + mTransaction->setITFieldVL(sfSignature, vucSignature); + sign(naPrivateKey); return shared_from_this(); @@ -290,11 +294,12 @@ Transaction::pointer Transaction::sharedNicknameSet( uint32 uSourceTag, const uint256& uNickname, bool bSetOffer, - const STAmount& saMinimumOffer) + const STAmount& saMinimumOffer, + const std::vector& vucSignature) { pointer tResult = boost::make_shared(ttNICKNAME_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); - return tResult->setNicknameSet(naPrivateKey, uNickname, bSetOffer, saMinimumOffer); + return tResult->setNicknameSet(naPrivateKey, uNickname, bSetOffer, saMinimumOffer, vucSignature); } // diff --git a/src/Transaction.h b/src/Transaction.h index bd1c1136ea..2510a04e64 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -75,7 +75,8 @@ private: const NewcoinAddress& naPrivateKey, const uint256& uNickname, bool bSetOffer, - const STAmount& saMinimumOffer); + const STAmount& saMinimumOffer, + const std::vector& vucSignature); Transaction::pointer setPasswordFund( const NewcoinAddress& naPrivateKey, @@ -172,7 +173,8 @@ public: uint32 uSourceTag, const uint256& uNickname, bool bSetOffer, - const STAmount& saMinimumOffer); + const STAmount& saMinimumOffer, + const std::vector& vucSignature); // Pre-fund password change. static Transaction::pointer sharedPasswordFund( From 1159e71c2639304b7e94c898b5c85c294f7f3d31 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Tue, 5 Jun 2012 14:52:37 -0700 Subject: [PATCH 13/17] Implement RPC commands nickname_info and nickname_set. --- src/NicknameState.cpp | 29 +++++++++++++ src/NicknameState.h | 37 +++++++++++++++++ src/RPCServer.cpp | 94 ++++++++++++++++++++++++++++++++++++------- src/RPCServer.h | 2 +- 4 files changed, 147 insertions(+), 15 deletions(-) create mode 100644 src/NicknameState.cpp create mode 100644 src/NicknameState.h diff --git a/src/NicknameState.cpp b/src/NicknameState.cpp new file mode 100644 index 0000000000..9b2cb3e857 --- /dev/null +++ b/src/NicknameState.cpp @@ -0,0 +1,29 @@ +#include "NicknameState.h" + +NicknameState::NicknameState(SerializedLedgerEntry::pointer ledgerEntry) : + mLedgerEntry(ledgerEntry) +{ + if (!mLedgerEntry || mLedgerEntry->getType() != ltNICKNAME) return; +} + +bool NicknameState::haveMinimumOffer() const +{ + return mLedgerEntry->getIFieldPresent(sfMinimumOffer); +} + +STAmount NicknameState::getMinimumOffer() const +{ + return mLedgerEntry->getIFieldPresent(sfMinimumOffer) + ? mLedgerEntry->getIValueFieldAmount(sfMinimumOffer) + : STAmount(); +} + +NewcoinAddress NicknameState::getAccountID() const +{ + return mLedgerEntry->getIValueFieldAccount(sfAccount); +} + +void NicknameState::addJson(Json::Value& val) +{ + val = mLedgerEntry->getJson(0); +} diff --git a/src/NicknameState.h b/src/NicknameState.h new file mode 100644 index 0000000000..fe116f4c5d --- /dev/null +++ b/src/NicknameState.h @@ -0,0 +1,37 @@ +#ifndef _NICKNAMESTATE_ +#define _NICKNAMESTATE_ + +// +// State of a nickname node. +// - Isolate ledger entry format. +// + +#include "SerializedLedger.h" + +#include + +class NicknameState +{ +public: + typedef boost::shared_ptr pointer; + +private: + SerializedLedgerEntry::pointer mLedgerEntry; + +public: + NicknameState(SerializedLedgerEntry::pointer ledgerEntry); // For accounts in a ledger + + bool haveMinimumOffer() const; + STAmount getMinimumOffer() const; + NewcoinAddress getAccountID() const; + + SerializedLedgerEntry::pointer getSLE() { return mLedgerEntry; } + const SerializedLedgerEntry& peekSLE() const { return *mLedgerEntry; } + SerializedLedgerEntry& peekSLE() { return *mLedgerEntry; } + + std::vector getRaw() const; + void addJson(Json::Value& value); +}; + +#endif +// vim:ts=4 diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 32faabb991..088c8f5c52 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -216,7 +216,7 @@ Json::Value RPCServer::getMasterGenerator(const uint256& uLedger, const NewcoinA Json::Value RPCServer::authorize(const uint256& uLedger, const NewcoinAddress& naRegularSeed, const NewcoinAddress& naSrcAccountID, NewcoinAddress& naAccountPublic, NewcoinAddress& naAccountPrivate, - STAmount& saSrcBalance, uint64 uFee, AccountState::pointer& asSrc, + STAmount& saSrcBalance, const STAmount& saFee, AccountState::pointer& asSrc, const NewcoinAddress& naVerifyGenerator) { // Source/paying account must exist. @@ -277,13 +277,13 @@ Json::Value RPCServer::authorize(const uint256& uLedger, saSrcBalance = asSrc->getBalance(); - if (saSrcBalance < uFee) + if (saSrcBalance < saFee) { return JSONRPCError(500, "insufficent funds"); } else { - saSrcBalance -= uFee; + saSrcBalance -= saFee; } return obj; @@ -780,7 +780,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) } else if (!saLimitAmount.setValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : "")) { - return JSONRPCError(500, "bad src amount/currency"); + return JSONRPCError(400, "bad src amount/currency"); } else if (!mNetOps->available()) { @@ -828,6 +828,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) } // nickname_info +// Note: Nicknames are not automatically looked up by commands as they are advisory and can be changed. Json::Value RPCServer::doNicknameInfo(Json::Value& params) { uint256 uLedger; @@ -871,20 +872,38 @@ Json::Value RPCServer::doNicknameInfo(Json::Value& params) // nickname_set [] [] Json::Value RPCServer::doNicknameSet(Json::Value& params) { + NewcoinAddress naSrcAccountID; + NewcoinAddress naSeed; uint256 uLedger; if (params.size() < 2 || params.size() > 3) { return JSONRPCError(400, "invalid params"); } + else if (!naSeed.setFamilySeedGeneric(params[0u].asString())) + { + return "disallowed seed"; + } + else if (!naSrcAccountID.setAccountID(params[1u].asString())) + { + return "bad source account id needed"; + } - std::string strNickname = params[2u].asString(); - boost::trim(strNickname); + STAmount saMinimumOffer; + bool bSetOffer = params.size() >= 4; + std::string strOfferCurrency; + std::string strNickname = params[2u].asString(); + boost::trim(strNickname); + std::vector vucSignature; if (strNickname.empty()) { return JSONRPCError(400, "invalid nickname (zero length)"); } + else if (params.size() >= 4 && !saMinimumOffer.setValue(params[3u].asString(), strOfferCurrency)) + { + return JSONRPCError(400, "bad dst amount/currency"); + } else if (!mNetOps->available()) { return JSONRPCError(503, "network not available"); @@ -894,9 +913,56 @@ Json::Value RPCServer::doNicknameSet(Json::Value& params) return JSONRPCError(503, "no current ledger"); } + STAmount saFee; NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); - return "not implemented"; + if (!nsSrc) + { + // Creating nickname. + saFee = theConfig.FEE_NICKNAME_CREATE; + } + else if (naSrcAccountID != nsSrc->getAccountID()) + { + // We don't own the nickname. + return JSONRPCError(400, "account does not control nickname"); + } + else + { + // Setting the minimum offer. + saFee = theConfig.FEE_DEFAULT; + } + + NewcoinAddress naMasterGenerator; + NewcoinAddress naAccountPublic; + NewcoinAddress naAccountPrivate; + AccountState::pointer asSrc; + STAmount saSrcBalance; + Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, + saSrcBalance, saFee, asSrc, naMasterGenerator); + + if (!obj.empty()) + return obj; + + // YYY Could verify nickname does not exist or points to paying account. + // XXX Adjust fee for nickname create. + + Transaction::pointer trans = Transaction::sharedNicknameSet( + naAccountPublic, naAccountPrivate, + naSrcAccountID, + asSrc->getSeq(), + saFee, + 0, // YYY No source tag + Ledger::getNicknameHash(strNickname), + bSetOffer, + saMinimumOffer, + vucSignature); + + (void) mNetOps->processTransaction(trans); + + obj["transaction"] = trans->getSTransaction()->getJson(0); + obj["status"] = trans->getStatus(); + + return obj; } // password_fund [] @@ -1106,11 +1172,11 @@ Json::Value RPCServer::doSend(Json::Value& params) } else if (!saDstAmount.setValue(params[3u].asString(), sDstCurrency)) { - return JSONRPCError(500, "bad dst amount/currency"); + return JSONRPCError(400, "bad dst amount/currency"); } else if (params.size() >= 6 && !saSrcAmount.setValue(params[5u].asString(), sSrcCurrency)) { - return JSONRPCError(500, "bad src amount/currency"); + return JSONRPCError(400, "bad src amount/currency"); } else if (!mNetOps->available()) { @@ -1474,7 +1540,7 @@ Json::Value RPCServer::doWalletAdd(Json::Value& params) } else if (params.size() >= 4 && !saAmount.setValue(params[3u].asString(), sDstCurrency)) { - return JSONRPCError(500, "bad dst amount/currency"); + return JSONRPCError(400, "bad dst amount/currency"); } else if (!mNetOps->available()) { @@ -1497,7 +1563,7 @@ Json::Value RPCServer::doWalletAdd(Json::Value& params) AccountState::pointer asSrc; STAmount saSrcBalance; Json::Value obj = authorize(uLedger, naRegularSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, - saSrcBalance, theConfig.FEE_CREATE, asSrc, naMasterGenerator); + saSrcBalance, theConfig.FEE_ACCOUNT_CREATE, asSrc, naMasterGenerator); if (!obj.empty()) return obj; @@ -1544,7 +1610,7 @@ Json::Value RPCServer::doWalletAdd(Json::Value& params) naAccountPublic, naAccountPrivate, naSrcAccountID, asSrc->getSeq(), - theConfig.FEE_CREATE, + theConfig.FEE_ACCOUNT_CREATE, 0, // YYY No source tag saAmount, naAuthKeyID, @@ -1705,7 +1771,7 @@ Json::Value RPCServer::doWalletCreate(Json::Value& params) AccountState::pointer asSrc; STAmount saSrcBalance; Json::Value obj = authorize(uLedger, naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, - saSrcBalance, theConfig.FEE_CREATE, asSrc, naMasterGenerator); + saSrcBalance, theConfig.FEE_ACCOUNT_CREATE, asSrc, naMasterGenerator); if (!obj.empty()) return obj; @@ -1719,7 +1785,7 @@ Json::Value RPCServer::doWalletCreate(Json::Value& params) naAccountPublic, naAccountPrivate, naSrcAccountID, asSrc->getSeq(), - theConfig.FEE_CREATE, + theConfig.FEE_ACCOUNT_CREATE, 0, // YYY No source tag naDstAccountID, saInitialFunds); // Initial funds in XNC. diff --git a/src/RPCServer.h b/src/RPCServer.h index a8358235c3..a972b05a6e 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -42,7 +42,7 @@ private: Json::Value getMasterGenerator(const uint256& uLedger, const NewcoinAddress& naRegularSeed, NewcoinAddress& naMasterGenerator); Json::Value authorize(const uint256& uLedger, const NewcoinAddress& naRegularSeed, const NewcoinAddress& naSrcAccountID, NewcoinAddress& naAccountPublic, NewcoinAddress& naAccountPrivate, - STAmount& saSrcBalance, uint64 uFee, AccountState::pointer& asSrc, + STAmount& saSrcBalance, const STAmount& saFee, AccountState::pointer& asSrc, const NewcoinAddress& naVerifyGenerator); Json::Value accounts(const uint256& uLedger, const NewcoinAddress& naMasterGenerator); From b4e238a2e451d73c0f76a1b24075b4634f28c8cf Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Jun 2012 15:41:44 -0700 Subject: [PATCH 14/17] With luck, a fix for the crash. --- src/LedgerConsensus.cpp | 10 ++++------ src/LedgerConsensus.h | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index dd787bafb2..0c14e9bdc4 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -584,12 +584,11 @@ void LedgerConsensus::Saccept(boost::shared_ptr This, SHAMap::p } void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer ledger, - std::deque& failedTransactions) + std::list& failedTransactions) { TransactionEngine engine(ledger); - SHAMapItem::pointer item = set->peekFirstItem(); - while (item) + for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag())) { Log(lsINFO) << "Processing candidate transaction: " << item->getTag().GetHex(); #ifndef TRUST_NETWORK @@ -622,14 +621,13 @@ void LedgerConsensus::applyTransactions(SHAMap::pointer set, Ledger::pointer led Log(lsWARNING) << " Throws"; } #endif - item = set->peekNextItem(item->getTag()); } int successes; do { successes = 0; - std::deque::iterator it = failedTransactions.begin(); + std::list::iterator it = failedTransactions.begin(); while (it != failedTransactions.end()) { try @@ -674,7 +672,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) } #endif - std::deque failedTransactions; + std::list failedTransactions; applyTransactions(set, newLCL, failedTransactions); newLCL->setClosed(); newLCL->setAccepted(); diff --git a/src/LedgerConsensus.h b/src/LedgerConsensus.h index 3a6aeaecde..ea77f87aff 100644 --- a/src/LedgerConsensus.h +++ b/src/LedgerConsensus.h @@ -2,7 +2,6 @@ #define __LEDGER_CONSENSUS__ #include -#include #include #include @@ -114,7 +113,7 @@ protected: void removePosition(LedgerProposal&, bool ours); void sendHaveTxSet(const std::vector& txSetHashes); void applyTransactions(SHAMap::pointer transactionSet, Ledger::pointer targetLedger, - std::deque& failedTransactions); + std::list& failedTransactions); // manipulating our own position void takeInitialPosition(Ledger::pointer initialLedger); From 7d153490ab7e0f2e5cd1a069594779e1467616e0 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Tue, 5 Jun 2012 15:54:52 -0700 Subject: [PATCH 15/17] Bugfixes. --- src/LedgerAcquire.cpp | 1 - src/Peer.cpp | 8 ++++++-- src/TransactionEngine.h | 2 +- src/newcoin.proto | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/LedgerAcquire.cpp b/src/LedgerAcquire.cpp index 1a71d79bc1..eb3769edad 100644 --- a/src/LedgerAcquire.cpp +++ b/src/LedgerAcquire.cpp @@ -403,7 +403,6 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::poi { if (packet.nodes_size() != 1) return false; const newcoin::TMLedgerNode& node = packet.nodes(0); - if (!node.has_nodedata()) return false; return ledger->takeBase(node.nodedata(), peer); } else if ((packet.type() == newcoin::liTX_NODE) || (packet.type() == newcoin::liAS_NODE)) diff --git a/src/Peer.cpp b/src/Peer.cpp index 893db52ab0..87b6dc8176 100644 --- a/src/Peer.cpp +++ b/src/Peer.cpp @@ -800,6 +800,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) if(packet.itype() == newcoin::liBASE) { // they want the ledger base data + Log(lsTRACE) << "Want ledger base data"; Serializer nData(128); ledger->addRaw(nData); reply.add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength()); @@ -834,6 +835,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) { std::vector::iterator nodeIDIterator; std::list< std::vector >::iterator rawNodeIterator; + int count = 0; for(nodeIDIterator = nodeIDs.begin(), rawNodeIterator = rawNodes.begin(); nodeIDIterator != nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator) { @@ -842,7 +844,9 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet) newcoin::TMLedgerNode* node = reply.add_nodes(); node->set_nodeid(nID.getDataPtr(), nID.getLength()); node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size()); + ++count; } + Log(lsTRACE) << "GetNodeFat: sending " << count << " nodes"; } } PackedMessage::pointer oPacket = boost::make_shared(reply, newcoin::mtLEDGER_DATA); @@ -875,12 +879,12 @@ void Peer::recvLedger(newcoin::TMLedgerData& packet) for (int i = 0; i < packet.nodes().size(); ++i) { const newcoin::TMLedgerNode& node = packet.nodes(i); - if (!node.has_nodeid() || !node.has_nodedata()) + if (!node.has_nodeid() || !node.has_nodedata() || (node.nodeid().size() != 33)) { + Log(lsWARNING) << "LedgerData request with invalid node ID"; punishPeer(PP_INVALID_REQUEST); return; } - nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size())); nodeData.push_back(std::vector(node.nodedata().begin(), node.nodedata().end())); } diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index 7e34e53c2f..597084b59f 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -127,7 +127,7 @@ public: Ledger::pointer getDefaultLedger() { return mDefaultLedger; } void setDefaultLedger(Ledger::pointer ledger) { mDefaultLedger = ledger; } Ledger::pointer getAlternateLedger() { return mAlternateLedger; } - void setAlternateLedger(Ledger::pointer ledger) { mDefaultLedger = ledger; } + void setAlternateLedger(Ledger::pointer ledger) { mAlternateLedger = ledger; } void setLedger(Ledger::pointer ledger) { mDefaultLedger = ledger; mAlternateLedger = Ledger::pointer(); } diff --git a/src/newcoin.proto b/src/newcoin.proto index 5355f52a11..5e3a0c4bc7 100644 --- a/src/newcoin.proto +++ b/src/newcoin.proto @@ -203,8 +203,8 @@ message TMObjectByHash } message TMLedgerNode { - required bytes nodeid = 1; - required bytes nodedata = 2; + required bytes nodedata = 1; + optional bytes nodeid = 2; // missing for ledger base data } enum TMLedgerInfoType { From e204a7dc3d9aabe16921c84c53c84dc2cde8957e Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 6 Jun 2012 01:25:00 -0700 Subject: [PATCH 16/17] Add const restrictions. --- src/Application.h | 2 +- src/DBInit.cpp | 7 +++++-- src/ParseSection.cpp | 8 ++++---- src/ParseSection.h | 8 ++++---- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Application.h b/src/Application.h index 55d405c66d..2c1fd6c006 100644 --- a/src/Application.h +++ b/src/Application.h @@ -79,7 +79,7 @@ public: DatabaseCon* getLedgerDB() { return mLedgerDB; } DatabaseCon* getWalletDB() { return mWalletDB; } DatabaseCon* getHashNodeDB() { return mHashNodeDB; } - DatabaseCon* getNetNodeDB() { return mNetNodeDB; } + DatabaseCon* getNetNodeDB() { return mNetNodeDB; } uint256 getNonce256() { return mNonce256; } std::size_t getNonceST() { return mNonceST; } diff --git a/src/DBInit.cpp b/src/DBInit.cpp index e043dca389..ba9d954503 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -68,6 +68,8 @@ const char *WalletDBInit[] = { FetchUpdated DATETIME \ );", + // Scoring and other information for domains. + // // Domain: // Domain source for https. // PublicKey: @@ -104,7 +106,7 @@ const char *WalletDBInit[] = { "CREATE INDEX SeedDomainNext ON SeedDomains (Next);", // Table of PublicKeys user has asked to trust. - // Fetches are made to the CAS. + // Fetches are made to the CAS. This gets the newcoin.txt so even validators without a web server can publish a newcoin.txt. // Next: // Time of next fetch attempt. // Scan: @@ -127,7 +129,8 @@ const char *WalletDBInit[] = { // Allow us to easily find the next SeedNode to fetch. "CREATE INDEX SeedNodeNext ON SeedNodes (Next);", - // Table of trusted nodes. + // Nodes we trust not grossly consipire. Derived from SeedDomains, SeedNodes, and ValidatorReferrals. + // // Score: // Computed trust score. Higher is better. // Seen: diff --git a/src/ParseSection.cpp b/src/ParseSection.cpp index 04da0eeb43..e0fe2425db 100644 --- a/src/ParseSection.cpp +++ b/src/ParseSection.cpp @@ -6,7 +6,7 @@ #define SECTION_DEFAULT_NAME "" -section ParseSection(const std::string strInput, const bool bTrim) +section ParseSection(const std::string& strInput, const bool bTrim) { std::string strData(strInput); std::vector vLines; @@ -66,7 +66,7 @@ void PrintSection(section secInput) std::cerr << "PrintSection<" << std::endl; } -section::mapped_type* sectionEntries(section& secSource, const std::string strSection) +section::mapped_type* sectionEntries(section& secSource, const std::string& strSection) { section::iterator it; section::mapped_type* smtResult; @@ -86,14 +86,14 @@ section::mapped_type* sectionEntries(section& secSource, const std::string strSe return smtResult; } -int sectionCount(section& secSource, std::string strSection) +int sectionCount(section& secSource, const std::string& strSection) { section::mapped_type* pmtEntries = sectionEntries(secSource, strSection); return pmtEntries ? -1 : pmtEntries->size(); } -bool sectionSingleB(section& secSource, const std::string strSection, std::string& strValue) +bool sectionSingleB(section& secSource, const std::string& strSection, std::string& strValue) { section::mapped_type* pmtEntries = sectionEntries(secSource, strSection); bool bSingle = pmtEntries && 1 == pmtEntries->size(); diff --git a/src/ParseSection.h b/src/ParseSection.h index 027f29f261..76095416a3 100644 --- a/src/ParseSection.h +++ b/src/ParseSection.h @@ -7,10 +7,10 @@ typedef std::map > section; -section ParseSection(const std::string strInput, const bool bTrim); +section ParseSection(const std::string& strInput, const bool bTrim); void PrintSection(section secInput); -bool sectionSingleB(section& secSource, const std::string strSection, std::string& strValue); -int sectionCount(section& secSource, std::string strSection); -section::mapped_type* sectionEntries(section& secSource, const std::string strSection); +bool sectionSingleB(section& secSource, const std::string& strSection, std::string& strValue); +int sectionCount(section& secSource, const std::string& strSection); +section::mapped_type* sectionEntries(section& secSource, const std::string& strSection); #endif From 232f7f2dbb44ea20d9b570a68c6847de6989fb21 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Wed, 6 Jun 2012 01:33:04 -0700 Subject: [PATCH 17/17] Add nodeInUNL() for validaiton. --- src/RPCServer.cpp | 2 +- src/UniqueNodeList.cpp | 131 +++++++++++++++++++++++++++++++++-------- src/UniqueNodeList.h | 20 +++++-- 3 files changed, 122 insertions(+), 31 deletions(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 17c4423cf0..624bb67198 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1355,7 +1355,7 @@ Json::Value RPCServer::doLedger(Json::Value& params) return "not implemented"; } -// unl_add [] +// unl_add | [] Json::Value RPCServer::doUnlAdd(Json::Value& params) { if (params.size() == 1 || params.size() == 2) diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 45fab4b5d1..79c09b14bf 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -40,6 +40,8 @@ UniqueNodeList::UniqueNodeList(boost::asio::io_service& io_service) : { } +// This is called when the application is started. +// Get update times and start fetching and scoring as needed. void UniqueNodeList::start() { miscLoad(); @@ -51,6 +53,7 @@ void UniqueNodeList::start() scoreNext(false); // Start scoring. } +// Load information about when we last updated. bool UniqueNodeList::miscLoad() { ScopedLock sl(theApp->getWalletDB()->getDBLock()); @@ -65,9 +68,12 @@ bool UniqueNodeList::miscLoad() db->endIterRows(); + trustedLoad(); + return true; } +// Persist update information. bool UniqueNodeList::miscSave() { Database* db=theApp->getWalletDB()->getDB(); @@ -80,6 +86,25 @@ bool UniqueNodeList::miscSave() return true; } +void UniqueNodeList::trustedLoad() +{ + Database* db=theApp->getWalletDB()->getDB(); + ScopedLock sl(theApp->getWalletDB()->getDBLock()); + ScopedLock slUNL(mUNLLock); + + mUNL.clear(); + + SQL_FOREACH(db, "SELECT PublicKey FROM TrustedNodes WHERE Score != 0;") + { + std::string strPublicKey; + + db->getStr("PublicKey", strPublicKey); + + mUNL.insert(strPublicKey); + } +} + +// For a round of scoring we destribute points from a node to nodes it refers to. // Returns true, iff scores were distributed. bool UniqueNodeList::scoreRound(std::vector& vsnNodes) { @@ -143,6 +168,7 @@ bool UniqueNodeList::scoreRound(std::vector& vsnNodes) return bDist; } +// From SeedDomains and ValidatorReferrals compute scores and update TrustedNodes. void UniqueNodeList::scoreCompute() { strIndex umPulicIdx; // Map of public key to index. @@ -271,6 +297,9 @@ void UniqueNodeList::scoreCompute() } } + // + // Distribute the points from the seeds. + // bool bDist = true; for (int i = SCORE_ROUNDS; bDist && i--;) @@ -289,6 +318,7 @@ void UniqueNodeList::scoreCompute() << std::endl; } + // Persist validator scores. ScopedLock sl(theApp->getWalletDB()->getDBLock()); db->executeSQL("BEGIN;"); @@ -317,9 +347,11 @@ void UniqueNodeList::scoreCompute() } } + boost::unordered_set usUNL; + if (vsnNodes.size()) { - // Update old entries and add new ones. + // Update the score old entries and add new entries as needed. std::vector vstrValues; vstrValues.resize(vsnNodes.size()); @@ -333,12 +365,20 @@ void UniqueNodeList::scoreCompute() % db->escape(sn.strValidator) % sn.iScore % strSeen); + + usUNL.insert(sn.strValidator); } db->executeSQL(str(boost::format("REPLACE INTO TrustedNodes (PublicKey,Score,Seen) VALUES %s;") % strJoin(vstrValues.begin(), vstrValues.end(), ","))); } + { + ScopedLock sl(mUNLLock); + + mUNL.swap(usUNL); + } + // Score IPs. db->executeSQL("UPDATE PeerIps SET Score = 0 WHERE Score != 0;"); @@ -507,7 +547,10 @@ void UniqueNodeList::fetchDirty() scoreNext(false); } -void UniqueNodeList::processIps(const std::string& strSite, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrIps) +// Persist the IPs refered to by a Validator. +// --> strSite: source of the IPs (for debugging) +// --> naNodePublic: public key of the validating node. +void UniqueNodeList::processIps(const std::string& strSite, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrIps) { Database* db=theApp->getWalletDB()->getDB(); @@ -590,7 +633,8 @@ void UniqueNodeList::processIps(const std::string& strSite, NewcoinAddress naNod fetchDirty(); } -void UniqueNodeList::processValidators(const std::string& strSite, const std::string& strValidatorsSrc, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrValidators) +// Persist ValidatorReferrals. +void UniqueNodeList::processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrValidators) { Database* db=theApp->getWalletDB()->getDB(); @@ -651,7 +695,8 @@ void UniqueNodeList::processValidators(const std::string& strSite, const std::st fetchDirty(); } -void UniqueNodeList::responseIps(const std::string& strSite, NewcoinAddress naNodePublic, const boost::system::error_code& err, const std::string strIpsFile) +// Given a section with IPs, parse and persist it for a validator. +void UniqueNodeList::responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string strIpsFile) { if (!err) { @@ -663,9 +708,8 @@ void UniqueNodeList::responseIps(const std::string& strSite, NewcoinAddress naNo fetchFinish(); } -// -// Process [ips_url] -// +// Process section [ips_url]. +// If we have a section with a single entry, fetch the url and process it. void UniqueNodeList::getIpsUrl(NewcoinAddress naNodePublic, section secSite) { std::string strIpsUrl; @@ -691,6 +735,7 @@ void UniqueNodeList::getIpsUrl(NewcoinAddress naNodePublic, section secSite) } } +// Given a section with validators, parse and persist it. void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, NewcoinAddress naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile) { if (!err) @@ -703,9 +748,7 @@ void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, New getIpsUrl(naNodePublic, secSite); } -// -// Process [validators_url] -// +// Process section [validators_url]. void UniqueNodeList::getValidatorsUrl(NewcoinAddress naNodePublic, section secSite) { std::string strValidatorsUrl; @@ -758,6 +801,7 @@ void UniqueNodeList::processFile(const std::string strDomain, NewcoinAddress naN getValidatorsUrl(naNodePublic, secSite); } +// Given a newcoin.txt, process it. void UniqueNodeList::responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile) { section secSite = ParseSection(strSiteFile, true); @@ -838,7 +882,7 @@ void UniqueNodeList::responseFetch(const std::string strDomain, const boost::sys seedDomain sdCurrent; - bool bFound = getSeedDomains(strDomain, sdCurrent); + bool bFound = getSeedDomains(strDomain, sdCurrent); assert(bFound); @@ -910,7 +954,7 @@ void UniqueNodeList::fetchTimerHandler(const boost::system::error_code& err) } } -// Try to process the next fetch. +// Try to process the next fetch of a newcoin.txt. void UniqueNodeList::fetchNext() { bool bFull; @@ -999,6 +1043,7 @@ void UniqueNodeList::fetchNext() } } +// For each kind of source, have a starting number of points to be distributed. int UniqueNodeList::iSourceScore(validatorSource vsWhy) { int iScore = 0; @@ -1056,6 +1101,7 @@ void UniqueNodeList::nodeAddDomain(const std::string& strDomain, validatorSource setSeedDomains(sdCurrent, true); } +// Retrieve a SeedDomain for DB. bool UniqueNodeList::getSeedDomains(const std::string& strDomain, seedDomain& dstSeedDomain) { bool bResult; @@ -1111,6 +1157,7 @@ bool UniqueNodeList::getSeedDomains(const std::string& strDomain, seedDomain& ds return bResult; } +// Persist a SeedDomain. void UniqueNodeList::setSeedDomains(const seedDomain& sdSource, bool bNext) { Database* db=theApp->getWalletDB()->getDB(); @@ -1147,34 +1194,60 @@ void UniqueNodeList::setSeedDomains(const seedDomain& sdSource, bool bNext) } } +// Add a trusted node. Called by RPC or other source. // XXX allow update of comment. -void UniqueNodeList::nodeAddPublic(NewcoinAddress naNodePublic, std::string strComment) +// XXX Broken should opperate on seeds. +void UniqueNodeList::nodeAddPublic(const NewcoinAddress& naNodePublic, const std::string& strComment) { std::string strPublicKey = naNodePublic.humanNodePublic(); - Database* db=theApp->getWalletDB()->getDB(); - ScopedLock sl(theApp->getWalletDB()->getDBLock()); + { + Database* db=theApp->getWalletDB()->getDB(); + ScopedLock sl(theApp->getWalletDB()->getDBLock()); - db->executeSQL(str(boost::format("INSERT INTO TrustedNodes (PublicKey,Comment) values (%s,%s);") - % db->escape(strPublicKey) % db->escape(strComment))); + db->executeSQL(str(boost::format("INSERT INTO TrustedNodes (PublicKey,Comment) values (%s,%s);") + % db->escape(strPublicKey) % db->escape(strComment))); + } + + { + ScopedLock slUNL(mUNLLock); + + mUNL.insert(strPublicKey); + } } +// XXX Broken should opperate on seeds. void UniqueNodeList::nodeRemove(NewcoinAddress naNodePublic) { - std::string strPublic = naNodePublic.humanNodePublic(); + std::string strPublicKey = naNodePublic.humanNodePublic(); - Database* db=theApp->getWalletDB()->getDB(); - ScopedLock sl(theApp->getWalletDB()->getDBLock()); + { + Database* db=theApp->getWalletDB()->getDB(); + ScopedLock sl(theApp->getWalletDB()->getDBLock()); - db->executeSQL(str(boost::format("DELETE FROM TrustedNodes where PublicKey=%s") % db->escape(strPublic))); + db->executeSQL(str(boost::format("DELETE FROM TrustedNodes where PublicKey=%s") % db->escape(strPublicKey))); + } + { + ScopedLock slUNL(mUNLLock); + + mUNL.erase(strPublicKey); + } } +// XXX Broken should opperate on seeds. void UniqueNodeList::nodeReset() { - Database* db=theApp->getWalletDB()->getDB(); + { + Database* db=theApp->getWalletDB()->getDB(); - ScopedLock sl(theApp->getWalletDB()->getDBLock()); - db->executeSQL("DELETE FROM TrustedNodes"); + ScopedLock sl(theApp->getWalletDB()->getDBLock()); + db->executeSQL("DELETE FROM TrustedNodes"); + } + { + ScopedLock slUNL(mUNLLock); + + mUNL.clear(); + } } Json::Value UniqueNodeList::getUnlJson() @@ -1203,7 +1276,9 @@ Json::Value UniqueNodeList::getUnlJson() return ret; } -void UniqueNodeList::nodeDefault(std::string strValidators) { +// Process a validators.txt. +// --> strValidators: a validators.txt +void UniqueNodeList::nodeDefault(const std::string& strValidators) { section secValidators = ParseSection(strValidators, true); section::mapped_type* pmtEntries = sectionEntries(secValidators, SECTION_VALIDATORS); @@ -1220,4 +1295,10 @@ void UniqueNodeList::nodeDefault(std::string strValidators) { } } +bool UniqueNodeList::nodeInUNL(const NewcoinAddress& naNodePublic) +{ + ScopedLock sl(mUNLLock); + + return mUNL.end() != mUNL.find(naNodePublic.humanNodePublic()); +} // vim:ts=4 diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h index c979871dea..40c6d99841 100644 --- a/src/UniqueNodeList.h +++ b/src/UniqueNodeList.h @@ -12,6 +12,7 @@ #include #include +#include // Guarantees minimum thoughput of 1 node per second. #define NODE_FETCH_JOBS 10 @@ -44,6 +45,10 @@ private: boost::posix_time::ptime mtpScoreUpdated; boost::posix_time::ptime mtpFetchUpdated; + boost::recursive_mutex mUNLLock; + // XXX Make this faster, make this the contents vector unsigned char or raw public key. + boost::unordered_set mUNL; + bool miscLoad(); bool miscSave(); @@ -58,6 +63,7 @@ private: std::string strComment; } seedDomain; + // Used to distribute scores. typedef struct { int iScore; int iRoundScore; @@ -71,6 +77,8 @@ private: typedef std::pair ipPort; typedef boost::unordered_map, score> epScore; + void trustedLoad(); + bool scoreRound(std::vector& vsnNodes); int iSourceScore(validatorSource vsWhy); @@ -98,11 +106,11 @@ private: void getValidatorsUrl(NewcoinAddress naNodePublic, section secSite); void getIpsUrl(NewcoinAddress naNodePublic, section secSite); - void responseIps(const std::string& strSite, NewcoinAddress naNodePublic, const boost::system::error_code& err, const std::string strIpsFile); + void responseIps(const std::string& strSite, const NewcoinAddress& naNodePublic, const boost::system::error_code& err, const std::string strIpsFile); void responseValidators(const std::string& strValidatorsUrl, NewcoinAddress naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile); - void processIps(const std::string& strSite, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrIps); - void processValidators(const std::string& strSite, const std::string& strValidatorsSrc, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrValidators); + void processIps(const std::string& strSite, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrIps); + void processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrValidators); void processFile(const std::string strDomain, NewcoinAddress naNodePublic, section secSite); @@ -115,14 +123,16 @@ public: // Begin processing. void start(); - void nodeAddPublic(NewcoinAddress naNodePublic, std::string strComment); + void nodeAddPublic(const NewcoinAddress& naNodePublic, const std::string& strComment); void nodeAddDomain(const std::string& strDomain, validatorSource vsWhy, std::string strComment=""); void nodeRemove(NewcoinAddress naNodePublic); - void nodeDefault(std::string strValidators); + void nodeDefault(const std::string& strValidators); void nodeReset(); void nodeScore(); + bool nodeInUNL(const NewcoinAddress& naNodePublic); + Json::Value getUnlJson(); };