diff --git a/package.json b/package.json index 18b461f0e..2d22eb117 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ripple-lib", - "version": "0.7.8", + "version": "0.7.9", "description": "Ripple JavaScript client library", "files": [ diff --git a/src/cpp/ripple/AccountSetTransactor.cpp b/src/cpp/ripple/AccountSetTransactor.cpp index 9ffa635e5..4e8c13834 100644 --- a/src/cpp/ripple/AccountSetTransactor.cpp +++ b/src/cpp/ripple/AccountSetTransactor.cpp @@ -44,7 +44,7 @@ TER AccountSetTransactor::doApply() uFlagsOut |= lsfRequireAuth; } - if (uTxFlags & tfOptionalAuth) + if ((uTxFlags & tfOptionalAuth) && isSetBit(uFlagsIn, lsfRequireAuth)) { cLog(lsINFO) << "AccountSet: Clear RequireAuth."; @@ -62,16 +62,16 @@ TER AccountSetTransactor::doApply() return temINVALID_FLAG; } - if (uTxFlags & tfRequireDestTag) + if ((uTxFlags & tfOptionalDestTag) && !isSetBit(uFlagsIn, lsfRequireDestTag)) { - cLog(lsINFO) << "AccountSet: Set RequireDestTag."; + cLog(lsINFO) << "AccountSet: Set lsfRequireDestTag."; uFlagsOut |= lsfRequireDestTag; } - if (uTxFlags & tfOptionalDestTag) + if ((uTxFlags & tfOptionalDestTag) && isSetBit(uFlagsIn, lsfRequireDestTag)) { - cLog(lsINFO) << "AccountSet: Clear RequireDestTag."; + cLog(lsINFO) << "AccountSet: Clear lsfRequireDestTag."; uFlagsOut &= ~lsfRequireDestTag; } @@ -79,6 +79,31 @@ TER AccountSetTransactor::doApply() if (uFlagsIn != uFlagsOut) mTxnAccount->setFieldU32(sfFlags, uFlagsOut); + // + // DisallowXRP + // + + if ((tfDisallowXRP|tfAllowXRP) == (uTxFlags & (tfDisallowXRP|tfAllowXRP))) + { + cLog(lsINFO) << "AccountSet: Malformed transaction: Contradictory flags set."; + + return temINVALID_FLAG; + } + + if ((uTxFlags & tfDisallowXRP) && !isSetBit(uFlagsIn, lsfDisallowXRP)) + { + cLog(lsINFO) << "AccountSet: Set lsfDisallowXRP."; + + uFlagsOut |= lsfDisallowXRP; + } + + if ((uTxFlags & tfAllowXRP) && isSetBit(uFlagsIn, lsfDisallowXRP)) + { + cLog(lsINFO) << "AccountSet: Clear lsfDisallowXRP."; + + uFlagsOut &= ~lsfDisallowXRP; + } + // // EmailHash // diff --git a/src/cpp/ripple/LedgerFormats.h b/src/cpp/ripple/LedgerFormats.h index 537f3f193..f9f0a737b 100644 --- a/src/cpp/ripple/LedgerFormats.h +++ b/src/cpp/ripple/LedgerFormats.h @@ -42,6 +42,7 @@ enum LedgerSpecificFlags lsfPasswordSpent = 0x00010000, // True, if password set fee is spent. lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments. lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs. + lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP. // ltOFFER lsfPassive = 0x00010000, diff --git a/src/cpp/ripple/PaymentTransactor.cpp b/src/cpp/ripple/PaymentTransactor.cpp index 65c4aedf3..f81832db9 100644 --- a/src/cpp/ripple/PaymentTransactor.cpp +++ b/src/cpp/ripple/PaymentTransactor.cpp @@ -146,7 +146,7 @@ TER PaymentTransactor::doApply() { cLog(lsINFO) << "Payment: Malformed transaction: DestinationTag required."; - return temDST_TAG_NEEDED; + return tefDST_TAG_NEEDED; } else { diff --git a/src/cpp/ripple/TransactionErr.cpp b/src/cpp/ripple/TransactionErr.cpp index 7df6880d4..bdd1dcee2 100644 --- a/src/cpp/ripple/TransactionErr.cpp +++ b/src/cpp/ripple/TransactionErr.cpp @@ -34,6 +34,7 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman) { tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." }, { tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." }, { tefCREATED, "tefCREATED", "Can't add an already created account." }, + { tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." }, { tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." }, { tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." }, { tefINTERNAL, "tefINTERNAL", "Internal error." }, @@ -71,7 +72,6 @@ bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman) { temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." }, { temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." }, { temDST_NEEDED, "temDST_NEEDED", "Destination not specified." }, - { temDST_TAG_NEEDED, "temDST_TAG_NEEDED", "Destination tag required." }, { temINVALID, "temINVALID", "The transaction is ill-formed." }, { temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." }, { temREDUNDANT, "temREDUNDANT", "Sends same currency to self." }, diff --git a/src/cpp/ripple/TransactionErr.h b/src/cpp/ripple/TransactionErr.h index 2d00c2f6a..2e18d5f16 100644 --- a/src/cpp/ripple/TransactionErr.h +++ b/src/cpp/ripple/TransactionErr.h @@ -51,7 +51,6 @@ enum TER // aka TransactionEngineResult temBAD_SEQUENCE, temDST_IS_SRC, temDST_NEEDED, - temDST_TAG_NEEDED, temINVALID, temINVALID_FLAG, temREDUNDANT, @@ -78,6 +77,7 @@ enum TER // aka TransactionEngineResult tefBAD_LEDGER, tefCLAIMED, tefCREATED, + tefDST_TAG_NEEDED, tefEXCEPTION, tefGEN_IN_USE, tefINTERNAL, diff --git a/src/cpp/ripple/TransactionFormats.h b/src/cpp/ripple/TransactionFormats.h index 7b285c73d..b7a5d079b 100644 --- a/src/cpp/ripple/TransactionFormats.h +++ b/src/cpp/ripple/TransactionFormats.h @@ -64,7 +64,11 @@ const uint32 tfRequireDestTag = 0x00010000; const uint32 tfOptionalDestTag = 0x00020000; const uint32 tfRequireAuth = 0x00040000; const uint32 tfOptionalAuth = 0x00080000; -const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag|tfRequireAuth|tfOptionalAuth); +const uint32 tfDisallowXRP = 0x00100000; +const uint32 tfAllowXRP = 0x00200000; +const uint32 tfAccountSetMask = ~(tfRequireDestTag|tfOptionalDestTag + |tfRequireAuth|tfOptionalAuth + |tfDisallowXRP|tfAllowXRP); // OfferCreate flags: const uint32 tfPassive = 0x00010000; diff --git a/src/cpp/ripple/TrustSetTransactor.cpp b/src/cpp/ripple/TrustSetTransactor.cpp index 8365fc1a6..55133bc11 100644 --- a/src/cpp/ripple/TrustSetTransactor.cpp +++ b/src/cpp/ripple/TrustSetTransactor.cpp @@ -17,7 +17,7 @@ TER TrustSetTransactor::doApply() const bool bHigh = mTxnAccountID > uDstAccountID; // true, iff current is high account. uint32 uQualityIn = bQualityIn ? mTxn.getFieldU32(sfQualityIn) : 0; - uint32 uQualityOut = bQualityIn ? mTxn.getFieldU32(sfQualityOut) : 0; + uint32 uQualityOut = bQualityOut ? mTxn.getFieldU32(sfQualityOut) : 0; if (bQualityIn && QUALITY_ONE == uQualityIn) uQualityIn = 0; diff --git a/src/js/amount.js b/src/js/amount.js index 3a6b2797e..01a65d48a 100644 --- a/src/js/amount.js +++ b/src/js/amount.js @@ -46,7 +46,7 @@ var Amount = function () { // integer : XRP // { 'value' : ..., 'currency' : ..., 'issuer' : ...} - this._value = new BigInteger(); // NaN for bad value. Always positive for non-XRP. + this._value = new BigInteger(); // NaN for bad value. Always positive. this._offset = 0; // Always 0 for XRP. this._is_native = true; // Default to XRP. Only valid if value is not NaN. this._is_negative = false; @@ -226,14 +226,6 @@ Amount.prototype.compareTo = function (v) { if (!this.is_comparable(v)) { result = Amount.NaN(); } - else if (this._is_native) { - result = this._value.compareTo(v._value); - - if (result > 1) - result = 1; - else if (result < -1) - result = -1; - } else if (this._is_negative !== v._is_negative) { result = this._is_negative ? -1 : 1; } @@ -242,15 +234,15 @@ Amount.prototype.compareTo = function (v) { ? 1 : v._value.equals(BigInteger.ZERO) ? 0 - : 1; + : -1; } else if (v._value.equals(BigInteger.ZERO)) { result = 1; } - else if (this._offset > v._offset) { + else if (!this._is_native && this._offset > v._offset) { result = this._is_negative ? -1 : 1; } - else if (this._offset < v._offset) { + else if (!this._is_native && this._offset < v._offset) { result = this._is_negative ? 1 : -1; } else { diff --git a/src/js/transaction.js b/src/js/transaction.js index 06189c6df..c83ad51da 100644 --- a/src/js/transaction.js +++ b/src/js/transaction.js @@ -116,6 +116,7 @@ Transaction.flags = { 'Passive' : 0x00010000, 'ImmediateOrCancel' : 0x00020000, 'FillOrKill' : 0x00040000, + 'Sell' : 0x00080000, }, 'Payment' : { @@ -575,6 +576,8 @@ Transaction.prototype.offer_cancel = function (src, sequence) { return this; }; +// Options: +// .set_flags() // --> expiration : Date or Number Transaction.prototype.offer_create = function (src, taker_pays, taker_gets, expiration) { this._secret = this._account_secret(src);