diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index e3b63cf40b..02343da2d8 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -130,15 +130,16 @@ int RPCServer::getParamCount(const Json::Value& params) return 1; } - +#if 0 // now, expire, n -bool RPCServer::parseBorrowRate(const std::string& sBorrowRate) +bool RPCServer::parseAcceptRate(const std::string& sAcceptRate) { - if (!sBorrowRate.compare("expire")) + if (!sAcceptRate.compare("expire")) 0; return true; } +#endif bool RPCServer::extractString(std::string& param, const Json::Value& params, int index) { @@ -373,30 +374,16 @@ Json::Value RPCServer::doPeers(Json::Value& params) return theApp->getConnectionPool().getPeersJson(); } -// credit_set [] [] [] +// credit_set [] Json::Value RPCServer::doCreditSet(Json::Value& params) { NewcoinAddress naSeed; NewcoinAddress naSrcAccountID; NewcoinAddress naDstAccountID; STAmount saLimitAmount; - std::string sBorrowRate; - std::string sBorrowStart; - std::string sBorrowExpire; - uint32 uBorrowRate; - uint32 uBorrowStart; - uint32 uBorrowExpire; + uint32 uAcceptRate = params.size() >= 6 ? boost::lexical_cast(params[5u].asString()) : 0; - if (params.size() >= 6) - sBorrowRate = params[6u].asString(); - - if (params.size() >= 7) - sBorrowStart = params[7u].asString(); - - if (params.size() >= 8) - sBorrowExpire = params[8u].asString(); - - if (params.size() < 5 || params.size() > 8) + if (params.size() < 5 || params.size() > 6) { return JSONRPCError(500, "invalid parameters"); } @@ -412,7 +399,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) { return JSONRPCError(500, "destination account id needed"); } - else if (!saLimitAmount.setValue(params[5u].asString(), params[6u].asString())) + else if (!saLimitAmount.setValue(params[3u].asString(), params[4u].asString())) { return JSONRPCError(500, "bad src amount/currency"); } @@ -427,16 +414,10 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) Json::Value obj = authorize(naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, sleSrc); if (!obj.empty()) - { return obj; - } STAmount saSrcBalance = sleSrc->getIValueFieldAmount(sfBalance); - uBorrowRate = 0; - uBorrowStart = 0; - uBorrowExpire = 0; - if (saSrcBalance < theConfig.FEE_DEFAULT) { return JSONRPCError(500, "insufficent funds"); @@ -451,9 +432,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) 0, // YYY No source tag naDstAccountID, saLimitAmount, - uBorrowRate, - uBorrowStart, - uBorrowExpire); + uAcceptRate); (void) theApp->getOPs().processTransaction(trans); @@ -463,9 +442,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params) obj["srcAccountID"] = naSrcAccountID.humanAccountID(); obj["dstAccountID"] = naDstAccountID.humanAccountID(); obj["limitAmount"] = saLimitAmount.getText(); - obj["borrowRate"] = uBorrowRate; - obj["borrowStart"] = uBorrowStart; - obj["borrowExpire"] = uBorrowExpire; + obj["acceptRate"] = uAcceptRate; return obj; } diff --git a/src/Transaction.cpp b/src/Transaction.cpp index 5872fdbf27..0816b30d8e 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -190,18 +190,12 @@ Transaction::pointer Transaction::setCreditSet( const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire) + uint32 uAcceptRate) { mTransaction->setITFieldAccount(sfDestination, naDstAccountID); mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount); - if (uBorrowRate) - mTransaction->setITFieldU32(sfBorrowRate, uBorrowRate); - if (uBorrowStart) - mTransaction->setITFieldU32(sfBorrowStart, uBorrowStart); - if (uBorrowExpire) - mTransaction->setITFieldU32(sfBorrowExpire, uBorrowExpire); + if (uAcceptRate) + mTransaction->setITFieldU32(sfAcceptRate, uAcceptRate); sign(naPrivateKey); @@ -216,15 +210,13 @@ Transaction::pointer Transaction::sharedCreditSet( uint32 uSourceTag, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire) + uint32 uAcceptRate) { pointer tResult = boost::make_shared(ttCREDIT_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag); - return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uBorrowRate, uBorrowStart, uBorrowExpire); + return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uAcceptRate); } // diff --git a/src/Transaction.h b/src/Transaction.h index e148270468..5f5789b328 100644 --- a/src/Transaction.h +++ b/src/Transaction.h @@ -61,9 +61,7 @@ private: const NewcoinAddress& naPrivateKey, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire); + uint32 uAcceptRate); Transaction::pointer setPayment( const NewcoinAddress& naPrivateKey, @@ -119,9 +117,7 @@ public: uint32 uSourceTag, const NewcoinAddress& naDstAccountID, const STAmount& saLimitAmount, - uint32 uBorrowRate, - uint32 uBorrowStart, - uint32 uBorrowExpire); + uint32 uAcceptRate); // Make a payment. static Transaction::pointer sharedPayment( diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index a1251e92f2..2dbb393575 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -2,9 +2,216 @@ #include "Config.h" #include "TransactionFormats.h" +#include "utils.h" #include +typedef SerializedLedgerEntry SLE; + +#define DIR_NODE_MAX 32 + +// We return the uNodeDir so that on delete we can quickly know where the element is mentioned in the directory. +TransactionEngineResult TransactionEngine::dirAdd( + std::vector& accounts, + uint64& uNodeDir, + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex) +{ + // Get the root. + uint256 uRootIndex = Ledger::getDirIndex(uBase, letKind); + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, uRootIndex); + bool bRootNew; + + // Get the last node index. + if (sleRoot) + { + bRootNew = false; + uNodeDir = sleRoot->getIFieldU64(sfLastNode); + } + else + { + bRootNew = true; + uNodeDir = 1; + + sleRoot = boost::make_shared(ltDIR_ROOT); + sleRoot->setIndex(uRootIndex); + sleRoot->setIFieldU64(sfFirstNode, uNodeDir); + sleRoot->setIFieldU64(sfLastNode, uNodeDir); + + accounts.push_back(std::make_pair(taaCREATE, sleRoot)); + } + + // Get the last node. + uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeDir); + LedgerStateParms lspNode = lepNONE; + SLE::pointer sleNode = bRootNew ? SLE::pointer() : mLedger->getDirNode(lspNode, uNodeIndex); + + if (sleNode) + { + STVector256 svIndexes; + + svIndexes = sleNode->getIFieldV256(sfIndexes); + if (DIR_NODE_MAX != svIndexes.peekValue().size()) + { + // Last node is not full, append. + + svIndexes.peekValue().push_back(uLedgerIndex); + sleNode->setIFieldV256(sfIndexes, svIndexes); + + accounts.push_back(std::make_pair(taaMODIFY, sleNode)); + } + // Last node is full, add a new node. + else if (!++uNodeDir) + { + return terDIR_FULL; + } + else + { + // Record new last node. + sleNode = SLE::pointer(); + + sleRoot->setIFieldU64(sfLastNode, uNodeDir); + accounts.push_back(std::make_pair(taaMODIFY, sleRoot)); + } + } + + if (!sleNode) + { + // Add to last node, which is empty. + sleNode = boost::make_shared(ltDIR_NODE); + sleNode->setIndex(uNodeIndex); + + STVector256 svIndexes; + + svIndexes.peekValue().push_back(uLedgerIndex); + sleNode->setIFieldV256(sfIndexes, svIndexes); + + accounts.push_back(std::make_pair(taaCREATE, sleNode)); + } + + return terSUCCESS; +} + +TransactionEngineResult TransactionEngine::dirDelete( + std::vector& accounts, + const uint64& uNodeDir, + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex) +{ + uint64 uNodeCur = uNodeDir; + uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeCur); + LedgerStateParms lspNode = lepNONE; + SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeIndex); + + if (!sleNode) + { + std::cerr << "dirDelete: no such node" << std::endl; + return terNODE_NOT_FOUND; + } + else + { + STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes); + std::vector& vuiIndexes = svIndexes.peekValue(); + std::vector::iterator it; + + it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex); + if (vuiIndexes.end() == it) + { + std::cerr << "dirDelete: node not mentioned" << std::endl; + return terNODE_NOT_MENTIONED; + } + else + { + // Get root information + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, Ledger::getDirIndex(uBase, letKind)); + + if (!sleRoot) + { + std::cerr << "dirDelete: root node is missing" << std::endl; + return terNODE_NO_ROOT; + } + + uint64 uFirstNodeOrig = sleRoot->getIFieldU64(sfFirstNode); + uint64 uLastNodeOrig = sleRoot->getIFieldU64(sfLastNode); + uint64 uFirstNode = uFirstNodeOrig; + uint64 uLastNode = uLastNodeOrig; + + // Remove the element. + if (vuiIndexes.size() > 1) + { + *it = vuiIndexes[vuiIndexes.size()-1]; + } + vuiIndexes.resize(vuiIndexes.size()-1); + + sleNode->setIFieldV256(sfIndexes, svIndexes); + + if (!vuiIndexes.empty() || (uFirstNode != uNodeCur && uLastNode != uNodeCur)) + { + // Node is not being deleted. + accounts.push_back(std::make_pair(taaMODIFY, sleNode)); + } + + while (uFirstNode && svIndexes.peekValue().empty() + && (uFirstNode == uNodeCur || uLastNode == uNodeCur)) + { + // Current node is empty and first or last, delete it. + accounts.push_back(std::make_pair(taaDELETE, sleNode)); + + if (uFirstNode == uLastNode) + { + // Complete deletion. + uFirstNode = 0; + } + else + { + if (uFirstNode == uNodeCur) + { + // Advance first node + ++uNodeCur; + ++uFirstNode; + } + else + { + // Rewind last node + --uNodeCur; + --uLastNode; + } + + // Get replacement node. + lspNode = lepNONE; + sleNode = mLedger->getDirNode(lspNode, Ledger::getDirIndex(uBase, letKind, uNodeCur)); + svIndexes = sleNode->getIFieldV256(sfIndexes); + } + } + + if (uFirstNode == uFirstNodeOrig && uLastNode == uLastNodeOrig) + { + // Dir is fine. + nothing(); + } + else if (uFirstNode) + { + // Update root's pointer pointers. + sleRoot->setIFieldU64(sfFirstNode, uFirstNode); + sleRoot->setIFieldU64(sfLastNode, uLastNode); + + accounts.push_back(std::make_pair(taaMODIFY, sleRoot)); + } + else + { + // Delete the root. + accounts.push_back(std::make_pair(taaDELETE, sleRoot)); + } + } + + return terSUCCESS; + } +} + TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn, TransactionEngineParams params) { @@ -106,8 +313,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran // find source account // If we are only verifying some transactions, this would be probablistic. - LedgerStateParms qry = lepNONE; - SerializedLedgerEntry::pointer sleSrc = mLedger->getAccountRoot(qry, srcAccountID); + LedgerStateParms lspRoot = lepNONE; + SLE::pointer sleSrc = mLedger->getAccountRoot(lspRoot, srcAccountID); if (!sleSrc) { std::cerr << str(boost::format("applyTransaction: Delay transaction: source account does not exisit: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; @@ -178,7 +385,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran break; case ttCREDIT_SET: - result = doCreditSet(txn, accounts); + result = doCreditSet(txn, accounts, srcAccountID); break; case ttINVALID: @@ -256,34 +463,34 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& return tenINVALID; } - LedgerStateParms qry = lepNONE; - SerializedLedgerEntry::pointer dest = accounts[0].second; + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = accounts[0].second; - if (!dest) + if (!sleDst) { // Source account does not exist. Could succeed if it was created first. std::cerr << str(boost::format("doClaim: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl; return terNO_ACCOUNT; } - std::cerr << str(boost::format("doClaim: %s") % dest->getFullText()) << std::endl; + std::cerr << str(boost::format("doClaim: %s") % sleDst->getFullText()) << std::endl; - if (dest->getIFieldPresent(sfAuthorizedKey)) + if (sleDst->getIFieldPresent(sfAuthorizedKey)) { // Source account already claimed. std::cerr << "doClaim: source already claimed" << std::endl; - return tenCLAIMED; + return terCLAIMED; } // // Verify claim is authorized for public key. // - std::vector vucCipher = txn.getITFieldVL(sfGenerator); - std::vector vucPubKey = txn.getITFieldVL(sfPubKey); - std::vector vucSignature = txn.getITFieldVL(sfSignature); + std::vector vucCipher = txn.getITFieldVL(sfGenerator); + std::vector vucPubKey = txn.getITFieldVL(sfPubKey); + std::vector vucSignature = txn.getITFieldVL(sfSignature); - NewcoinAddress naAccountPublic; + NewcoinAddress naAccountPublic; naAccountPublic.setAccountPublic(vucPubKey); @@ -297,11 +504,11 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& // Verify generator not already in use. // - uint160 hGeneratorID = naAccountPublic.getAccountID(); + uint160 hGeneratorID = naAccountPublic.getAccountID(); - qry = lepNONE; - SerializedLedgerEntry::pointer gen = mLedger->getGenerator(qry, hGeneratorID); - if (gen) + qry = lepNONE; + SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID); + if (sleGen) { // Generator is already in use. Regular passphrases limited to one wallet. std::cerr << "doClaim: generator already in use" << std::endl; @@ -313,41 +520,132 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& // // Set the public key needed to use the account. - dest->setIFieldH160(sfAuthorizedKey, hGeneratorID); + sleDst->setIFieldH160(sfAuthorizedKey, hGeneratorID); // Construct a generator map entry. - gen = boost::make_shared(ltGENERATOR_MAP); + sleGen = boost::make_shared(ltGENERATOR_MAP); - gen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); - gen->setIFieldH160(sfGeneratorID, hGeneratorID); - gen->setIFieldVL(sfGenerator, vucCipher); + sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID)); + sleGen->setIFieldH160(sfGeneratorID, hGeneratorID); + sleGen->setIFieldVL(sfGenerator, vucCipher); - accounts.push_back(std::make_pair(taaCREATE, gen)); + accounts.push_back(std::make_pair(taaCREATE, sleGen)); std::cerr << "doClaim<" << std::endl; + return terSUCCESS; } -TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction&, std::vector&) +TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction& txn, + std::vector&accounts, + const uint160& uSrcAccountID) { - return tenINVALID; + TransactionEngineResult terResult = terSUCCESS; + std::cerr << "doCreditSet>" << std::endl; + + // Check if destination makes sense. + uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); + + if (!uDstAccountID) + { + std::cerr << "doCreditSet: Invalid transaction: Payment destination account not specifed." << std::endl; + return tenDST_NEEDED; + } + else if (uSrcAccountID == uDstAccountID) + { + std::cerr << "doCreditSet: Invalid transaction: Source account is the same as destination." << std::endl; + return tenDST_IS_SRC; + } + + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID); + if (!sleDst) + { + std::cerr << "doCreditSet: Delay transaction: Destination account does not exist." << std::endl; + + return terNO_DST; + } + + STAmount saLimitAmount = txn.getITFieldAmount(sfLimitAmount); + uint160 uCurrency = saLimitAmount.getCurrency(); + bool bSltD = uSrcAccountID < uDstAccountID; + uint32 uFlags = bSltD ? lsfLowIndexed : lsfHighIndexed; + STAmount saBalance(uCurrency); + bool bAddIndex; + + qry = lepNONE; + SLE::pointer sleRippleState = mLedger->getRippleState(qry, uSrcAccountID, uDstAccountID, uCurrency); + if (sleRippleState) + { + std::cerr << "doCreditSet: Modifying ripple line." << std::endl; + + bAddIndex = !(sleRippleState->getFlags() & uFlags); + + sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighID, saLimitAmount); + + accounts.push_back(std::make_pair(taaMODIFY, sleRippleState)); + + if (bAddIndex) + sleRippleState->setFlag(uFlags); + } + // Line does not exist. + else if (!saLimitAmount.getValue()) + { + std::cerr << "doCreditSet: Setting non-existant ripple line to 0." << std::endl; + + return terNO_LINE_NO_ZERO; + } + else + { + std::cerr << "doCreditSet: Creating ripple line." << std::endl; + STAmount saZero(uCurrency); + + bAddIndex = true; + sleRippleState = boost::make_shared(ltRIPPLE_STATE); + + sleRippleState->setIndex(Ledger::getRippleStateIndex(uSrcAccountID, uDstAccountID, uCurrency)); + + sleRippleState->setFlag(uFlags); + sleRippleState->setIFieldAmount(sfBalance, saZero); // Zero balance in currency. + sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighLimit, saLimitAmount); + sleRippleState->setIFieldAmount(bSltD ? sfHighLimit : sfLowLimit, saZero); + sleRippleState->setIFieldAccount(bSltD ? sfLowID : sfHighID, uSrcAccountID); + sleRippleState->setIFieldAccount(bSltD ? sfHighID : sfLowID, uDstAccountID); + + accounts.push_back(std::make_pair(taaCREATE, sleRippleState)); + } + + if (bAddIndex) + { + // Add entries so clients can find lines. + // - Client needs to be able to walk who account has given credit to and who has account's credit. + // - Client doesn't need to know every account who has extended credit but it owed nothing. + uint64 uSrcRef; // Ignored, ripple_state dirs never delete. + + // XXX Verify extend is passing the right bits, not the zero bits. + // XXX Make dirAdd more flexiable to take vector. + terResult = dirAdd(accounts, uSrcRef, ltRIPPLE_STATE, uint160extend256(uSrcAccountID, 0), sleRippleState->getIndex()); + } + + std::cerr << "doCreditSet<" << std::endl; + + return terResult; } TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn, std::vector& accounts, - uint160 srcAccountID) + const uint160& srcAccountID) { uint32 txFlags = txn.getFlags(); - uint160 dstAccountID = txn.getITFieldAccount(sfDestination); + uint160 uDstAccountID = txn.getITFieldAccount(sfDestination); - // Does the destination account exist? - if (!dstAccountID) + if (!uDstAccountID) { std::cerr << "doPayment: Invalid transaction: Payment destination account not specifed." << std::endl; return tenINVALID; } // XXX Only bad if no currency conversion in between through other people's offer. - else if (srcAccountID == dstAccountID) + else if (srcAccountID == uDstAccountID) { std::cerr << "doPayment: Invalid transaction: Source account is the same as destination." << std::endl; return tenINVALID; @@ -355,24 +653,23 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction bool bCreate = !!(txFlags & tfCreateAccount); - uint160 currency; + uint160 uCurrency; if (txn.getITFieldPresent(sfCurrency)) { - currency = txn.getITFieldH160(sfCurrency); - if (!currency) + uCurrency = txn.getITFieldH160(sfCurrency); + if (!uCurrency) { - std::cerr << "doPayment: Invalid transaction: XNC explicitly specified." << std::endl; + std::cerr << "doPayment: Invalid transaction: " SYSTEM_CURRENCY_CODE " explicitly specified." << std::endl; return tenEXPLICITXNC; } } - LedgerStateParms qry = lepNONE; - - SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, dstAccountID); - if (!dest) + LedgerStateParms qry = lepNONE; + SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID); + if (!sleDst) { // Destination account does not exist. - if (bCreate && !!currency) + if (bCreate && !!uCurrency) { std::cerr << "doPayment: Invalid transaction: Create account may only fund XBC." << std::endl; return tenCREATEXNC; @@ -380,32 +677,32 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction else if (!bCreate) { std::cerr << "doPayment: Delay transaction: Destination account does not exist." << std::endl; - return terNO_TARGET; + return terNO_DST; } // Create the account. - dest = boost::make_shared(ltACCOUNT_ROOT); + sleDst = boost::make_shared(ltACCOUNT_ROOT); - dest->setIndex(Ledger::getAccountRootIndex(dstAccountID)); - dest->setIFieldAccount(sfAccount, dstAccountID); - dest->setIFieldU32(sfSequence, 1); + sleDst->setIndex(Ledger::getAccountRootIndex(uDstAccountID)); + sleDst->setIFieldAccount(sfAccount, uDstAccountID); + sleDst->setIFieldU32(sfSequence, 1); - accounts.push_back(std::make_pair(taaCREATE, dest)); + accounts.push_back(std::make_pair(taaCREATE, sleDst)); } // Destination exists. else if (bCreate) { std::cerr << "doPayment: Invalid transaction: Account already created." << std::endl; - return tenCREATED; + return terCREATED; } else { - accounts.push_back(std::make_pair(taaMODIFY, dest)); + accounts.push_back(std::make_pair(taaMODIFY, sleDst)); } STAmount saAmount = txn.getITFieldAmount(sfAmount); - if (!currency) + if (!uCurrency) { STAmount saSrcBalance = accounts[0].second->getIValueFieldAmount(sfBalance); @@ -430,8 +727,8 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector&) { std::cerr << "doTransitSet>" << std::endl; - - SerializedLedgerEntry::pointer sleSrc = accounts[0].second; +#if 0 + SLE::pointer sleSrc = accounts[0].second; bool bTxnTransitRate = st->getIFieldPresent(sfTransitRate); bool bTxnTransitStart = st->getIFieldPresent(sfTransitStart); @@ -451,104 +748,85 @@ TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransact uint32 uActNextTransitStart = bActNextTransitStart ? sleSrc->getIFieldU32(sfNextTransitStart) : 0; uint32 uActNextTransitExpire = bActNextTransitExpire ? sleSrc->getIFieldU32(sfNextTransitExpire) : 0; - // Try to overwrite next rate. + // + // Update view + // - bool bBetterNextExpire = - (!bTxnTransitExpire // Txn does not expire (same or extends) - || (bActNextTransitExpire && uTxnTransitExpire >= uActTransitExpire)); // Same or longer the next. + bool bNoCurrent = !bActTransitRate; + bool bCurrentExpired = + bActTransitExpire // Current can expire + && bActNextTransitStart // Have a replacement + && uActTransitExpire <= uLedger; // Current is expired - bool bBetterNextRate = - !bActNextTransitRate // No next rate, txn is better. - || (uTxnTransitRate <= uActNextTransitRate); // Charge is the same or less. - - // Must start at the same time or sooner. - bool bBetterNextStart = - - // If starting sooner, must be better than current, or current must not protect range. - - - if (!bActNextTransitRate) + // Replace current with next if need. + if (bNoCurrent // No current. + && bActNextTransitRate // Have next. + && uActNextTransitStart <= uLedger) // Next has started. { - // No next. Overwrite next. - } - else if (uTxnTransitRate <= uActNextTransitRate && bBetterNextExpire) - { - // Better than + // Make next current. + uActTransitRate = uActNextTransitRate; + bActTransitExpire = bActNextTransitStart; + uActTransitExpire = uActNextTransitExpire; + + // Remove next. + uActNextTransitStart = 0; } - // True if no rate is active or going to be active; - bool bNoRate = !bActTransitRate && !bActNextTransitRate; + // + // Determine new transaction deposition. + // - bool bStartNow = bTxnTransitStart - ? uTxnTransitStart < uLedger - : bActTransitRate - ? bActTransitExpire - ? - : true // Current never expires. - : true; // Nothing is running. + bool bBetterThanCurrent = + !no current + || ( + Expires same or later than current + Start before or same as current + Fee same or less than current + ) - // True if new rate does not apply immediately. - boo bRateIsLater = bTxnTransitStart - ? uTxnTransitStart < uLedger + bool bBetterThanNext = + !no next + || ( + Expires same or later than next + Start before or same as next + Fee same or less than next + ) - : bActNextTransitRate && bTxnTransitExpire; + bool bBetterThanBoth = + bBetterThanCurrent && bBetterThanNext - if (no_rate || rate_is_better || rate_is_later) + bool bCurrentBlocks = + !bBetterThanCurrent + && overlaps with current + + bool bNextBlocks = + !bBetterThanNext + && overlaps with next + + if (bBetterThanBoth) { - // Install. - if (starting) - { - // install now - } - else - { - // install next - } + // Erase both and install. + + // If not starting now, install as next. + } + else if (bCurrentBlocks || bNextBlocks) + { + // Invalid ignore + } + else if (bBetterThanCurrent) + { + // Install over current + } + else if (bBetterThanNext) + { + // Install over next } else { - return tenTRANSIT_WORSE; + // Error. } - if (no_rate && starting) - if (!bActTransitRate && !bActNextTransitRate) { - // No rate - bProtected = false; - } if (bActTransitRate && !bTx - - if (bTxnTransitStart && uTxnTransitStart > uLedger) - { - // Start at a particular time. - - } - else - { - // No start or start in the past, start now. - if (!bActTransitRate && !bActNextTransitRate) - { - // No current or future rate. - - uDstTransitRate = uTxnTransitRate; - uDstTransitExpire = uTxnTransitExpire; // 0 for never expire. - } - else if (bActTransitRate && !bActNextTransitRate) - { - // Have a current rate and none pending. - if (!bActTransitExpire) { - // Current rate does not expire - - } - } - else - { - // Have a future rate. - - } - } - if (!bActTransitRate && !bActNextTransitRate) - { - - } + return tenTRANSIT_WORSE; // Set current. uDstTransitRate = uTxnTransitRate; @@ -560,7 +838,7 @@ TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransact uDstNextTransitExpire = uTxnTransitExpire; // 0 for never expire. if (txn.getITFieldPresent(sfCurrency)) - +#endif std::cerr << "doTransitSet<" << std::endl; return tenINVALID; } diff --git a/src/TransactionEngine.h b/src/TransactionEngine.h index bd2f3bdd55..2679b9dbfe 100644 --- a/src/TransactionEngine.h +++ b/src/TransactionEngine.h @@ -18,11 +18,9 @@ enum TransactionEngineResult tenGEN_IN_USE = -300, // Generator already in use. tenCREATEXNC, // Can not specify non XNC for Create. tenEXPLICITXNC, // XNC is used by default, don't specify it. + tenDST_NEEDED, // Destination not specified. + tenDST_IS_SRC, // Destination may not be source. - // Not possible due to ledger database: Fee claimed - tenCREATED = -200, // Can not create a previously created account. - tenCLAIMED, // Can not claim a previously claimed account. - tenTRANSIT_WORSE, // Can not override a better promise. // Other tenFAILED = -100, // Something broke horribly @@ -32,18 +30,27 @@ enum TransactionEngineResult terSUCCESS = 0, // The transaction was applied - // terFAILED_BUT_COULD_SUCEED = >0 + // terFAILED_BUT_COULD_SUCCEED = >0 + // Conflict with ledger database: Fee claimed + // Might succeed if not conflict is not caused by transaction ordering. terALREADY, // The transaction was already in the ledger - terNO_ACCOUNT, // The source account does not exist - terNO_TARGET, // The destination does not exist - terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load) - terINSUF_FEE_B, // Account balance can't pay fee - terUNFUNDED, // Source account had insufficient balance for transactin - terNO_PATH, // No path existed or met transaction/balance requirements - terPAST_SEQ, // This sequence number has already past terBAD_SEQ, // This sequence number should be zero for prepaid transactions. - terPRE_SEQ, // Missing/inapplicable prior transaction + terCLAIMED, // Can not claim a previously claimed account. + terCREATED, // Can not create a previously created account. + terDIR_FULL, // Can not add entry to full dir. + terINSUF_FEE_B, // Account balance can't pay fee + terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load) + terNODE_NOT_FOUND, // Can not delete a dir node. + terNODE_NOT_MENTIONED, + terNODE_NO_ROOT, + terNO_ACCOUNT, // The source account does not exist + terNO_DST, // The destination does not exist + terNO_PATH, // No path existed or met transaction/balance requirements terPAST_LEDGER, // The transaction expired and can't be applied + terPAST_SEQ, // This sequence number has already past + terPRE_SEQ, // Missing/inapplicable prior transaction + terUNFUNDED, // Source account had insufficient balance for transactin + terNO_LINE_NO_ZERO, // Can't zero non-existant line, destination might make it. }; enum TransactionEngineParams @@ -65,17 +72,33 @@ typedef std::pair Affe class TransactionEngine { +private: + TransactionEngineResult dirAdd( + std::vector& accounts, + uint64& uNodeDir, // Node of entry. + const LedgerEntryType letKind, + const uint256& uBase, + const uint256& uLedgerIndex); + + TransactionEngineResult dirDelete( + std::vector& accounts, + const uint64& uNodeDir, // Node item is mentioned in. + const LedgerEntryType letKind, + const uint256& uBase, // Key of item. + const uint256& uLedgerIndex); // Item being deleted + protected: Ledger::pointer mLedger; - TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector&); TransactionEngineResult doCancel(const SerializedTransaction&, std::vector&); TransactionEngineResult doClaim(const SerializedTransaction&, std::vector&); + TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector&, + const uint160& srcAccountID); TransactionEngineResult doDelete(const SerializedTransaction&, std::vector&); TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector&); TransactionEngineResult doOffer(const SerializedTransaction&, std::vector&); TransactionEngineResult doPayment(const SerializedTransaction&, std::vector&, - uint160 srcAccountID); + const uint160& srcAccountID); TransactionEngineResult doStore(const SerializedTransaction&, std::vector&); TransactionEngineResult doTake(const SerializedTransaction&, std::vector&); TransactionEngineResult doTransitSet(const SerializedTransaction&, std::vector&); diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index 42af4a4c12..10d435f26c 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -18,9 +18,9 @@ TransactionFormat InnerTxnFormats[]= { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, { S_FIELD(LimitAmount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(BorrowRate), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(BorrowStart), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(BorrowExpire), STI_UINT32, SOE_IFFLAG, 4 }, + { S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 }, + { S_FIELD(AcceptStart), STI_UINT32, SOE_IFFLAG, 2 }, + { S_FIELD(AcceptExpire), STI_UINT32, SOE_IFFLAG, 4 }, { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 8 }, { S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 }, { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } diff --git a/src/main.cpp b/src/main.cpp index 8c8177cec5..21256e672a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,7 @@ void printHelp(const po::options_description& desc) cout << " account_info |" << endl; cout << " account_info || []" << endl; cout << " connect []" << endl; - cout << " credit_set [] [] []" << endl; + cout << " credit_set []" << endl; cout << " ledger" << endl; cout << " peers" << endl; cout << " send [] [] []" << endl;