mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Work towards ripple and offers.
This commit is contained in:
@@ -256,10 +256,11 @@ STAmount::STAmount(const char* name, int64 value) : SerializedType(name), mOffse
|
|||||||
|
|
||||||
void STAmount::setValue(const STAmount &a)
|
void STAmount::setValue(const STAmount &a)
|
||||||
{
|
{
|
||||||
mCurrency = a.mCurrency;
|
mCurrency = a.mCurrency;
|
||||||
mValue = a.mValue;
|
mIssuer = a.mIssuer;
|
||||||
mOffset = a.mOffset;
|
mValue = a.mValue;
|
||||||
mIsNative = a.mIsNative;
|
mOffset = a.mOffset;
|
||||||
|
mIsNative = a.mIsNative;
|
||||||
mIsNegative = a.mIsNegative;
|
mIsNegative = a.mIsNegative;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,11 +456,13 @@ STAmount STAmount::operator-(void) const
|
|||||||
|
|
||||||
STAmount& STAmount::operator=(const STAmount& a)
|
STAmount& STAmount::operator=(const STAmount& a)
|
||||||
{
|
{
|
||||||
mValue = a.mValue;
|
mValue = a.mValue;
|
||||||
mOffset = a.mOffset;
|
mOffset = a.mOffset;
|
||||||
mCurrency = a.mCurrency;
|
mIssuer = a.mIssuer;
|
||||||
mIsNative = a.mIsNative;
|
mCurrency = a.mCurrency;
|
||||||
|
mIsNative = a.mIsNative;
|
||||||
mIsNegative = a.mIsNegative;
|
mIsNegative = a.mIsNegative;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -469,6 +472,7 @@ STAmount& STAmount::operator=(uint64 v)
|
|||||||
mValue = v;
|
mValue = v;
|
||||||
mIsNegative = false;
|
mIsNegative = false;
|
||||||
if (!mIsNative) canonicalize();
|
if (!mIsNative) canonicalize();
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,6 +481,7 @@ STAmount& STAmount::operator+=(uint64 v)
|
|||||||
if (mIsNative)
|
if (mIsNative)
|
||||||
setSNValue(getSNValue() + static_cast<int64>(v));
|
setSNValue(getSNValue() + static_cast<int64>(v));
|
||||||
else *this += STAmount(mCurrency, v);
|
else *this += STAmount(mCurrency, v);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,6 +490,7 @@ STAmount& STAmount::operator-=(uint64 v)
|
|||||||
if (mIsNative)
|
if (mIsNative)
|
||||||
setSNValue(getSNValue() - static_cast<int64>(v));
|
setSNValue(getSNValue() - static_cast<int64>(v));
|
||||||
else *this -= STAmount(mCurrency, v);
|
else *this -= STAmount(mCurrency, v);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,15 +703,24 @@ STAmount STAmount::multiply(const STAmount& v1, const STAmount& v2, const uint16
|
|||||||
else return STAmount(currencyOut, v.getulong(), offset1 + offset2 + 14);
|
else return STAmount(currencyOut, v.getulong(), offset1 + offset2 + 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert an offer into an index amount so they sort by rate.
|
||||||
|
// A taker will take the best, lowest, rate first.
|
||||||
|
// (e.g. a taker will prefer pay 1 get 3 over pay 1 get 2.
|
||||||
|
// --> offerOut: takerGets: How much the offerer is selling to the taker.
|
||||||
|
// --> offerIn: takerPays: How much the offerer is receiving from the taker.
|
||||||
|
// <-- uRate: normalize(offerIn/offerOut)
|
||||||
|
// A lower rate is better for the person taking the order.
|
||||||
|
// The taker gets more for less with a lower rate.
|
||||||
uint64 STAmount::getRate(const STAmount& offerOut, const STAmount& offerIn)
|
uint64 STAmount::getRate(const STAmount& offerOut, const STAmount& offerIn)
|
||||||
{ // Convert an offer into an index amount so they sort (lower is better)
|
{
|
||||||
// offerOut = how much comes out of the offer, from the offeror to the taker
|
|
||||||
// offerIn = how much goes into the offer, from the taker to the offeror
|
|
||||||
if (offerOut.isZero()) throw std::runtime_error("Worthless offer");
|
if (offerOut.isZero()) throw std::runtime_error("Worthless offer");
|
||||||
|
|
||||||
STAmount r = divide(offerIn, offerOut, uint160(1));
|
STAmount r = divide(offerIn, offerOut, uint160(1));
|
||||||
|
|
||||||
assert((r.getExponent() >= -100) && (r.getExponent() <= 155));
|
assert((r.getExponent() >= -100) && (r.getExponent() <= 155));
|
||||||
|
|
||||||
uint64 ret = r.getExponent() + 100;
|
uint64 ret = r.getExponent() + 100;
|
||||||
|
|
||||||
return (ret << (64 - 8)) | r.getMantissa();
|
return (ret << (64 - 8)) | r.getMantissa();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,11 +761,19 @@ STAmount STAmount::getClaimed(STAmount& offerOut, STAmount& offerIn, STAmount& p
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
STAmount STAmount::getNeeded(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
|
STAmount STAmount::getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed)
|
||||||
{ // Someone wants to get (needed) out of the offer, how much should they pay in?
|
{ // Someone wants to get (needed) out of the offer, how much should they pay in?
|
||||||
if (offerOut.isZero()) return STAmount(offerIn.getCurrency());
|
if (offerOut.isZero())
|
||||||
if (needed >= offerOut) return needed;
|
return STAmount(offerIn.getCurrency());
|
||||||
|
|
||||||
|
if (needed >= offerOut)
|
||||||
|
{
|
||||||
|
// They need more than offered, pay full amount.
|
||||||
|
return needed;
|
||||||
|
}
|
||||||
|
|
||||||
STAmount ret = divide(multiply(needed, offerIn, uint160(1)), offerOut, offerIn.getCurrency());
|
STAmount ret = divide(multiply(needed, offerIn, uint160(1)), offerOut, offerIn.getCurrency());
|
||||||
|
|
||||||
return (ret > offerIn) ? offerIn : ret;
|
return (ret > offerIn) ? offerIn : ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
src/Ledger.h
19
src/Ledger.h
@@ -65,6 +65,7 @@ private:
|
|||||||
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
||||||
uint64 mTotCoins;
|
uint64 mTotCoins;
|
||||||
uint64 mCloseTime; // when this ledger closes
|
uint64 mCloseTime; // when this ledger closes
|
||||||
|
uint64 mParentCloseTime;
|
||||||
uint32 mLedgerSeq;
|
uint32 mLedgerSeq;
|
||||||
uint16 mLedgerInterval;
|
uint16 mLedgerInterval;
|
||||||
bool mClosed, mValidHash, mAccepted, mImmutable;
|
bool mClosed, mValidHash, mAccepted, mImmutable;
|
||||||
@@ -119,6 +120,7 @@ public:
|
|||||||
uint64 getTotalCoins() const { return mTotCoins; }
|
uint64 getTotalCoins() const { return mTotCoins; }
|
||||||
void destroyCoins(uint64 fee) { mTotCoins -= fee; }
|
void destroyCoins(uint64 fee) { mTotCoins -= fee; }
|
||||||
uint64 getCloseTimeNC() const { return mCloseTime; }
|
uint64 getCloseTimeNC() const { return mCloseTime; }
|
||||||
|
uint64 getParentCloseTimeNC() const { return mParentCloseTime; }
|
||||||
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
||||||
uint16 getInterval() const { return mLedgerInterval; }
|
uint16 getInterval() const { return mLedgerInterval; }
|
||||||
|
|
||||||
@@ -200,17 +202,24 @@ public:
|
|||||||
SLE::pointer getOffer(LedgerStateParms& parms, const uint160& uAccountID, uint32 uSequence)
|
SLE::pointer getOffer(LedgerStateParms& parms, const uint160& uAccountID, uint32 uSequence)
|
||||||
{ return getOffer(parms, getOfferIndex(uAccountID, uSequence)); }
|
{ return getOffer(parms, getOfferIndex(uAccountID, uSequence)); }
|
||||||
|
|
||||||
|
// The index of an offer.
|
||||||
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
|
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
|
||||||
|
|
||||||
static uint256 getOfferDirIndex(const uint160& uAccountID);
|
//
|
||||||
|
// Owner functions
|
||||||
|
//
|
||||||
|
|
||||||
|
// All items controlled by an account are here: offers
|
||||||
|
static uint256 getOwnerDirIndex(const uint160& uAccountID);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Directory functions
|
// Directory functions
|
||||||
//
|
// Directories are doubly linked lists of nodes.
|
||||||
|
|
||||||
|
// Given a directory root and and index compute the index of a node.
|
||||||
static uint256 getDirNodeIndex(const uint256& uDirRoot, const uint64 uNodeIndex=0);
|
static uint256 getDirNodeIndex(const uint256& uDirRoot, const uint64 uNodeIndex=0);
|
||||||
|
|
||||||
|
// Return a node: root or normal
|
||||||
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
|
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -223,12 +232,12 @@ public:
|
|||||||
// Ripple functions : credit lines
|
// Ripple functions : credit lines
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// Index of node which is the ripple state between to accounts for a currency.
|
||||||
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency);
|
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency);
|
||||||
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
||||||
{ return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); }
|
{ return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); }
|
||||||
|
|
||||||
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB)
|
// Directory of lines indexed by an account (not all lines are indexed)
|
||||||
{ return getRippleStateIndex(naA, naB, uint160()); }
|
|
||||||
static uint256 getRippleDirIndex(const uint160& uAccountID);
|
static uint256 getRippleDirIndex(const uint160& uAccountID);
|
||||||
|
|
||||||
RippleState::pointer getRippleState(const uint256& uNode);
|
RippleState::pointer getRippleState(const uint256& uNode);
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ LedgerEntryFormat LedgerFormats[]=
|
|||||||
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
||||||
{ S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 },
|
{ S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 },
|
||||||
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
||||||
{ S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 16 },
|
{ S_FIELD(TransferRate), STI_UINT32, SOE_IFFLAG, 16 },
|
||||||
|
{ S_FIELD(Domain), STI_VL, SOE_IFFLAG, 32 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
@@ -49,7 +50,7 @@ LedgerEntryFormat LedgerFormats[]=
|
|||||||
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
|
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 },
|
{ S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(OwnerNode), STI_UINT64, SOE_REQUIRED, 0 },
|
{ S_FIELD(OwnerNode), STI_UINT64, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(OfferNode), STI_UINT64, SOE_REQUIRED, 0 },
|
{ S_FIELD(BookNode), STI_UINT64, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ enum LedgerNameSpace
|
|||||||
spaceRipple = 'r',
|
spaceRipple = 'r',
|
||||||
spaceRippleDir = 'R',
|
spaceRippleDir = 'R',
|
||||||
spaceOffer = 'o', // Entry for an offer.
|
spaceOffer = 'o', // Entry for an offer.
|
||||||
spaceOfferDir = 'O', // Directory of an account's offers.
|
spaceOwnerDir = 'O', // Directory of things owned by an account.
|
||||||
spaceBookDir = 'B', // Directory of order books.
|
spaceBookDir = 'B', // Directory of order books.
|
||||||
spaceBond = 'b',
|
spaceBond = 'b',
|
||||||
spaceInvoice = 'i',
|
spaceInvoice = 'i',
|
||||||
|
|||||||
@@ -99,11 +99,11 @@ uint256 Ledger::getOfferIndex(const uint160& uAccountID, uint32 uSequence)
|
|||||||
return s.getSHA512Half();
|
return s.getSHA512Half();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 Ledger::getOfferDirIndex(const uint160& uAccountID)
|
uint256 Ledger::getOwnerDirIndex(const uint160& uAccountID)
|
||||||
{
|
{
|
||||||
Serializer s(22);
|
Serializer s(22);
|
||||||
|
|
||||||
s.add16(spaceOfferDir); // 2
|
s.add16(spaceOwnerDir); // 2
|
||||||
s.add160(uAccountID); // 20
|
s.add160(uAccountID); // 20
|
||||||
|
|
||||||
return s.getSHA512Half();
|
return s.getSHA512Half();
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ enum SOE_Field
|
|||||||
sfAmountOut,
|
sfAmountOut,
|
||||||
sfAuthorizedKey,
|
sfAuthorizedKey,
|
||||||
sfBalance,
|
sfBalance,
|
||||||
|
sfBookNode,
|
||||||
sfBorrowExpire,
|
sfBorrowExpire,
|
||||||
sfBorrowRate,
|
sfBorrowRate,
|
||||||
sfBorrowStart,
|
sfBorrowStart,
|
||||||
@@ -43,6 +44,7 @@ enum SOE_Field
|
|||||||
sfCurrencyIn,
|
sfCurrencyIn,
|
||||||
sfCurrencyOut,
|
sfCurrencyOut,
|
||||||
sfDestination,
|
sfDestination,
|
||||||
|
sfDomain,
|
||||||
sfEmailHash,
|
sfEmailHash,
|
||||||
sfExpiration,
|
sfExpiration,
|
||||||
sfExtensions,
|
sfExtensions,
|
||||||
@@ -76,7 +78,6 @@ enum SOE_Field
|
|||||||
sfNextTransitRate,
|
sfNextTransitRate,
|
||||||
sfNextTransitStart,
|
sfNextTransitStart,
|
||||||
sfNickname,
|
sfNickname,
|
||||||
sfOfferNode,
|
|
||||||
sfOfferSequence,
|
sfOfferSequence,
|
||||||
sfOwnerNode,
|
sfOwnerNode,
|
||||||
sfPaths,
|
sfPaths,
|
||||||
@@ -90,9 +91,7 @@ enum SOE_Field
|
|||||||
sfSourceTag,
|
sfSourceTag,
|
||||||
sfTarget,
|
sfTarget,
|
||||||
sfTargetLedger,
|
sfTargetLedger,
|
||||||
sfTransitExpire,
|
sfTransferRate,
|
||||||
sfTransitRate,
|
|
||||||
sfTransitStart,
|
|
||||||
sfVersion,
|
sfVersion,
|
||||||
sfWalletLocator,
|
sfWalletLocator,
|
||||||
|
|
||||||
|
|||||||
@@ -207,6 +207,7 @@ class STAmount : public SerializedType
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint160 mCurrency;
|
uint160 mCurrency;
|
||||||
|
uint160 mIssuer; // Only for access, not compared.
|
||||||
|
|
||||||
uint64 mValue;
|
uint64 mValue;
|
||||||
int mOffset;
|
int mOffset;
|
||||||
@@ -282,7 +283,10 @@ public:
|
|||||||
void negate() { if (!isZero()) mIsNegative = !mIsNegative; }
|
void negate() { if (!isZero()) mIsNegative = !mIsNegative; }
|
||||||
void zero() { mOffset = mIsNative ? -100 : 0; mValue = 0; mIsNegative = false; }
|
void zero() { mOffset = mIsNative ? -100 : 0; mValue = 0; mIsNegative = false; }
|
||||||
|
|
||||||
const uint160& getCurrency() const { return mCurrency; }
|
const uint160& getIssuer() const { return mIssuer; }
|
||||||
|
void setIssuer(const uint160& uIssuer) { mIssuer = uIssuer; }
|
||||||
|
|
||||||
|
const uint160& getCurrency() const { return mCurrency; }
|
||||||
bool setValue(const std::string& sAmount, const std::string& sCurrency);
|
bool setValue(const std::string& sAmount, const std::string& sCurrency);
|
||||||
void setValue(const STAmount &);
|
void setValue(const STAmount &);
|
||||||
|
|
||||||
@@ -329,7 +333,7 @@ public:
|
|||||||
static STAmount getClaimed(STAmount& offerOut, STAmount& offerIn, STAmount& paid);
|
static STAmount getClaimed(STAmount& offerOut, STAmount& offerIn, STAmount& paid);
|
||||||
|
|
||||||
// Someone is offering X for Y, I need Z, how much do I pay
|
// Someone is offering X for Y, I need Z, how much do I pay
|
||||||
static STAmount getNeeded(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed);
|
static STAmount getPay(const STAmount& offerOut, const STAmount& offerIn, const STAmount& needed);
|
||||||
|
|
||||||
// Native currency conversions, to/from display format
|
// Native currency conversions, to/from display format
|
||||||
static uint64 convertToDisplayAmount(const STAmount& internalAmount, uint64 totalNow, uint64 totalInit);
|
static uint64 convertToDisplayAmount(const STAmount& internalAmount, uint64 totalNow, uint64 totalInit);
|
||||||
|
|||||||
@@ -61,12 +61,12 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
|
|||||||
{ terINSUF_FEE_T, "terINSUF_FEE_T", "fee insufficient now (account doesn't exist, network load)" },
|
{ terINSUF_FEE_T, "terINSUF_FEE_T", "fee insufficient now (account doesn't exist, network load)" },
|
||||||
{ terNODE_NOT_FOUND, "terNODE_NOT_FOUND", "Can not delete a directory node." },
|
{ terNODE_NOT_FOUND, "terNODE_NOT_FOUND", "Can not delete a directory node." },
|
||||||
{ terNODE_NOT_MENTIONED, "terNODE_NOT_MENTIONED", "Could not remove node from a directory." },
|
{ terNODE_NOT_MENTIONED, "terNODE_NOT_MENTIONED", "Could not remove node from a directory." },
|
||||||
{ terNODE_NO_ROOT, "terNODE_NO_ROOT", "Directory doesn't exist." },
|
{ terNODE_NO_ROOT, "terNODE_NO_ROOT", "Directory doesn't exist." },
|
||||||
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist" },
|
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist" },
|
||||||
{ terNO_DST, "terNO_DST", "The destination does not exist" },
|
{ terNO_DST, "terNO_DST", "The destination does not exist" },
|
||||||
{ terNO_LINE_NO_ZERO, "terNO_LINE_NO_ZERO", "Can't zero non-existant line, destination might make it." },
|
{ terNO_LINE_NO_ZERO, "terNO_LINE_NO_ZERO", "Can't zero non-existant line, destination might make it." },
|
||||||
{ terNO_PATH, "terNO_PATH", "No path existed or met transaction/balance requirements" },
|
{ terNO_PATH, "terNO_PATH", "No path existed or met transaction/balance requirements" },
|
||||||
{ terOFFER_NOT_FOUND, "terOFFER_NOT_FOUND", "Can not cancel offer." },
|
{ terOFFER_NOT_FOUND, "terOFFER_NOT_FOUND", "Can not cancel offer." },
|
||||||
{ terOVER_LIMIT, "terOVER_LIMIT", "Over limit." },
|
{ terOVER_LIMIT, "terOVER_LIMIT", "Over limit." },
|
||||||
{ terPAST_LEDGER, "terPAST_LEDGER", "The transaction expired and can't be applied" },
|
{ terPAST_LEDGER, "terPAST_LEDGER", "The transaction expired and can't be applied" },
|
||||||
{ terPAST_SEQ, "terPAST_SEQ", "This sequence number has already past" },
|
{ terPAST_SEQ, "terPAST_SEQ", "This sequence number has already past" },
|
||||||
@@ -452,7 +452,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
TransactionEngineParams params, Ledger::pointer ledger)
|
TransactionEngineParams params, Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
Log(lsTRACE) << "applyTransaction>";
|
Log(lsTRACE) << "applyTransaction>";
|
||||||
mLedger = ledger;
|
mLedger = ledger;
|
||||||
|
mLedgerParentCloseTime = mLedger->getParentCloseTimeNC();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (1)
|
if (1)
|
||||||
@@ -536,10 +537,9 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
case ttACCOUNT_SET:
|
case ttACCOUNT_SET:
|
||||||
case ttCREDIT_SET:
|
case ttCREDIT_SET:
|
||||||
case ttINVOICE:
|
case ttINVOICE:
|
||||||
case ttOFFER:
|
case ttOFFER_CREATE:
|
||||||
case ttOFFER_CANCEL:
|
case ttOFFER_CANCEL:
|
||||||
case ttPASSWORD_FUND:
|
case ttPASSWORD_FUND:
|
||||||
case ttTRANSIT_SET:
|
|
||||||
case ttWALLET_ADD:
|
case ttWALLET_ADD:
|
||||||
nothing();
|
nothing();
|
||||||
break;
|
break;
|
||||||
@@ -797,8 +797,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
result = doInvoice(txn, accounts);
|
result = doInvoice(txn, accounts);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ttOFFER:
|
case ttOFFER_CREATE:
|
||||||
result = doOffer(txn, accounts, srcAccountID);
|
result = doOfferCreate(txn, accounts, srcAccountID);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ttOFFER_CANCEL:
|
case ttOFFER_CANCEL:
|
||||||
@@ -821,10 +821,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
result = doPayment(txn, accounts, srcAccountID);
|
result = doPayment(txn, accounts, srcAccountID);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ttTRANSIT_SET:
|
|
||||||
result = doTransitSet(txn, accounts);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ttWALLET_ADD:
|
case ttWALLET_ADD:
|
||||||
result = doWalletAdd(txn, accounts);
|
result = doWalletAdd(txn, accounts);
|
||||||
break;
|
break;
|
||||||
@@ -1549,125 +1545,6 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
|||||||
return terBAD_RIPPLE;
|
return terBAD_RIPPLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector<AffectedAccount>&)
|
|
||||||
{
|
|
||||||
std::cerr << "doTransitSet>" << std::endl;
|
|
||||||
#if 0
|
|
||||||
SLE::pointer sleSrc = accounts[0].second;
|
|
||||||
|
|
||||||
bool bTxnTransitRate = st->getIFieldPresent(sfTransitRate);
|
|
||||||
bool bTxnTransitStart = st->getIFieldPresent(sfTransitStart);
|
|
||||||
bool bTxnTransitExpire = st->getIFieldPresent(sfTransitExpire);
|
|
||||||
uint32 uTxnTransitRate = bTxnTransitRate ? st->getIFieldU32(sfTransitRate) : 0;
|
|
||||||
uint32 uTxnTransitStart = bTxnTransitStart ? st->getIFieldU32(sfTransitStart) : 0;
|
|
||||||
uint32 uTxnTransitExpire = bTxnTransitExpire ? st->getIFieldU32(sfTransitExpire) : 0;
|
|
||||||
|
|
||||||
bool bActTransitRate = sleSrc->getIFieldPresent(sfTransitRate);
|
|
||||||
bool bActTransitExpire = sleSrc->getIFieldPresent(sfTransitExpire);
|
|
||||||
bool bActNextTransitRate = sleSrc->getIFieldPresent(sfNextTransitRate);
|
|
||||||
bool bActNextTransitStart = sleSrc->getIFieldPresent(sfNextTransitStart);
|
|
||||||
bool bActNextTransitExpire = sleSrc->getIFieldPresent(sfNextTransitExpire);
|
|
||||||
uint32 uActTransitRate = bActTransitRate ? sleSrc->getIFieldU32(sfTransitRate) : 0;
|
|
||||||
uint32 uActTransitExpire = bActTransitExpire ? sleSrc->getIFieldU32(sfTransitExpire) : 0;
|
|
||||||
uint32 uActNextTransitRate = bActNextTransitRate ? sleSrc->getIFieldU32(sfNextTransitRate) : 0;
|
|
||||||
uint32 uActNextTransitStart = bActNextTransitStart ? sleSrc->getIFieldU32(sfNextTransitStart) : 0;
|
|
||||||
uint32 uActNextTransitExpire = bActNextTransitExpire ? sleSrc->getIFieldU32(sfNextTransitExpire) : 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Update view
|
|
||||||
//
|
|
||||||
|
|
||||||
bool bNoCurrent = !bActTransitRate;
|
|
||||||
bool bCurrentExpired =
|
|
||||||
bActTransitExpire // Current can expire
|
|
||||||
&& bActNextTransitStart // Have a replacement
|
|
||||||
&& uActTransitExpire <= uLedger; // Current is expired
|
|
||||||
|
|
||||||
// Replace current with next if need.
|
|
||||||
if (bNoCurrent // No current.
|
|
||||||
&& bActNextTransitRate // Have next.
|
|
||||||
&& uActNextTransitStart <= uLedger) // Next has started.
|
|
||||||
{
|
|
||||||
// Make next current.
|
|
||||||
uActTransitRate = uActNextTransitRate;
|
|
||||||
bActTransitExpire = bActNextTransitStart;
|
|
||||||
uActTransitExpire = uActNextTransitExpire;
|
|
||||||
|
|
||||||
// Remove next.
|
|
||||||
uActNextTransitStart = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Determine new transaction deposition.
|
|
||||||
//
|
|
||||||
|
|
||||||
bool bBetterThanCurrent =
|
|
||||||
!no current
|
|
||||||
|| (
|
|
||||||
Expires same or later than current
|
|
||||||
Start before or same as current
|
|
||||||
Fee same or less than current
|
|
||||||
)
|
|
||||||
|
|
||||||
bool bBetterThanNext =
|
|
||||||
!no next
|
|
||||||
|| (
|
|
||||||
Expires same or later than next
|
|
||||||
Start before or same as next
|
|
||||||
Fee same or less than next
|
|
||||||
)
|
|
||||||
|
|
||||||
bool bBetterThanBoth =
|
|
||||||
bBetterThanCurrent && bBetterThanNext
|
|
||||||
|
|
||||||
bool bCurrentBlocks =
|
|
||||||
!bBetterThanCurrent
|
|
||||||
&& overlaps with current
|
|
||||||
|
|
||||||
bool bNextBlocks =
|
|
||||||
!bBetterThanNext
|
|
||||||
&& overlaps with next
|
|
||||||
|
|
||||||
if (bBetterThanBoth)
|
|
||||||
{
|
|
||||||
// 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
|
|
||||||
{
|
|
||||||
// Error.
|
|
||||||
}
|
|
||||||
|
|
||||||
return tenTRANSIT_WORSE;
|
|
||||||
|
|
||||||
// Set current.
|
|
||||||
uDstTransitRate = uTxnTransitRate;
|
|
||||||
uDstTransitExpire = uTxnTransitExpire; // 0 for never expire.
|
|
||||||
|
|
||||||
// Set future.
|
|
||||||
uDstNextTransitRate = uTxnTransitRate;
|
|
||||||
uDstNextTransitStart = uTxnTransitStart;
|
|
||||||
uDstNextTransitExpire = uTxnTransitExpire; // 0 for never expire.
|
|
||||||
|
|
||||||
if (txn.getITFieldPresent(sfCurrency))
|
|
||||||
#endif
|
|
||||||
std::cerr << "doTransitSet<" << std::endl;
|
|
||||||
return tenINVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn,
|
TransactionEngineResult TransactionEngine::doWalletAdd(const SerializedTransaction& txn,
|
||||||
std::vector<AffectedAccount>& accounts)
|
std::vector<AffectedAccount>& accounts)
|
||||||
{
|
{
|
||||||
@@ -1736,10 +1613,168 @@ TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction
|
|||||||
return tenUNKNOWN;
|
return tenUNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX Needs to take offers.
|
#ifdef WORK_IN_PROGRESS
|
||||||
// XXX Use bPassive when taking.
|
// XXX Disallow loops in ripple paths
|
||||||
// XXX Also use quality when rippling a take.
|
// XXX Note accounts we visited so as not mark them found unfunded.
|
||||||
TransactionEngineResult TransactionEngine::doOffer(
|
// Before an offer is place into the ledger, fill as much as possible.
|
||||||
|
// XXX Also use quality fees when rippling a take.
|
||||||
|
// XXX Also be careful of taking own offer: delete old offer.
|
||||||
|
// --> uBookBase: the opposite order book.
|
||||||
|
TransactionEngineResult TransactionEngine::offerTake(
|
||||||
|
bool bPassive,
|
||||||
|
uint64 uTakeQuality,
|
||||||
|
const uint256& uBookBase,
|
||||||
|
const uint160& uTakerAccountID,
|
||||||
|
STAmount& saTakerGets, // With issuer.
|
||||||
|
STAmount& saTakerPays, // With issuer.
|
||||||
|
std::vector<SLE::pointer> vspUnfundedFound)
|
||||||
|
{
|
||||||
|
uint256 uTipIndex = uBookIndex;
|
||||||
|
bool bDone = true;
|
||||||
|
STAmount saSold = 0; // XXX Add in currency
|
||||||
|
STAmount saOffered = XXX amount to fill.
|
||||||
|
TransactionEngineResult terResult = tenUNKNOWN;
|
||||||
|
|
||||||
|
while (tenUNKNOWN == terResult)
|
||||||
|
{
|
||||||
|
uTipIndex = Ledger::indexNext(uTipIndex);
|
||||||
|
|
||||||
|
uint256 uTipBase;
|
||||||
|
uint64 uTipQuality = Ledger::indexQuality(uTipIndex, uTipBase);
|
||||||
|
|
||||||
|
if (saSold == saAmount)
|
||||||
|
{
|
||||||
|
// Filled order.
|
||||||
|
terResult = terSUCCESS;
|
||||||
|
}
|
||||||
|
else if (uTipBase != uBookBase
|
||||||
|
|| uTakeQuality < uTipQuality
|
||||||
|
|| (bPassive && uTakeQuality == uTipQuality))
|
||||||
|
{
|
||||||
|
// No qualifying offer.
|
||||||
|
|
||||||
|
terResult = terSUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Have an offer to consider.
|
||||||
|
LedgerStateParms qry = lepNONE;
|
||||||
|
SLE::pointer sleOffer = mLedger->getOffer(qry, uTipIndex);
|
||||||
|
|
||||||
|
assert(sleOffer);
|
||||||
|
if (!sleOffer)
|
||||||
|
{
|
||||||
|
// Missing ledger entry.
|
||||||
|
Log(lsINFO) << "offerTake: Missing offer node: " << uTipIndex.ToString();
|
||||||
|
|
||||||
|
terResult = terBAD_LEDGER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NewcoinAddress naOfferAccountID = sleOffer->getIValueFieldAccount(sfAccount);
|
||||||
|
STAmount saOfferTakerGets = sleOffer->getIValueFieldAmount(sfAmountOut);
|
||||||
|
|
||||||
|
if (naOfferAccountID == uTakerAccountID)
|
||||||
|
{
|
||||||
|
// Would take own offer. Consider it unfunded. Delete it.
|
||||||
|
|
||||||
|
vspUnfundedFound.push_back(sleOffer);
|
||||||
|
}
|
||||||
|
else if (sleOffer->getIFieldPresent(sfExpiration) && sleOffer->getIFieldU32(sfExpiration) <= prevLedgerClose)
|
||||||
|
{
|
||||||
|
// Offer is expired. Delete it.
|
||||||
|
|
||||||
|
vspUnfundedFound.push_back(sleOffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SLE::pointer sleOfferAccount;
|
||||||
|
SLE::pointer sleOfferRipplePays;
|
||||||
|
STAmount saOfferBalance;
|
||||||
|
|
||||||
|
if (saTakerGets.isNative())
|
||||||
|
{
|
||||||
|
// Handle getting stamps.
|
||||||
|
LedgerStateParms qry = lepNONE;
|
||||||
|
SLE::pointer sleOfferAccount = mLedger->getAccountRoot(qry, naOfferAccountID);
|
||||||
|
if (!sleOfferAccount)
|
||||||
|
{
|
||||||
|
Log(lsWARNING) << "offerTake: delay: can't receive stamps from non-existant account";
|
||||||
|
|
||||||
|
terResult = terNO_ACCOUNT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saOfferBalance = sleOfferAccount->getIValueFieldAmount(sfBalance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Handling getting ripple.
|
||||||
|
|
||||||
|
if (saTakerGets.getIssuer() == naOfferAccountID)
|
||||||
|
{
|
||||||
|
// Taker gets offer's IOUs from offerer. Always works
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sleOfferRipplePays = getRippleState(getRippleStateIndex(uSrcAccountID, saTakerGets.getIssuer(), saTakerGets.getCurrency()));
|
||||||
|
|
||||||
|
bool bSltD = uSrcAccountID < uIssuerOutID;
|
||||||
|
|
||||||
|
STAmount saSrcBalance = sleRippleState->getIValueFieldAmount(sfBalance);
|
||||||
|
if (bSltD)
|
||||||
|
saSrcBalance.negate(); // Put balance in low terms.
|
||||||
|
}
|
||||||
|
STAmount saSrcBalance = sleOfferAccount->getIValueFieldAmount(sfBalance);
|
||||||
|
|
||||||
|
if (saSrcBalance.isZero())
|
||||||
|
{
|
||||||
|
terResult = terUNFUNDED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
STAmount saTakerPaysCur = STAmount::getPay(saOfferTakerGets, saOfferTakerPays, saTakerWants);
|
||||||
|
STAmount saTakerGetsCur = STAmount::getClaimed(saOfferTakerGets, saOfferTakerPays, saTakerPays);
|
||||||
|
|
||||||
|
saTakerWants -= saTakerGetsCur;
|
||||||
|
|
||||||
|
sleOfferAccount->setIFieldAmount(sfBalance, saSrcBalance - saPaid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Handle getting IOUs.
|
||||||
|
else
|
||||||
|
|
||||||
|
if (saSrcBalance.isPositive())
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
== saOoffer is unfunded
|
||||||
|
else
|
||||||
|
figure out how much to convert
|
||||||
|
|
||||||
|
note to counter party how much taken
|
||||||
|
|
||||||
|
if took it all
|
||||||
|
deleteIt
|
||||||
|
else
|
||||||
|
makeChanges
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tenUNKNOWN == terResult ? terSUCCESS : terResult;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TransactionEngineResult TransactionEngine::doOfferCreate(
|
||||||
const SerializedTransaction& txn,
|
const SerializedTransaction& txn,
|
||||||
std::vector<AffectedAccount>& accounts,
|
std::vector<AffectedAccount>& accounts,
|
||||||
const uint160& uSrcAccountID)
|
const uint160& uSrcAccountID)
|
||||||
@@ -1748,8 +1783,8 @@ TransactionEngineResult TransactionEngine::doOffer(
|
|||||||
bool bPassive = !!(txFlags & tfPassive);
|
bool bPassive = !!(txFlags & tfPassive);
|
||||||
STAmount saAmountIn = txn.getITFieldAmount(sfAmountIn);
|
STAmount saAmountIn = txn.getITFieldAmount(sfAmountIn);
|
||||||
STAmount saAmountOut = txn.getITFieldAmount(sfAmountOut);
|
STAmount saAmountOut = txn.getITFieldAmount(sfAmountOut);
|
||||||
uint160 uIssuerIn = txn.getITFieldAccount(sfIssuerIn);
|
uint160 uIssuerInID = txn.getITFieldAccount(sfIssuerIn);
|
||||||
uint160 uIssuerOut = txn.getITFieldAccount(sfIssuerOut);
|
uint160 uIssuerOutID = txn.getITFieldAccount(sfIssuerOut);
|
||||||
uint32 uExpiration = txn.getITFieldU32(sfExpiration);
|
uint32 uExpiration = txn.getITFieldU32(sfExpiration);
|
||||||
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
|
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
|
||||||
uint32 uSequence = txn.getSequence();
|
uint32 uSequence = txn.getSequence();
|
||||||
@@ -1758,72 +1793,133 @@ TransactionEngineResult TransactionEngine::doOffer(
|
|||||||
SLE::pointer sleOffer = boost::make_shared<SerializedLedgerEntry>(ltOFFER);
|
SLE::pointer sleOffer = boost::make_shared<SerializedLedgerEntry>(ltOFFER);
|
||||||
|
|
||||||
uint256 uLedgerIndex = Ledger::getOfferIndex(uSrcAccountID, uSequence);
|
uint256 uLedgerIndex = Ledger::getOfferIndex(uSrcAccountID, uSequence);
|
||||||
Log(lsINFO) << "doOffer: Creating offer node: " << uLedgerIndex.ToString();
|
Log(lsINFO) << "doOfferCreate: Creating offer node: " << uLedgerIndex.ToString();
|
||||||
|
|
||||||
uint160 uCurrencyIn = saAmountIn.getCurrency();
|
uint160 uCurrencyIn = saAmountIn.getCurrency();
|
||||||
uint160 uCurrencyOut = saAmountOut.getCurrency();
|
uint160 uCurrencyOut = saAmountOut.getCurrency();
|
||||||
|
|
||||||
TransactionEngineResult terResult;
|
TransactionEngineResult terResult = terSUCCESS;
|
||||||
uint64 uOwnerNode; // Delete hint.
|
uint64 uOwnerNode; // Delete hint.
|
||||||
uint64 uOfferNode; // Delete hint.
|
uint64 uBookNode; // Delete hint.
|
||||||
// uint64 uBookNode; // Delete hint.
|
|
||||||
|
|
||||||
uint32 uPrevLedgerTime = 0; // XXX Need previous
|
uint32 uPrevLedgerTime = 0; // XXX Need previous
|
||||||
|
|
||||||
if (!bHaveExpiration || !uExpiration)
|
if (!bHaveExpiration || !uExpiration)
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Malformed offer: bad expiration";
|
Log(lsWARNING) << "doOfferCreate: Malformed offer: bad expiration";
|
||||||
|
|
||||||
terResult = tenBAD_EXPIRATION;
|
terResult = tenBAD_EXPIRATION;
|
||||||
}
|
}
|
||||||
else if (!bHaveExpiration || uPrevLedgerTime >= uExpiration)
|
else if (!bHaveExpiration || uPrevLedgerTime >= uExpiration)
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Expired transaction: offer expired";
|
Log(lsWARNING) << "doOfferCreate: Expired transaction: offer expired";
|
||||||
|
|
||||||
terResult = tenEXPIRED;
|
terResult = tenEXPIRED;
|
||||||
}
|
}
|
||||||
else if (saAmountIn.isNative() && saAmountOut.isNative())
|
else if (saAmountIn.isNative() && saAmountOut.isNative())
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Malformed offer: stamps for stamps";
|
Log(lsWARNING) << "doOfferCreate: Malformed offer: stamps for stamps";
|
||||||
|
|
||||||
terResult = tenBAD_OFFER;
|
terResult = tenBAD_OFFER;
|
||||||
}
|
}
|
||||||
else if (saAmountIn.isZero() || saAmountOut.isZero())
|
else if (saAmountIn.isZero() || saAmountOut.isZero())
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Malformed offer: bad amount";
|
Log(lsWARNING) << "doOfferCreate: Malformed offer: bad amount";
|
||||||
|
|
||||||
terResult = tenBAD_OFFER;
|
terResult = tenBAD_OFFER;
|
||||||
}
|
}
|
||||||
else if (uCurrencyIn == uCurrencyOut && uIssuerIn == uIssuerOut)
|
else if (uCurrencyIn == uCurrencyOut && uIssuerInID == uIssuerOutID)
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Malformed offer: no conversion";
|
Log(lsWARNING) << "doOfferCreate: Malformed offer: no conversion";
|
||||||
|
|
||||||
terResult = tenREDUNDANT;
|
terResult = tenREDUNDANT;
|
||||||
}
|
}
|
||||||
else if (uCurrencyIn.isZero() == uIssuerIn.isZero() && uCurrencyOut.isZero() == uIssuerOut.isZero())
|
else if (saAmountIn.isNative() != uIssuerInID.isZero() || saAmountOut.isNative() != uIssuerOutID.isZero())
|
||||||
{
|
{
|
||||||
Log(lsWARNING) << "doOffer: Malformed offer: bad issuer";
|
Log(lsWARNING) << "doOfferCreate: Malformed offer: bad issuer";
|
||||||
|
|
||||||
terResult = tenBAD_ISSUER;
|
terResult = tenBAD_ISSUER;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Make sure signer has funds.
|
||||||
|
SLE::pointer sleSrc = accounts[0].second;
|
||||||
|
STAmount saSrcBalance = sleSrc->getIValueFieldAmount(sfBalance);
|
||||||
|
|
||||||
// XXX check currencies and accounts
|
if (saAmountOut.isNative() && !saSrcBalance.isZero())
|
||||||
// XXX check funded
|
{
|
||||||
// XXX check output credit line exists
|
// Delivering stamps and has stamps.
|
||||||
// XXX when deleting a credit line, delete outstanding offers
|
nothing();
|
||||||
|
}
|
||||||
|
else if (uIssuerOutID == uSrcAccountID)
|
||||||
|
{
|
||||||
|
// Delivering self issued IOUs.
|
||||||
|
nothing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LedgerStateParms qry = lepNONE;
|
||||||
|
SLE::pointer sleRippleOut = mLedger->getRippleState(qry, Ledger::getRippleStateIndex(uSrcAccountID, uIssuerOutID, uCurrencyOut));
|
||||||
|
bool bSltD = uSrcAccountID < uIssuerOutID;
|
||||||
|
|
||||||
// XXX Only place the offer if a portion is not filled.
|
STAmount saSrcBalance = sleRippleOut->getIValueFieldAmount(sfBalance);
|
||||||
|
if (bSltD)
|
||||||
|
saSrcBalance.negate(); // Put balance in low terms.
|
||||||
|
|
||||||
if (terSUCCESS == terResult)
|
if (saSrcBalance.isPositive())
|
||||||
terResult = dirAdd(accounts, uOwnerNode, Ledger::getOfferDirIndex(uSrcAccountID), uLedgerIndex);
|
{
|
||||||
|
// Funded.
|
||||||
|
nothing();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log(lsWARNING) << "doOfferCreate: delay: offers must be funded";
|
||||||
|
|
||||||
|
terResult = terUNFUNDED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (terSUCCESS == terResult)
|
if (terSUCCESS == terResult)
|
||||||
{
|
{
|
||||||
terResult = dirAdd(accounts, uOfferNode,
|
LedgerStateParms qry = lepNONE;
|
||||||
Ledger::getQualityIndex(
|
SLE::pointer sleRippleIn = mLedger->getAccountRoot(qry, uIssuerInID);
|
||||||
Ledger::getBookBase(uCurrencyIn, uIssuerIn, uCurrencyOut, uIssuerOut),
|
if (!sleRippleIn)
|
||||||
STAmount::getRate(saAmountOut, saAmountIn)),
|
{
|
||||||
uLedgerIndex);
|
Log(lsWARNING) << "doOfferCreate: delay: can't receive IOUs from non-existant issuer";
|
||||||
|
|
||||||
|
terResult = terNO_ACCOUNT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
#ifdef WORK_IN_PROGRESS
|
||||||
|
terResult = offerTake(
|
||||||
|
bPassive,
|
||||||
|
STAmount::getRate(saAmountIn, saAmountOut),
|
||||||
|
Ledger::getBookBase(uCurrencyOut, uIssuerOutID, uCurrencyIn, uIssuerInID)
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// XXX Check if some portion of order was not complete.
|
||||||
|
|
||||||
|
if (terSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
// Add offer to owner's directory.
|
||||||
|
terResult = dirAdd(accounts, uOwnerNode, Ledger::getOwnerDirIndex(uSrcAccountID), uLedgerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terSUCCESS == terResult)
|
||||||
|
{
|
||||||
|
// Add offer to order book.
|
||||||
|
terResult = dirAdd(
|
||||||
|
accounts,
|
||||||
|
uBookNode,
|
||||||
|
Ledger::getQualityIndex(
|
||||||
|
Ledger::getBookBase(uCurrencyIn, uIssuerInID, uCurrencyOut, uIssuerOutID),
|
||||||
|
STAmount::getRate(saAmountOut, saAmountIn)),
|
||||||
|
uLedgerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (terSUCCESS == terResult)
|
if (terSUCCESS == terResult)
|
||||||
@@ -1835,7 +1931,7 @@ TransactionEngineResult TransactionEngine::doOffer(
|
|||||||
sleOffer->setIFieldAmount(sfAmountIn, saAmountIn);
|
sleOffer->setIFieldAmount(sfAmountIn, saAmountIn);
|
||||||
sleOffer->setIFieldAmount(sfAmountOut, saAmountOut);
|
sleOffer->setIFieldAmount(sfAmountOut, saAmountOut);
|
||||||
sleOffer->setIFieldU64(sfOwnerNode, uOwnerNode);
|
sleOffer->setIFieldU64(sfOwnerNode, uOwnerNode);
|
||||||
sleOffer->setIFieldU64(sfOfferNode, uOfferNode);
|
sleOffer->setIFieldU64(sfBookNode, uBookNode);
|
||||||
sleOffer->setIFieldU32(sfExpiration, uExpiration);
|
sleOffer->setIFieldU32(sfExpiration, uExpiration);
|
||||||
|
|
||||||
if (bPassive)
|
if (bPassive)
|
||||||
|
|||||||
@@ -140,6 +140,7 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
Ledger::pointer mDefaultLedger, mAlternateLedger;
|
Ledger::pointer mDefaultLedger, mAlternateLedger;
|
||||||
Ledger::pointer mLedger;
|
Ledger::pointer mLedger;
|
||||||
|
uint64 mLedgerParentCloseTime;
|
||||||
|
|
||||||
TransactionEngineResult doAccountSet(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doAccountSet(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
TransactionEngineResult doClaim(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doClaim(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
@@ -147,7 +148,7 @@ protected:
|
|||||||
const uint160& uSrcAccountID);
|
const uint160& uSrcAccountID);
|
||||||
TransactionEngineResult doDelete(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doDelete(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
TransactionEngineResult doInvoice(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doInvoice(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
TransactionEngineResult doOffer(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
|
TransactionEngineResult doOfferCreate(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
|
||||||
const uint160& uSrcAccountID);
|
const uint160& uSrcAccountID);
|
||||||
TransactionEngineResult doOfferCancel(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
|
TransactionEngineResult doOfferCancel(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
|
||||||
const uint160& uSrcAccountID);
|
const uint160& uSrcAccountID);
|
||||||
@@ -160,7 +161,6 @@ protected:
|
|||||||
const uint160& uSrcAccountID);
|
const uint160& uSrcAccountID);
|
||||||
TransactionEngineResult doStore(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doStore(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
TransactionEngineResult doTake(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doTake(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
TransactionEngineResult doTransitSet(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
|
||||||
TransactionEngineResult doWalletAdd(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
TransactionEngineResult doWalletAdd(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{
|
{
|
||||||
{ "AccountSet", ttACCOUNT_SET, {
|
{ "AccountSet", ttACCOUNT_SET, {
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 1 },
|
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
|
||||||
{ S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 2 },
|
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
||||||
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 4 },
|
{ S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 },
|
||||||
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 8 },
|
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
||||||
|
{ S_FIELD(Domain), STI_VL, SOE_IFFLAG, 16 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
@@ -53,7 +54,7 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ "Offer", ttOFFER, {
|
{ "OfferCreate", ttOFFER_CREATE, {
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
{ S_FIELD(AmountIn), STI_AMOUNT, SOE_REQUIRED, 0 },
|
{ S_FIELD(AmountIn), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
|
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||||
@@ -63,7 +64,7 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ "OfferCancel", ttOFFER, {
|
{ "OfferCancel", ttOFFER_CANCEL, {
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
{ S_FIELD(OfferSequence), STI_UINT32, SOE_REQUIRED, 0 },
|
{ S_FIELD(OfferSequence), STI_UINT32, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
|
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
|
||||||
@@ -98,15 +99,6 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ "TransitSet", ttTRANSIT_SET, {
|
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
|
||||||
{ S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 1 },
|
|
||||||
{ S_FIELD(TransitStart), STI_UINT32, SOE_IFFLAG, 2 },
|
|
||||||
{ S_FIELD(TransitExpire), 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 } }
|
|
||||||
},
|
|
||||||
{ "WalletAdd", ttWALLET_ADD, {
|
{ "WalletAdd", ttWALLET_ADD, {
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },
|
{ S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||||
|
|||||||
@@ -13,10 +13,9 @@ enum TransactionType
|
|||||||
ttPASSWORD_FUND = 4,
|
ttPASSWORD_FUND = 4,
|
||||||
ttPASSWORD_SET = 5,
|
ttPASSWORD_SET = 5,
|
||||||
ttNICKNAME_SET = 6,
|
ttNICKNAME_SET = 6,
|
||||||
ttOFFER = 7,
|
ttOFFER_CREATE = 7,
|
||||||
ttOFFER_CANCEL = 8,
|
ttOFFER_CANCEL = 8,
|
||||||
ttCREDIT_SET = 20,
|
ttCREDIT_SET = 20,
|
||||||
ttTRANSIT_SET = 21,
|
|
||||||
ttINVOICE = 10,
|
ttINVOICE = 10,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user