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; 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/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/RPCServer.cpp b/src/RPCServer.cpp index d856b8947c..17c4423cf0 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()) { @@ -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 e9e71b2192..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; @@ -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; @@ -869,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 87aec83de0..7e34e53c2f 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); 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/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;