Work in progress on offers and ripple.

This commit is contained in:
Arthur Britto
2012-07-07 14:34:42 -07:00
parent 5cf06d45a0
commit 4b20162e7f
11 changed files with 447 additions and 77 deletions

View File

@@ -184,16 +184,26 @@ public:
static uint256 getNicknameIndex(const uint256& uNickname);
//
// Order book functions
//
// Order book dirs have a base so we can use next to step through them in quality order.
static uint256 getBookBase(const uint160& uCurrencyIn, const uint160& uAccountIn,
const uint160& uCurrencyOut, const uint160& uAccountOut);
//
// Offer functions
//
static uint160 getOfferBase(const uint160& currencyIn, const uint160& accountIn,
const uint160& currencyOut, const uint160& accountOut);
SLE::pointer getOffer(LedgerStateParms& parms, const uint256& uIndex);
SLE::pointer getOffer(LedgerStateParms& parms, const uint160& uAccountID, uint32 uSequence)
{ return getOffer(parms, getOfferIndex(uAccountID, uSequence)); }
static uint256 getOfferIndex(const uint160& offerBase, uint64 rate, int skip = 0);
static int getOfferSkip(const uint256& offerId);
static uint256 getOfferIndex(const uint160& uAccountID, uint32 uSequence);
static uint256 getOfferDirIndex(const uint160& uAccountID);
//
// Directory functions
@@ -205,7 +215,7 @@ public:
SLE::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
//
// Ripple functions
// Ripple functions : credit lines
//
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency);

View File

@@ -46,6 +46,18 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
{ "Offer", ltOFFER, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(AmountIn), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(OwnerNode), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(OfferNode), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
{ "RippleState", ltRIPPLE_STATE, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
@@ -53,7 +65,8 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(HighID), STI_ACCOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 },
{ S_FIELD(QualityIn), STI_UINT32, SOE_IFFLAG, 1 },
{ S_FIELD(QualityOut), STI_UINT32, SOE_IFFLAG, 2 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},

View File

@@ -7,37 +7,41 @@
enum LedgerEntryType
{
ltINVALID = -1,
ltACCOUNT_ROOT,
ltDIR_ROOT,
ltDIR_NODE,
ltGENERATOR_MAP,
ltRIPPLE_STATE,
ltNICKNAME
ltACCOUNT_ROOT = 'a',
ltDIR_ROOT = 'D',
ltDIR_NODE = 'd',
ltGENERATOR_MAP = 'g',
ltRIPPLE_STATE = 'r',
ltNICKNAME = 'n',
ltOFFER = 'o',
};
// Used as a prefix for computing ledger indexes (keys).
enum LedgerNameSpace
{
spaceAccount = 0,
spaceGenerator = 1,
spaceNickname = 2,
spaceRipple = 3,
spaceRippleDir = 4,
spaceOffer = 5,
spaceOfferDir = 6,
spaceBond = 7,
spaceInvoice = 8,
spaceMultiSig = 9,
spaceAccount = 'a',
spaceGenerator = 'g',
spaceNickname = 'n',
spaceRipple = 'r',
spaceRippleDir = 'R',
spaceOffer = 'o', // Entry for an offer.
spaceOfferDir = 'O', // Directory of an account's offers.
spaceBookDir = 'B', // Directory of order books.
spaceBond = 'b',
spaceInvoice = 'i',
};
enum LedgerSpecificFlags
{
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True if password set fee is spent.
// ltOFFER
lsfPassive = 0x00010000,
// ltRIPPLE_STATE
lsfLowIndexed = 0x00010000,
lsfHighIndexed = 0x00020000,
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True if password set fee is spent.
};
struct LedgerEntryFormat

View File

@@ -59,55 +59,47 @@ uint256 Ledger::getRippleDirIndex(const uint160& uAccountID)
return s.getSHA512Half();
}
uint160 Ledger::getOfferBase(const uint160& currencyIn, const uint160& accountIn,
const uint160& currencyOut, const uint160& accountOut)
uint256 Ledger::getBookBase(const uint160& uCurrencyIn, const uint160& uAccountIn,
const uint160& uCurrencyOut, const uint160& uAccountOut)
{
bool inNative = currencyIn.isZero();
bool outNative = currencyOut.isZero();
bool bInNative = uCurrencyIn.isZero();
bool bOutNative = uCurrencyOut.isZero();
if (inNative && outNative)
throw std::runtime_error("native to native offer");
assert(!bInNative || !bOutNative); // Stamps to stamps not allowed.
assert(bInNative == !uAccountIn.isZero()); // Make sure issuer is specified as needed.
assert(bOutNative == !uAccountOut.isZero()); // Make sure issuer is specified as needed.
assert(uCurrencyIn != uCurrencyOut || uAccountIn != uAccountOut); // Currencies or accounts must differ.
Serializer s(80);
Serializer s(82);
if (inNative)
{
if (!currencyIn) throw std::runtime_error("native currencies are untied");
s.add32(0); // prevent collisions by ensuring different lengths
}
else
{
if (!!currencyIn) throw std::runtime_error("national currencies must be tied");
s.add160(currencyIn);
s.add160(accountIn);
s.add16(spaceBookDir); // 2
s.add160(uCurrencyIn); // 20
s.add160(uCurrencyOut); // 20
s.add160(uAccountIn); // 20
s.add160(uAccountOut); // 20
return getDirIndex(s.getSHA512Half()); // Return with index 0.
}
if (outNative)
uint256 Ledger::getOfferIndex(const uint160& uAccountID, uint32 uSequence)
{
if (!currencyOut) throw std::runtime_error("native currencies are untied");
}
else
{
if (!!currencyOut) throw std::runtime_error("national currencies must be tied");
s.add160(currencyOut);
s.add160(accountOut);
}
return s.getRIPEMD160();
}
uint256 Ledger::getOfferIndex(const uint160& offerBase, uint64 rate, int skip)
{ // the node for an offer index
Serializer s;
s.add160(offerBase);
s.add64(rate);
s.add32(skip);
return s.get256(0);
s.add16(spaceOffer);
s.add160(uAccountID);
s.add32(uSequence);
return s.getSHA512Half();
}
int Ledger::getOfferSkip(const uint256& offerId)
{ // how far ahead we skip if an index node is full
return *offerId.begin();
uint256 Ledger::getOfferDirIndex(const uint160& uAccountID)
{
Serializer s;
s.add16(spaceOfferDir);
s.add160(uAccountID);
return s.getSHA512Half();
}
// vim:ts=4

View File

@@ -6,6 +6,8 @@
#include "utils.h"
#include "Log.h"
// XXX Use shared locks where possible?
LedgerStateParms Ledger::writeBack(LedgerStateParms parms, SLE::pointer entry)
{
ScopedLock l(mAccountStateMap->Lock());
@@ -112,6 +114,18 @@ SLE::pointer Ledger::getNickname(LedgerStateParms& parms, const uint256& uNickna
return getASNode(parms, uNickname, ltNICKNAME);
}
//
// Offer
//
SLE::pointer Ledger::getOffer(LedgerStateParms& parms, const uint256& uIndex)
{
ScopedLock l(mAccountStateMap->Lock());
return getASNode(parms, uIndex, ltOFFER);
}
//
// Ripple State
//

View File

@@ -44,7 +44,7 @@ enum SOE_Field
sfCurrencyOut,
sfDestination,
sfEmailHash,
sfExpireLedger,
sfExpiration,
sfExtensions,
sfFirstNode,
sfFlags,
@@ -56,6 +56,8 @@ enum SOE_Field
sfIdentifier,
sfIndexes,
sfInvoiceID,
sfIssuerIn,
sfIssuerOut,
sfLastNode,
sfLastReceive,
sfLastTxn,
@@ -72,9 +74,13 @@ enum SOE_Field
sfNextTransitRate,
sfNextTransitStart,
sfNickname,
sfOfferCurrency,
sfOfferNode,
sfOfferSequence,
sfOwnerNode,
sfPaths,
sfPubKey,
sfQualityIn,
sfQualityOut,
sfSendMax,
sfSequence,
sfSignature,

View File

@@ -108,7 +108,6 @@ public:
void resize(size_t n) { mData.resize(n); }
size_t capacity() const { return mData.capacity(); }
bool operator==(const std::vector<unsigned char>& v) { return v == mData; }
bool operator!=(const std::vector<unsigned char>& v) { return v != mData; }
bool operator==(const Serializer& v) { return v.mData == mData; }

View File

@@ -28,7 +28,10 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ tenBAD_AMOUNT, "tenBAD_AMOUNT", "Can only send positive amounts." },
{ tenBAD_AUTH_MASTER, "tenBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
{ tenBAD_CLAIM_ID, "tenBAD_CLAIM_ID", "Malformed." },
{ tenBAD_EXPIRATION, "tenBAD_EXPIRATION", "Malformed." },
{ tenBAD_GEN_AUTH, "tenBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tenBAD_OFFER, "tenBAD_OFFER", "Malformed." },
{ tenBAD_ISSUER, "tenBAD_ISSUER", "Malformed." },
{ tenBAD_RIPPLE, "tenBAD_RIPPLE", "Ledger prevents ripple from succeeding." },
{ tenBAD_SET_ID, "tenBAD_SET_ID", "Malformed." },
{ tenCLAIMED, "tenCLAIMED", "Can not claim a previously claimed account." },
@@ -36,6 +39,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ tenCREATEXNS, "tenCREATEXNS", "Can not specify non XNS for Create." },
{ tenDST_IS_SRC, "tenDST_IS_SRC", "Destination may not be source." },
{ tenDST_NEEDED, "tenDST_NEEDED", "Destination not specified." },
{ tenEXPIRED, "tenEXPIRED", "Won't add an expired offer." },
{ tenEXPLICITXNS, "tenEXPLICITXNS", "XNS is used by default, don't specify it." },
{ tenFAILED, "tenFAILED", "Something broke horribly" },
{ tenGEN_IN_USE, "tenGEN_IN_USE", "Generator already in use." },
@@ -61,6 +65,7 @@ bool transResultInfo(TransactionEngineResult terCode, std::string& strToken, std
{ 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_PATH, "terNO_PATH", "No path existed or met transaction/balance requirements" },
{ terOFFER_NOT_FOUND, "terOFFER_NOT_FOUND", "Can not cancel offer." },
{ terOVER_LIMIT, "terOVER_LIMIT", "Over limit." },
{ terPAST_LEDGER, "terPAST_LEDGER", "The transaction expired and can't be applied" },
{ terPAST_SEQ, "terPAST_SEQ", "This sequence number has already past" },
@@ -470,6 +475,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
case ttCREDIT_SET:
case ttINVOICE:
case ttOFFER:
case ttOFFER_CANCEL:
case ttPASSWORD_FUND:
case ttTRANSIT_SET:
case ttWALLET_ADD:
@@ -730,7 +736,11 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
break;
case ttOFFER:
result = doOffer(txn, accounts);
result = doOffer(txn, accounts, srcAccountID);
break;
case ttOFFER_CANCEL:
result = doOfferCancel(txn, accounts, srcAccountID);
break;
case ttNICKNAME_SET:
@@ -1117,6 +1127,146 @@ TransactionEngineResult TransactionEngine::doPasswordSet(const SerializedTransac
return result;
}
#ifdef WORK_IN_PROGRESS
TransactionEngineResult calcOfferFill(SAAmount& saSrc, paymentNode& pnSrc, paymentNode& pnDst)
{
TransactionEngineResult terResult;
if (!saSrc.isZero())
{
}
return bSuccess;
}
// Find offers to satisfy pnDst.
// --> pnDst.saWanted: currency and amount wanted
// --> pnSrc.saIOURedeem.mCurrency: use this before saIOUIssue, limit to use.
// --> pnSrc.saIOUIssue.mCurrency: use this after saIOURedeem, limit to use.
// <-- pnDst.saReceive
// <-- pnDst.saIOUForgive
// <-- pnDst.saIOUAccept
// <-- terResult : terSUCCESS = no error and if !bAllowPartial complelely satisfied wanted.
// <-> usOffersDeleteAlways:
// <-> usOffersDeleteOnSuccess:
TransactionEngineResult calcOfferFill(paymentNode& pnSrc, paymentNode& pnDst, bool bAllowPartial)
{
TransactionEngineResult terResult;
terResult = calcOfferFill(pnSrc.saIOURedeem, pnSrc, pnDst, bAllowPartial);
if (terSUCCESS == terResult)
{
terResult = calcOfferFill(pnSrc.saIOUIssue, pnSrc, pnDst, bAllowPartial)
}
if (terSUCCESS == terResult && !bAllowPartial)
{
STAmount saTotal = pnSrc.saIOURedeem;
saTotal += pnSrc.saIOUIssue;
if (saTotal != saWanted)
terResult = terINSUF_PATH;
}
return terResult;
}
// From the destination work towards the source calculating how much must be asked for.
// --> bAllowPartial: If false, can fail if can't meet requirements.
// <-- bSuccess: true=success, false=insufficient funds.
// <-> pnNodes:
// --> [end]saWanted.mAmount
// --> [all]saWanted.mCurrency
// --> [all]saAccount
// <-> [0]saWanted.mAmount : --> limit, <-- actual
bool calcPaymentReverse(std::vector<paymentNode>& pnNodes, bool bAllowPartial)
{
bool bDone = false;
bool bSuccess = false;
// path: dst .. src
while (!bDone)
{
if (cur->saWanted.isZero())
{
// Must want something.
terResult = terINVALID;
bDone = true;
}
else if (cur->saWanted.isNative())
{
if (prv->how == direct)
{
// Stamp transfer desired.
if (prv->prev())
{
// More entries before stamp transfer.
terResult = terINVALID;
bDone = true;
}
else if (prv->account->saBalance() >= cur->saWanted)
{
// Transfer stamps.
prv->saSend = cur->saWanted;
bDone = true;
bSuccess = true;
}
else
{
// Insufficient funds for transfer
bDone = true;
}
}
else
{
// Must convert to stamps via offer.
if (calcOfferFill(prv, cur, bAllowPartial))
{
}
else
{
bDone = false;
}
}
}
else
{
// Rippling.
}
}
}
// From the source work toward the destination calculate how much is transfered at each step and finally.
// <-> pnNodes:
// --> [0]saWanted.mAmount
// --> [all]saWanted.saSend
// --> [all]saWanted.IOURedeem
// --> [all]saWanted.IOUIssue
// --> [all]saAccount
bool calcPaymentForward(std::vector<paymentNode>& pnNodes)
{
cur = src;
if (!cur->saSend.isZero())
{
// Sending stamps - always final step.
assert(!cur->next);
nxt->saReceive = cur->saSend;
bDone = true;
}
else
{
// Rippling.
}
}
#endif
// XXX Need to audit for things like setting accountID not having memory.
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts,
@@ -1524,10 +1674,152 @@ TransactionEngineResult TransactionEngine::doInvoice(const SerializedTransaction
return tenUNKNOWN;
}
TransactionEngineResult TransactionEngine::doOffer(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
// XXX Needs to take offers.
// XXX Use bPassive when taking.
// XXX Also use quality when rippling a take.
TransactionEngineResult TransactionEngine::doOffer(
const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts,
const uint160& uSrcAccountID)
{
return tenUNKNOWN;
uint32 txFlags = txn.getFlags();
bool bPassive = !!(txFlags & tfPassive);
STAmount saAmountIn = txn.getITFieldAmount(sfAmountIn);
STAmount saAmountOut = txn.getITFieldAmount(sfAmountOut);
uint160 uIssuerIn = txn.getITFieldAccount(sfIssuerIn);
uint160 uIssuerOut = txn.getITFieldAccount(sfIssuerOut);
uint32 uExpiration = txn.getITFieldU32(sfExpiration);
bool bHaveExpiration = txn.getITFieldPresent(sfExpiration);
uint32 uSequence = txn.getSequence();
// LedgerStateParms qry = lepNONE;
SLE::pointer sleOffer = boost::make_shared<SerializedLedgerEntry>(ltOFFER);
uint256 uLedgerIndex = Ledger::getOfferIndex(uSrcAccountID, uSequence);
Log(lsINFO) << "doOffer: Creating offer node: " << uLedgerIndex.ToString();
uint160 uCurrencyIn = saAmountIn.getCurrency();
uint160 uCurrencyOut = saAmountOut.getCurrency();
TransactionEngineResult terResult;
uint64 uOwnerNode; // Delete hint.
uint64 uOfferNode; // Delete hint.
// uint64 uBookNode; // Delete hint.
uint32 uPrevLedgerTime = 0; // XXX Need previous
if (!bHaveExpiration || !uExpiration)
{
Log(lsWARNING) << "doOffer: Malformed offer: bad expiration";
terResult = tenBAD_EXPIRATION;
}
else if (!bHaveExpiration || uPrevLedgerTime >= uExpiration)
{
Log(lsWARNING) << "doOffer: Expired transaction: offer expired";
terResult = tenEXPIRED;
}
else if (saAmountIn.isNative() && saAmountOut.isNative())
{
Log(lsWARNING) << "doOffer: Malformed offer: stamps for stamps";
terResult = tenBAD_OFFER;
}
else if (saAmountIn.isZero() || saAmountOut.isZero())
{
Log(lsWARNING) << "doOffer: Malformed offer: bad amount";
terResult = tenBAD_OFFER;
}
else if (uCurrencyIn == uCurrencyOut && uIssuerIn == uIssuerOut)
{
Log(lsWARNING) << "doOffer: Malformed offer: no conversion";
terResult = tenREDUNDANT;
}
else if (uCurrencyIn.isZero() == uIssuerIn.isZero() && uCurrencyOut.isZero() == uIssuerOut.isZero())
{
Log(lsWARNING) << "doOffer: Malformed offer: bad issuer";
terResult = tenBAD_ISSUER;
}
// XXX check currencies and accounts
// XXX check funded
// XXX check output credit line exists
// XXX when deleting a credit line, delete outstanding offers
// XXX Only place the offer if a portion is not filled.
if (terSUCCESS == terResult)
terResult = dirAdd(accounts, uOwnerNode, Ledger::getOfferDirIndex(uSrcAccountID), uLedgerIndex);
if (terSUCCESS == terResult)
{
terResult = dirAdd(accounts, uOfferNode,
Ledger::getDirIndex(
Ledger::getBookBase(uCurrencyIn, uIssuerIn, uCurrencyOut, uIssuerOut),
STAmount::getRate(saAmountOut, saAmountIn)),
uLedgerIndex);
}
if (terSUCCESS == terResult)
{
sleOffer->setIndex(uLedgerIndex);
sleOffer->setIFieldAccount(sfAccount, uSrcAccountID);
sleOffer->setIFieldU32(sfSequence, uSequence);
sleOffer->setIFieldAmount(sfAmountIn, saAmountIn);
sleOffer->setIFieldAmount(sfAmountOut, saAmountOut);
sleOffer->setIFieldU64(sfOwnerNode, uOwnerNode);
sleOffer->setIFieldU64(sfOfferNode, uOfferNode);
sleOffer->setIFieldU32(sfExpiration, uExpiration);
if (bPassive)
sleOffer->setFlag(lsfPassive);
accounts.push_back(std::make_pair(taaCREATE, sleOffer));
}
return terResult;
}
TransactionEngineResult TransactionEngine::doOfferCancel(
const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts,
const uint160& uSrcAccountID)
{
uint32 uSequence = txn.getITFieldU32(sfSequence);
uint256 uLedgerIndex = Ledger::getOfferIndex(uSrcAccountID, uSequence);
LedgerStateParms qry = lepNONE;
SLE::pointer sleOffer = mLedger->getOffer(qry, uLedgerIndex);
TransactionEngineResult terResult;
if (sleOffer)
{
terResult = tenUNKNOWN;
#if 0
uint64 uOwnerNode = sleOffer->getIFieldU64(sfOwnerNode);
uint64 uOwnerNode = sleOffer->getIFieldU64(sfOfferNode);
terResult = dirDelete(accounts, uOwnerNode, ___, uLedgerIndex);
if (terSUCCESS == terResult)
{
terResult = dirDelete(accounts, uOfferNode, ___, uLedgerIndex);
}
#endif
accounts.push_back(std::make_pair(taaDELETE, sleOffer));
}
else
{
terResult = terOFFER_NOT_FOUND;
}
return terResult;
}
TransactionEngineResult TransactionEngine::doTake(const SerializedTransaction& txn,

View File

@@ -19,7 +19,10 @@ enum TransactionEngineResult
tenBAD_ADD_AUTH,
tenBAD_AMOUNT,
tenBAD_CLAIM_ID,
tenBAD_EXPIRATION,
tenBAD_GEN_AUTH,
tenBAD_ISSUER,
tenBAD_OFFER,
tenBAD_SET_ID,
tenCREATEXNS,
tenDST_IS_SRC,
@@ -33,6 +36,7 @@ enum TransactionEngineResult
tenBAD_AUTH_MASTER,
tenBAD_RIPPLE,
tenCREATED,
tenEXPIRED,
tenMSG_SET,
terALREADY,
@@ -62,6 +66,7 @@ enum TransactionEngineResult
terNO_DST,
terNO_LINE_NO_ZERO,
terNO_PATH,
terOFFER_NOT_FOUND,
terOVER_LIMIT,
terPAST_LEDGER,
terPAST_SEQ,
@@ -106,6 +111,29 @@ private:
const uint256& uBase, // Key of item.
const uint256& uLedgerIndex); // Item being deleted
#ifdef WORK_IN_PROGRESS
typedef struct {
STAmount saWanted; // What this node wants from upstream.
STAmount saIOURedeem; // What this node will redeem downstream.
STAmount saIOUIssue; // What this node will issue downstream.
STAmount saSend; // Amount of stamps this node will send.
STAmount saIOUForgive; // Amount of IOUs to forgive.
STAmount saIOUAccept; // Amount of IOUs to accept.
STAmount saRecieve; // Amount stamps to receive.
STAccount saAccount;
} paymentNode;
typedef struct {
boost::unordered_set<....> offersDeletedAlways;
boost::unordered_set<....> offersDeletedOnSuccess;
std::vector<paymentNode> vpnNodes;
bool bAllowPartial;
} paymentGroup;
#endif
TransactionEngineResult setAuthorized(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts, bool bMustSetGenerator);
protected:
@@ -118,7 +146,10 @@ protected:
const uint160& uSrcAccountID);
TransactionEngineResult doDelete(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 doOffer(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
const uint160& uSrcAccountID);
TransactionEngineResult doOfferCancel(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
const uint160& uSrcAccountID);
TransactionEngineResult doNicknameSet(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,
const uint160& uSrcAccountID);
TransactionEngineResult doPasswordFund(const SerializedTransaction& txn, std::vector<AffectedAccount>& accounts,

View File

@@ -59,8 +59,14 @@ TransactionFormat InnerTxnFormats[]=
{ S_FIELD(AmountOut), STI_AMOUNT, SOE_REQUIRED, 0 },
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 2 },
{ S_FIELD(ExpireLedger), STI_UINT32, SOE_IFFLAG, 4 },
{ S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 8 },
{ S_FIELD(Expiration), STI_UINT32, SOE_IFFLAG, 4 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
{ "OfferCancel", ttOFFER, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(OfferSequence), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},

View File

@@ -13,10 +13,11 @@ enum TransactionType
ttPASSWORD_FUND = 4,
ttPASSWORD_SET = 5,
ttNICKNAME_SET = 6,
ttOFFER = 7,
ttOFFER_CANCEL = 8,
ttCREDIT_SET = 20,
ttTRANSIT_SET = 21,
ttINVOICE = 10,
ttOFFER = 11,
};
struct TransactionFormat
@@ -39,6 +40,8 @@ const int TransactionMaxLen = 1048576;
const uint32 tfCreateAccount = 0x00010000;
const uint32 tfNoRippleDirect = 0x00020000;
const uint32 tfPassive = 0x00010000;
const uint32 tfUnsetEmailHash = 0x00010000;
const uint32 tfUnsetWalletLocator = 0x00020000;