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/Config.cpp b/src/Config.cpp index 74df508ae4..08b3f36c57 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 @@ -25,7 +26,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" @@ -61,7 +63,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; @@ -123,8 +126,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 aa00ae1756..909f636ebd 100644 --- a/src/Config.h +++ b/src/Config.h @@ -76,8 +76,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; 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/Ledger.cpp b/src/Ledger.cpp index 1c5a8b7f21..440fb393a2 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 00750ea9c2..9d82641295 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" @@ -140,8 +141,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); @@ -163,25 +162,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); } + static 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 @@ -203,6 +198,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/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/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); 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/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/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 // 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/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 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/RPCServer.cpp b/src/RPCServer.cpp index d856b8947c..624bb67198 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 @@ -215,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. @@ -276,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; @@ -779,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()) { @@ -826,6 +827,144 @@ 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; + + 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) +{ + 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"; + } + + 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"); + } + else if ((uLedger = mNetOps->getCurrentLedger()).isZero()) + { + return JSONRPCError(503, "no current ledger"); + } + + STAmount saFee; + NicknameState::pointer nsSrc = mNetOps->getNicknameState(uLedger, strNickname); + + 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 [] // YYY Make making account default to first account for seed. Json::Value RPCServer::doPasswordFund(Json::Value ¶ms) @@ -1033,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()) { @@ -1216,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) @@ -1401,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()) { @@ -1424,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; @@ -1471,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, @@ -1632,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; @@ -1646,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. @@ -1867,6 +2006,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..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); @@ -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/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" 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 diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 72930ef294..328a7aa6fc 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -259,6 +259,49 @@ 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, + const std::vector& vucSignature) +{ + mTransaction->setITFieldH256(sfNickname, uNickname); + + // XXX Make sure field is present even for 0! + if (bSetOffer) + mTransaction->setITFieldAmount(sfMinimumOffer, saMinimumOffer); + + if (!vucSignature.empty()) + mTransaction->setITFieldVL(sfSignature, vucSignature); + + 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, + const std::vector& vucSignature) +{ + pointer tResult = boost::make_shared(ttNICKNAME_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); + + return tResult->setNicknameSet(naPrivateKey, uNickname, bSetOffer, saMinimumOffer, vucSignature); +} + // // PasswordFund // diff --git a/src/Transaction.h b/src/Transaction.h index 90cb1b934d..2510a04e64 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -71,6 +71,13 @@ private: const STAmount& saLimitAmount, uint32 uAcceptRate); + Transaction::pointer setNicknameSet( + const NewcoinAddress& naPrivateKey, + const uint256& uNickname, + bool bSetOffer, + const STAmount& saMinimumOffer, + const std::vector& vucSignature); + Transaction::pointer setPasswordFund( const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID); @@ -157,6 +164,18 @@ 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, + const std::vector& vucSignature); + // Pre-fund password change. static Transaction::pointer sharedPasswordFund( const NewcoinAddress& naPublicKey, const NewcoinAddress& naPrivateKey, diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 5126bbd4fa..8748f8b336 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)); @@ -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; @@ -473,7 +483,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran { std::cerr << "applyTransaction: Source is an unclaimed account." << std::endl; - result = tenUNCLAIMED; + result = terUNCLAIMED; } break; } @@ -514,9 +524,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; } @@ -554,7 +564,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran Log(lsINFO) << "Aseq=" << a_seq << ", Tseq=" << t_seq; if (t_seq != a_seq) { - // WRITEME: Special case code for changing transaction key if (a_seq < t_seq) { std::cerr << "applyTransaction: future sequence number" << std::endl; @@ -623,6 +632,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; @@ -651,7 +664,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) { @@ -870,6 +882,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(sfNickname); + 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(taaMODIFY, 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..597084b59f 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 @@ -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); @@ -125,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/TransactionFormats.cpp b/src/TransactionFormats.cpp index 66995e5a92..cddcafcf6c 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(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 }, + { 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, 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(); }; 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; 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 {