mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-27 14:35:52 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin into api2
This commit is contained in:
@@ -383,7 +383,7 @@ bool STAmount::setFullValue(const std::string& sAmount, const std::string& sCurr
|
|||||||
// Stamps not must have an issuer.
|
// Stamps not must have an issuer.
|
||||||
if (mIsNative && !mIssuer.isZero())
|
if (mIsNative && !mIssuer.isZero())
|
||||||
{
|
{
|
||||||
Log(lsINFO) << "Issuer specified for stamps: " << sIssuer;
|
Log(lsINFO) << "Issuer specified for XRP: " << sIssuer;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,27 +30,6 @@ static int initFields()
|
|||||||
{
|
{
|
||||||
sfTxnSignature.notSigningField(); sfTxnSignatures.notSigningField();
|
sfTxnSignature.notSigningField(); sfTxnSignatures.notSigningField();
|
||||||
sfSignature.notSigningField();
|
sfSignature.notSigningField();
|
||||||
|
|
||||||
sfHighQualityIn.setMeta(SFM_CHANGE); sfHighQualityOut.setMeta(SFM_CHANGE);
|
|
||||||
sfLowQualityIn.setMeta(SFM_CHANGE); sfLowQualityOut.setMeta(SFM_CHANGE);
|
|
||||||
|
|
||||||
sfLowLimit.setMeta(SFM_ALWAYS); sfHighLimit.setMeta(SFM_ALWAYS);
|
|
||||||
sfTakerPays.setMeta(SFM_ALWAYS); sfTakerGets.setMeta(SFM_ALWAYS);
|
|
||||||
sfQualityIn.setMeta(SFM_ALWAYS); sfQualityOut.setMeta(SFM_ALWAYS);
|
|
||||||
|
|
||||||
sfBalance.setMeta(SFM_ALWAYS);
|
|
||||||
|
|
||||||
sfPublicKey.setMeta(SFM_CHANGE); sfMessageKey.setMeta(SFM_CHANGE);
|
|
||||||
sfSigningPubKey.setMeta(SFM_CHANGE); sfAuthorizedKey.setMeta(SFM_CHANGE);
|
|
||||||
sfSigningAccounts.setMeta(SFM_CHANGE);
|
|
||||||
|
|
||||||
sfWalletLocator.setMeta(SFM_ALWAYS);
|
|
||||||
sfWalletSize.setMeta(SFM_ALWAYS);
|
|
||||||
sfNickname.setMeta(SFM_CHANGE);
|
|
||||||
sfAmount.setMeta(SFM_ALWAYS);
|
|
||||||
sfDomain.setMeta(SFM_CHANGE);
|
|
||||||
sfOwner.setMeta(SFM_ALWAYS);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static const int f = initFields();
|
static const int f = initFields();
|
||||||
@@ -60,6 +39,7 @@ SField::SField(SerializedTypeID tid, int fv) : fieldCode(FIELD_CODE(tid, fv)), f
|
|||||||
{ // call with the map mutex
|
{ // call with the map mutex
|
||||||
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv);
|
fieldName = lexical_cast_i(tid) + "/" + lexical_cast_i(fv);
|
||||||
codeToField[fieldCode] = this;
|
codeToField[fieldCode] = this;
|
||||||
|
assert((fv != 1) || ((tid != STI_ARRAY) && (tid!=STI_OBJECT)));
|
||||||
}
|
}
|
||||||
|
|
||||||
SField::ref SField::getField(int code)
|
SField::ref SField::getField(int code)
|
||||||
|
|||||||
@@ -33,14 +33,6 @@ enum SOE_Flags
|
|||||||
SOE_OPTIONAL = 1, // optional
|
SOE_OPTIONAL = 1, // optional
|
||||||
};
|
};
|
||||||
|
|
||||||
enum SF_Meta
|
|
||||||
{
|
|
||||||
SFM_NEVER = 0,
|
|
||||||
SFM_CHANGE = 1,
|
|
||||||
SFM_DELETE = 2,
|
|
||||||
SFM_ALWAYS = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
class SField
|
class SField
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -59,19 +51,17 @@ public:
|
|||||||
const SerializedTypeID fieldType; // STI_*
|
const SerializedTypeID fieldType; // STI_*
|
||||||
const int fieldValue; // Code number for protocol
|
const int fieldValue; // Code number for protocol
|
||||||
std::string fieldName;
|
std::string fieldName;
|
||||||
SF_Meta fieldMeta;
|
|
||||||
bool signingField;
|
bool signingField;
|
||||||
|
|
||||||
SField(int fc, SerializedTypeID tid, int fv, const char* fn) :
|
SField(int fc, SerializedTypeID tid, int fv, const char* fn) :
|
||||||
fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), fieldMeta(SFM_NEVER), signingField(true)
|
fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mapMutex);
|
boost::mutex::scoped_lock sl(mapMutex);
|
||||||
codeToField[fieldCode] = this;
|
codeToField[fieldCode] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SField(SerializedTypeID tid, int fv, const char *fn) :
|
SField(SerializedTypeID tid, int fv, const char *fn) :
|
||||||
fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn),
|
fieldCode(FIELD_CODE(tid, fv)), fieldType(tid), fieldValue(fv), fieldName(fn), signingField(true)
|
||||||
fieldMeta(SFM_NEVER), signingField(true)
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mapMutex);
|
boost::mutex::scoped_lock sl(mapMutex);
|
||||||
codeToField[fieldCode] = this;
|
codeToField[fieldCode] = this;
|
||||||
@@ -95,10 +85,6 @@ public:
|
|||||||
bool isBinary() const { return fieldValue < 256; }
|
bool isBinary() const { return fieldValue < 256; }
|
||||||
bool isDiscardable() const { return fieldValue > 256; }
|
bool isDiscardable() const { return fieldValue > 256; }
|
||||||
|
|
||||||
SF_Meta getMeta() const { return fieldMeta; }
|
|
||||||
bool shouldMetaDel() const { return (fieldMeta == SFM_DELETE) || (fieldMeta == SFM_ALWAYS); }
|
|
||||||
bool shouldMetaMod() const { return (fieldMeta == SFM_CHANGE) || (fieldMeta == SFM_ALWAYS); }
|
|
||||||
void setMeta(SF_Meta m) { fieldMeta = m; }
|
|
||||||
bool isSigningField() const { return signingField; }
|
bool isSigningField() const { return signingField; }
|
||||||
void notSigningField() { signingField = false; }
|
void notSigningField() { signingField = false; }
|
||||||
|
|
||||||
|
|||||||
@@ -17,13 +17,15 @@
|
|||||||
enum JobType
|
enum JobType
|
||||||
{ // must be in priority order, low to high
|
{ // must be in priority order, low to high
|
||||||
jtINVALID,
|
jtINVALID,
|
||||||
jtVALIDATION_ut,
|
jtVALIDATION_ut, // A validation from an untrusted source
|
||||||
jtTRANSACTION,
|
jtCLIENTOP_ut, // A client operation from a non-local/untrusted source
|
||||||
jtPROPOSAL_ut,
|
jtTRANSACTION, // A transaction received from the network
|
||||||
jtVALIDATION_t,
|
jtPROPOSAL_ut, // A proposal from an untrusted source
|
||||||
jtTRANSACTION_l,
|
jtCLIENTOP_t, // A client operation from a trusted source
|
||||||
jtPROPOSAL_t,
|
jtVALIDATION_t, // A validation from a trusted source
|
||||||
jtADMIN,
|
jtTRANSACTION_l, // A local transaction
|
||||||
|
jtPROPOSAL_t, // A proposal from a trusted source
|
||||||
|
jtADMIN, // An administrative operation
|
||||||
jtDEATH, // job of death, used internally
|
jtDEATH, // job of death, used internally
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -927,11 +927,6 @@ uint256 Ledger::getBookBase(const uint160& uTakerPaysCurrency, const uint160& uT
|
|||||||
bool bInNative = uTakerPaysCurrency.isZero();
|
bool bInNative = uTakerPaysCurrency.isZero();
|
||||||
bool bOutNative = uTakerGetsCurrency.isZero();
|
bool bOutNative = uTakerGetsCurrency.isZero();
|
||||||
|
|
||||||
assert(!bInNative || !bOutNative); // Stamps to stamps not allowed.
|
|
||||||
assert(bInNative == uTakerPaysIssuerID.isZero()); // Make sure issuer is specified as needed.
|
|
||||||
assert(bOutNative == uTakerGetsIssuerID.isZero()); // Make sure issuer is specified as needed.
|
|
||||||
assert(uTakerPaysCurrency != uTakerGetsCurrency || uTakerPaysIssuerID != uTakerGetsIssuerID); // Currencies or accounts must differ.
|
|
||||||
|
|
||||||
Serializer s(82);
|
Serializer s(82);
|
||||||
|
|
||||||
s.add16(spaceBookDir); // 2
|
s.add16(spaceBookDir); // 2
|
||||||
@@ -942,13 +937,18 @@ uint256 Ledger::getBookBase(const uint160& uTakerPaysCurrency, const uint160& uT
|
|||||||
|
|
||||||
uint256 uBaseIndex = getQualityIndex(s.getSHA512Half()); // Return with quality 0.
|
uint256 uBaseIndex = getQualityIndex(s.getSHA512Half()); // Return with quality 0.
|
||||||
|
|
||||||
Log(lsINFO) << str(boost::format("getBookBase(%s,%s,%s,%s) = %s")
|
cLog(lsDEBUG) << boost::str(boost::format("getBookBase(%s,%s,%s,%s) = %s")
|
||||||
% STAmount::createHumanCurrency(uTakerPaysCurrency)
|
% STAmount::createHumanCurrency(uTakerPaysCurrency)
|
||||||
% RippleAddress::createHumanAccountID(uTakerPaysIssuerID)
|
% RippleAddress::createHumanAccountID(uTakerPaysIssuerID)
|
||||||
% STAmount::createHumanCurrency(uTakerGetsCurrency)
|
% STAmount::createHumanCurrency(uTakerGetsCurrency)
|
||||||
% RippleAddress::createHumanAccountID(uTakerGetsIssuerID)
|
% RippleAddress::createHumanAccountID(uTakerGetsIssuerID)
|
||||||
% uBaseIndex.ToString());
|
% uBaseIndex.ToString());
|
||||||
|
|
||||||
|
assert(!bInNative || !bOutNative); // XRP to XRP not allowed.
|
||||||
|
assert(bInNative == uTakerPaysIssuerID.isZero()); // Make sure issuer is specified as needed.
|
||||||
|
assert(bOutNative == uTakerGetsIssuerID.isZero()); // Make sure issuer is specified as needed.
|
||||||
|
assert(uTakerPaysCurrency != uTakerGetsCurrency || uTakerPaysIssuerID != uTakerGetsIssuerID); // Currencies or accounts must differ.
|
||||||
|
|
||||||
return uBaseIndex;
|
return uBaseIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@ bool LCTransaction::updateVote(int percentTime, bool proposing)
|
|||||||
|
|
||||||
LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previousLedger, uint32 closeTime)
|
LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previousLedger, uint32 closeTime)
|
||||||
: mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger),
|
: mState(lcsPRE_CLOSE), mCloseTime(closeTime), mPrevLedgerHash(prevLCLHash), mPreviousLedger(previousLedger),
|
||||||
mValPublic(theConfig.VALIDATION_PUB), mValPrivate(theConfig.VALIDATION_PRIV),
|
mValPublic(theConfig.VALIDATION_PUB), mValPrivate(theConfig.VALIDATION_PRIV), mConsensusFail(false),
|
||||||
mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false),
|
mCurrentMSeconds(0), mClosePercent(0), mHaveCloseTimeConsensus(false),
|
||||||
mConsensusStartTime(boost::posix_time::microsec_clock::universal_time())
|
mConsensusStartTime(boost::posix_time::microsec_clock::universal_time())
|
||||||
{
|
{
|
||||||
@@ -305,6 +305,36 @@ LedgerConsensus::LedgerConsensus(const uint256& prevLCLHash, Ledger::ref previou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LedgerConsensus::checkOurValidation()
|
||||||
|
{ // This only covers some cases - Fix for the case where we can't ever acquire the consensus ledger
|
||||||
|
if (!mHaveCorrectLCL || !mValPublic.isValid() || !mValPrivate.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
SerializedValidation::pointer lastVal = theApp->getOPs().getLastValidation();
|
||||||
|
if (lastVal)
|
||||||
|
{
|
||||||
|
if (lastVal->getFieldU32(sfLedgerSequence) == mPreviousLedger->getLedgerSeq())
|
||||||
|
return;
|
||||||
|
if (lastVal->getLedgerHash() == mPrevLedgerHash)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 signingHash;
|
||||||
|
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
|
||||||
|
(mPreviousLedger->getHash(), theApp->getOPs().getValidationTimeNC(), mValPublic, false);
|
||||||
|
v->setTrusted();
|
||||||
|
v->sign(signingHash, mValPrivate);
|
||||||
|
theApp->isNew(signingHash);
|
||||||
|
theApp->getValidations().addValidation(v);
|
||||||
|
std::vector<unsigned char> validation = v->getSigned();
|
||||||
|
ripple::TMValidation val;
|
||||||
|
val.set_validation(&validation[0], validation.size());
|
||||||
|
theApp->getConnectionPool().relayMessage(NULL,
|
||||||
|
boost::make_shared<PackedMessage>(val, ripple::mtVALIDATION));
|
||||||
|
theApp->getOPs().setLastValidation(v);
|
||||||
|
cLog(lsWARNING) << "Sending partial validation";
|
||||||
|
}
|
||||||
|
|
||||||
void LedgerConsensus::checkLCL()
|
void LedgerConsensus::checkLCL()
|
||||||
{
|
{
|
||||||
uint256 netLgr = mPrevLedgerHash;
|
uint256 netLgr = mPrevLedgerHash;
|
||||||
@@ -575,12 +605,13 @@ void LedgerConsensus::statePreClose()
|
|||||||
|
|
||||||
void LedgerConsensus::closeLedger()
|
void LedgerConsensus::closeLedger()
|
||||||
{
|
{
|
||||||
mState = lcsESTABLISH;
|
checkOurValidation();
|
||||||
mConsensusStartTime = boost::posix_time::microsec_clock::universal_time();
|
mState = lcsESTABLISH;
|
||||||
mCloseTime = theApp->getOPs().getCloseTimeNC();
|
mConsensusStartTime = boost::posix_time::microsec_clock::universal_time();
|
||||||
theApp->getOPs().setLastCloseTime(mCloseTime);
|
mCloseTime = theApp->getOPs().getCloseTimeNC();
|
||||||
statusChange(ripple::neCLOSING_LEDGER, *mPreviousLedger);
|
theApp->getOPs().setLastCloseTime(mCloseTime);
|
||||||
takeInitialPosition(*theApp->getMasterLedger().closeLedger(true));
|
statusChange(ripple::neCLOSING_LEDGER, *mPreviousLedger);
|
||||||
|
takeInitialPosition(*theApp->getMasterLedger().closeLedger(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerConsensus::stateEstablish()
|
void LedgerConsensus::stateEstablish()
|
||||||
@@ -769,7 +800,7 @@ bool LedgerConsensus::haveConsensus(bool forReal)
|
|||||||
cLog(lsDEBUG) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
|
cLog(lsDEBUG) << "Checking for TX consensus: agree=" << agree << ", disagree=" << disagree;
|
||||||
|
|
||||||
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
|
return ContinuousLedgerTiming::haveConsensus(mPreviousProposers, agree + disagree, agree, currentValidations,
|
||||||
mPreviousMSeconds, mCurrentMSeconds, forReal);
|
mPreviousMSeconds, mCurrentMSeconds, forReal, mConsensusFail);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
|
SHAMap::pointer LedgerConsensus::getTransactionTree(const uint256& hash, bool doAcquire)
|
||||||
@@ -1193,15 +1224,17 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
|||||||
}
|
}
|
||||||
|
|
||||||
statusChange(ripple::neACCEPTED_LEDGER, *newLCL);
|
statusChange(ripple::neACCEPTED_LEDGER, *newLCL);
|
||||||
if (mValidating)
|
if (mValidating && !mConsensusFail)
|
||||||
{
|
{
|
||||||
uint256 signingHash;
|
uint256 signingHash;
|
||||||
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
|
SerializedValidation::pointer v = boost::make_shared<SerializedValidation>
|
||||||
(newLCLHash, theApp->getOPs().getValidationTimeNC(), mValPublic, mValPrivate,
|
(newLCLHash, theApp->getOPs().getValidationTimeNC(), mValPublic, mProposing);
|
||||||
mProposing, boost::ref(signingHash));
|
v->setFieldU32(sfLedgerSequence, newLCL->getLedgerSeq());
|
||||||
|
v->sign(signingHash, mValPrivate);
|
||||||
v->setTrusted();
|
v->setTrusted();
|
||||||
theApp->isNew(signingHash); // suppress it if we receive it
|
theApp->isNew(signingHash); // suppress it if we receive it
|
||||||
theApp->getValidations().addValidation(v);
|
theApp->getValidations().addValidation(v);
|
||||||
|
theApp->getOPs().setLastValidation(v);
|
||||||
std::vector<unsigned char> validation = v->getSigned();
|
std::vector<unsigned char> validation = v->getSigned();
|
||||||
ripple::TMValidation val;
|
ripple::TMValidation val;
|
||||||
val.set_validation(&validation[0], validation.size());
|
val.set_validation(&validation[0], validation.size());
|
||||||
@@ -1238,7 +1271,7 @@ void LedgerConsensus::accept(SHAMap::ref set)
|
|||||||
cLog(lsINFO) << "Applying transactions from current ledger";
|
cLog(lsINFO) << "Applying transactions from current ledger";
|
||||||
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, newLCL,
|
applyTransactions(theApp->getMasterLedger().getCurrentLedger()->peekTransactionMap(), newOL, newLCL,
|
||||||
failedTransactions, true);
|
failedTransactions, true);
|
||||||
theApp->getMasterLedger().pushLedger(newLCL, newOL, true);
|
theApp->getMasterLedger().pushLedger(newLCL, newOL, !mConsensusFail);
|
||||||
mNewLedgerHash = newLCL->getHash();
|
mNewLedgerHash = newLCL->getHash();
|
||||||
mState = lcsACCEPTED;
|
mState = lcsACCEPTED;
|
||||||
sl.unlock();
|
sl.unlock();
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ protected:
|
|||||||
LedgerAcquire::pointer mAcquiringLedger;
|
LedgerAcquire::pointer mAcquiringLedger;
|
||||||
LedgerProposal::pointer mOurPosition;
|
LedgerProposal::pointer mOurPosition;
|
||||||
RippleAddress mValPublic, mValPrivate;
|
RippleAddress mValPublic, mValPrivate;
|
||||||
bool mProposing, mValidating, mHaveCorrectLCL;
|
bool mProposing, mValidating, mHaveCorrectLCL, mConsensusFail;
|
||||||
|
|
||||||
int mCurrentMSeconds, mClosePercent, mCloseResolution;
|
int mCurrentMSeconds, mClosePercent, mCloseResolution;
|
||||||
bool mHaveCloseTimeConsensus;
|
bool mHaveCloseTimeConsensus;
|
||||||
@@ -148,6 +148,7 @@ protected:
|
|||||||
void playbackProposals();
|
void playbackProposals();
|
||||||
int getThreshold();
|
int getThreshold();
|
||||||
void closeLedger();
|
void closeLedger();
|
||||||
|
void checkOurValidation();
|
||||||
|
|
||||||
void beginAccept(bool synchronous);
|
void beginAccept(bool synchronous);
|
||||||
void endConsensus();
|
void endConsensus();
|
||||||
|
|||||||
@@ -394,22 +394,21 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
SLE::pointer origNode = mLedger->getSLE(it.first);
|
SLE::pointer origNode = mLedger->getSLE(it.first);
|
||||||
|
|
||||||
if (origNode && (origNode->getType() == ltDIR_NODE)) // No metadata for dir nodes
|
|
||||||
continue;
|
|
||||||
|
|
||||||
SLE::pointer curNode = it.second.mEntry;
|
SLE::pointer curNode = it.second.mEntry;
|
||||||
mSet.setAffectedNode(it.first, *type);
|
uint16 nodeType = curNode ? curNode->getFieldU16(sfLedgerEntryType) : origNode->getFieldU16(sfLedgerEntryType);
|
||||||
|
|
||||||
|
mSet.setAffectedNode(it.first, *type, nodeType);
|
||||||
|
|
||||||
if (type == &sfDeletedNode)
|
if (type == &sfDeletedNode)
|
||||||
{
|
{
|
||||||
assert(origNode);
|
assert(origNode);
|
||||||
|
assert(curNode);
|
||||||
threadOwners(origNode, mLedger, newMod);
|
threadOwners(origNode, mLedger, newMod);
|
||||||
|
|
||||||
STObject finals(sfFinalFields);
|
STObject finals(sfFinalFields);
|
||||||
BOOST_FOREACH(const SerializedType& obj, *curNode)
|
BOOST_FOREACH(const SerializedType& obj, *curNode)
|
||||||
{ // search the deleted node for values saved on delete
|
{ // save non-default values
|
||||||
if (obj.getFName().shouldMetaDel() && !obj.isDefault())
|
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType))
|
||||||
finals.addObject(obj);
|
finals.addObject(obj);
|
||||||
}
|
}
|
||||||
if (!finals.empty())
|
if (!finals.empty())
|
||||||
@@ -421,7 +420,7 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
|
|||||||
STObject mods(sfPreviousFields);
|
STObject mods(sfPreviousFields);
|
||||||
BOOST_FOREACH(const SerializedType& obj, *origNode)
|
BOOST_FOREACH(const SerializedType& obj, *origNode)
|
||||||
{ // search the original node for values saved on modify
|
{ // search the original node for values saved on modify
|
||||||
if (obj.getFName().shouldMetaMod() && !obj.isDefault() && !curNode->hasMatchingEntry(obj))
|
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType) && !curNode->hasMatchingEntry(obj))
|
||||||
mods.addObject(obj);
|
mods.addObject(obj);
|
||||||
}
|
}
|
||||||
if (!mods.empty())
|
if (!mods.empty())
|
||||||
@@ -432,6 +431,15 @@ void LedgerEntrySet::calcRawMeta(Serializer& s, TER result)
|
|||||||
{
|
{
|
||||||
assert(!origNode);
|
assert(!origNode);
|
||||||
threadOwners(curNode, mLedger, newMod);
|
threadOwners(curNode, mLedger, newMod);
|
||||||
|
|
||||||
|
STObject news(sfNewFields);
|
||||||
|
BOOST_FOREACH(const SerializedType& obj, *curNode)
|
||||||
|
{ // save non-default values
|
||||||
|
if (!obj.isDefault() && (obj.getFName() != sfLedgerEntryType))
|
||||||
|
news.addObject(obj);
|
||||||
|
}
|
||||||
|
if (!news.empty())
|
||||||
|
mSet.getAffectedNode(it.first, *type).addObject(news);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type == &sfCreatedNode) || (type == &sfModifiedNode))
|
if ((type == &sfCreatedNode) || (type == &sfModifiedNode))
|
||||||
|
|||||||
@@ -63,7 +63,8 @@ bool ContinuousLedgerTiming::haveConsensus(
|
|||||||
int currentFinished, // proposers who have validated a ledger after this one
|
int currentFinished, // proposers who have validated a ledger after this one
|
||||||
int previousAgreeTime, // how long it took to agree on the last ledger
|
int previousAgreeTime, // how long it took to agree on the last ledger
|
||||||
int currentAgreeTime, // how long we've been trying to agree
|
int currentAgreeTime, // how long we've been trying to agree
|
||||||
bool forReal) // deciding whether to stop consensus process
|
bool forReal, // deciding whether to stop consensus process
|
||||||
|
bool& failed) // we can't reach a consensus
|
||||||
{
|
{
|
||||||
cLog(lsTRACE) << boost::str(boost::format("CLC::haveConsensus: prop=%d/%d agree=%d validated=%d time=%d/%d%s") %
|
cLog(lsTRACE) << boost::str(boost::format("CLC::haveConsensus: prop=%d/%d agree=%d validated=%d time=%d/%d%s") %
|
||||||
currentProposers % previousProposers % currentAgree % currentFinished % currentAgreeTime % previousAgreeTime %
|
currentProposers % previousProposers % currentAgree % currentFinished % currentAgreeTime % previousAgreeTime %
|
||||||
@@ -85,13 +86,15 @@ bool ContinuousLedgerTiming::haveConsensus(
|
|||||||
if (((currentAgree * 100 + 100) / (currentProposers + 1)) > 80)
|
if (((currentAgree * 100 + 100) / (currentProposers + 1)) > 80)
|
||||||
{
|
{
|
||||||
tLog(forReal, lsINFO) << "normal consensus";
|
tLog(forReal, lsINFO) << "normal consensus";
|
||||||
|
failed = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If 50% of the nodes on your UNL have moved on, you should declare consensus
|
// If 80% of the nodes on your UNL have moved on, you should declare consensus
|
||||||
if (((currentFinished * 100) / (currentProposers + 1)) > 50)
|
if (((currentFinished * 100) / (currentProposers + 1)) > 80)
|
||||||
{
|
{
|
||||||
tLog(forReal, lsWARNING) << "We see no consensus, but 50% of nodes have moved on";
|
tLog(forReal, lsWARNING) << "We see no consensus, but 80% of nodes have moved on";
|
||||||
|
failed = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
int previousProposers, int currentProposers,
|
int previousProposers, int currentProposers,
|
||||||
int currentAgree, int currentClosed,
|
int currentAgree, int currentClosed,
|
||||||
int previousAgreeTime, int currentAgreeTime,
|
int previousAgreeTime, int currentAgreeTime,
|
||||||
bool forReal);
|
bool forReal, bool& failed);
|
||||||
|
|
||||||
static int getNextLedgerTimeResolution(int previousResolution, bool previousAgree, int ledgerSeq);
|
static int getNextLedgerTimeResolution(int previousResolution, bool previousAgree, int ledgerSeq);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1168,11 +1168,10 @@ std::map<RippleAddress,bool> NetworkOPs::getAffectedAccounts(const SerializedTra
|
|||||||
const STAccount* sa = dynamic_cast<const STAccount*>(&it);
|
const STAccount* sa = dynamic_cast<const STAccount*>(&it);
|
||||||
if (sa)
|
if (sa)
|
||||||
{
|
{
|
||||||
bool found = false;
|
|
||||||
RippleAddress na = sa->getValueNCA();
|
RippleAddress na = sa->getValueNCA();
|
||||||
accounts[na]=true;
|
accounts[na]=true;
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
if( it.getFName() == sfLimitAmount )
|
if( it.getFName() == sfLimitAmount )
|
||||||
{
|
{
|
||||||
const STAmount* amount = dynamic_cast<const STAmount*>(&it);
|
const STAmount* amount = dynamic_cast<const STAmount*>(&it);
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ protected:
|
|||||||
uint256 mLastCloseHash;
|
uint256 mLastCloseHash;
|
||||||
uint32 mLastCloseTime;
|
uint32 mLastCloseTime;
|
||||||
uint32 mLastValidationTime;
|
uint32 mLastValidationTime;
|
||||||
|
SerializedValidation::pointer mLastValidation;
|
||||||
|
|
||||||
|
|
||||||
// XXX Split into more locks.
|
// XXX Split into more locks.
|
||||||
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
|
boost::interprocess::interprocess_upgradable_mutex mMonitorLock;
|
||||||
@@ -131,8 +133,10 @@ public:
|
|||||||
Ledger::pointer getLedgerByHash(const uint256& hash) { return mLedgerMaster->getLedgerByHash(hash); }
|
Ledger::pointer getLedgerByHash(const uint256& hash) { return mLedgerMaster->getLedgerByHash(hash); }
|
||||||
Ledger::pointer getLedgerBySeq(const uint32 seq) { return mLedgerMaster->getLedgerBySeq(seq); }
|
Ledger::pointer getLedgerBySeq(const uint32 seq) { return mLedgerMaster->getLedgerBySeq(seq); }
|
||||||
|
|
||||||
uint256 getClosedLedgerHash()
|
uint256 getClosedLedgerHash() { return mLedgerMaster->getClosedLedger()->getHash(); }
|
||||||
{ return mLedgerMaster->getClosedLedger()->getHash(); }
|
|
||||||
|
SerializedValidation::ref getLastValidation() { return mLastValidation; }
|
||||||
|
void setLastValidation(SerializedValidation::ref v) { mLastValidation = v; }
|
||||||
|
|
||||||
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }
|
SLE::pointer getSLE(Ledger::pointer lpLedger, const uint256& uHash) { return lpLedger->getSLE(uHash); }
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,16 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include <boost/format.hpp>
|
||||||
|
|
||||||
#include <openssl/rand.h>
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
#include "Serializer.h"
|
#include "Serializer.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
SETUP_LOG();
|
||||||
|
|
||||||
const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
||||||
const int ProofOfWork::sMaxIterations(1 << 23);
|
const int ProofOfWork::sMaxIterations(1 << 23);
|
||||||
@@ -16,26 +23,35 @@ bool ProofOfWork::isValid() const
|
|||||||
|
|
||||||
uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations)
|
uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations)
|
||||||
{ // calculate the approximate number of hashes required to solve this proof of work
|
{ // calculate the approximate number of hashes required to solve this proof of work
|
||||||
if ((iterations > sMaxIterations) || (target < sMinTarget));
|
if ((iterations > sMaxIterations) || (target < sMinTarget))
|
||||||
|
{
|
||||||
|
cLog(lsINFO) << "Iterations:" << iterations;
|
||||||
|
cLog(lsINFO) << "MaxIterat: " << sMaxIterations;
|
||||||
|
cLog(lsINFO) << "Target: " << target;
|
||||||
|
cLog(lsINFO) << "MinTarget: " << sMinTarget;
|
||||||
throw std::runtime_error("invalid proof of work target/iteration");
|
throw std::runtime_error("invalid proof of work target/iteration");
|
||||||
|
}
|
||||||
|
|
||||||
// more iterations means more hashes per iteration but also a larger final hash
|
// more iterations means more hashes per iteration but also a larger final hash
|
||||||
uint64 difficulty = iterations * (iterations / 4 + 1);
|
uint64 difficulty = iterations + (iterations / 4);
|
||||||
|
|
||||||
// Multiply the number of hashes needed by 16 for each leading zero in the hex difficulty
|
// Multiply the number of hashes needed by 256 for each leading zero byte in the difficulty
|
||||||
const unsigned char *ptr = target.begin();
|
const unsigned char *ptr = target.begin();
|
||||||
while (*ptr == 0)
|
while (*ptr == 0)
|
||||||
{
|
{
|
||||||
difficulty *= 16;
|
difficulty *= 256;
|
||||||
ptr++;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
difficulty = (difficulty * 256) / (*ptr + 1);
|
||||||
// If the first digit after a zero isn't an F, multiply
|
|
||||||
difficulty *= (16 - *ptr);
|
|
||||||
|
|
||||||
return difficulty;
|
return difficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint256 getSHA512Half(const std::vector<uint256>& vec)
|
||||||
|
{
|
||||||
|
return Serializer::getSHA512Half(vec.front().begin(), vec.size() * (256 / 8));
|
||||||
|
}
|
||||||
|
|
||||||
uint256 ProofOfWork::solve(int maxIterations) const
|
uint256 ProofOfWork::solve(int maxIterations) const
|
||||||
{
|
{
|
||||||
if (!isValid())
|
if (!isValid())
|
||||||
@@ -44,23 +60,157 @@ uint256 ProofOfWork::solve(int maxIterations) const
|
|||||||
uint256 nonce;
|
uint256 nonce;
|
||||||
RAND_bytes(nonce.begin(), nonce.size());
|
RAND_bytes(nonce.begin(), nonce.size());
|
||||||
|
|
||||||
Serializer s1, s2;
|
std::vector<uint256> buf2;
|
||||||
std::vector<unsigned char> buf;
|
buf2.resize(mIterations);
|
||||||
buf.reserve((256 / 8) * mIterations);
|
|
||||||
|
|
||||||
while (maxIterations > 8)
|
std::vector<uint256> buf1;
|
||||||
|
buf1.resize(3);
|
||||||
|
buf1[0] = mChallenge;
|
||||||
|
|
||||||
|
while (maxIterations > 0)
|
||||||
{
|
{
|
||||||
s1.add256(mChallenge);
|
buf1[1] = nonce;
|
||||||
s1.add256(nonce);
|
buf1[2] = uint256();
|
||||||
// uint256 base = s1.getSHA512Half();
|
for (int i = (mIterations - 1); i >= 0; --i)
|
||||||
|
|
||||||
for (int i = 0; i < mIterations; ++i)
|
|
||||||
{
|
{
|
||||||
// WRITEME
|
buf1[2] = getSHA512Half(buf1);
|
||||||
|
buf2[i] = buf1[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
s1.erase();
|
if (getSHA512Half(buf2) <= mTarget)
|
||||||
nonce++;
|
return nonce;
|
||||||
|
|
||||||
|
++nonce;
|
||||||
|
--maxIterations;
|
||||||
}
|
}
|
||||||
return uint256();
|
return uint256();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ProofOfWork::checkSolution(const uint256& solution) const
|
||||||
|
{
|
||||||
|
if (mIterations > sMaxIterations)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<uint256> buf1;
|
||||||
|
buf1.push_back(mChallenge);
|
||||||
|
buf1.push_back(solution);
|
||||||
|
buf1.push_back(uint256());
|
||||||
|
|
||||||
|
std::vector<uint256> buf2;
|
||||||
|
buf2.resize(mIterations);
|
||||||
|
for (int i = (mIterations - 1); i >= 0; --i)
|
||||||
|
{
|
||||||
|
buf1[2] = getSHA512Half(buf1);
|
||||||
|
buf2[i] = buf1[2];
|
||||||
|
}
|
||||||
|
return getSHA512Half(buf2) <= mTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProofOfWorkGenerator::ProofOfWorkGenerator() :
|
||||||
|
mIterations(128),
|
||||||
|
mTarget("0003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"),
|
||||||
|
mLastDifficultyChange(time(NULL)),
|
||||||
|
mValidTime(180)
|
||||||
|
{
|
||||||
|
RAND_bytes(mSecret.begin(), mSecret.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
ProofOfWork ProofOfWorkGenerator::getProof()
|
||||||
|
{
|
||||||
|
// challenge - target - iterations - time - validator
|
||||||
|
static boost::format f("%s-%s-%d-%d");
|
||||||
|
|
||||||
|
int now = static_cast<int>(time(NULL) / 4);
|
||||||
|
|
||||||
|
uint256 challenge;
|
||||||
|
RAND_bytes(challenge.begin(), challenge.size());
|
||||||
|
|
||||||
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
|
|
||||||
|
std::string s = boost::str(f % challenge.GetHex() % mTarget.GetHex() % mIterations % now);
|
||||||
|
std::string c = mSecret.GetHex() + s;
|
||||||
|
s += "-" + Serializer::getSHA512Half(c).GetHex();
|
||||||
|
|
||||||
|
return ProofOfWork(s, mIterations, challenge, mTarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
POWResult ProofOfWorkGenerator::checkProof(const std::string& token, const uint256& solution)
|
||||||
|
{ // challenge - target - iterations - time - validator
|
||||||
|
|
||||||
|
std::vector<std::string> fields;
|
||||||
|
boost::split(fields, token, boost::algorithm::is_any_of("-"));
|
||||||
|
if (fields.size() != 5)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "PoW " << token << " is corrupt";
|
||||||
|
return powCORRUPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string v = mSecret.GetHex() + fields[0] + "-" + fields[1] + "-" + fields[2] + "-" + fields[3];
|
||||||
|
if (fields[4] != Serializer::getSHA512Half(v).GetHex())
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "PoW " << token << " has a bad token";
|
||||||
|
return powBADTOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 challenge, target;
|
||||||
|
challenge.SetHex(fields[0]);
|
||||||
|
target.SetHex(fields[1]);
|
||||||
|
|
||||||
|
time_t t = lexical_cast_s<time_t>(fields[3]);
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
|
if ((t * 4) > (now + mValidTime))
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "PoW " << token << " has expired";
|
||||||
|
return powEXPIRED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ProofOfWork pow(token, lexical_cast_s<int>(fields[2]), challenge, target);
|
||||||
|
if (!pow.checkSolution(solution))
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "PoW " << token << " has a bad nonce";
|
||||||
|
return powBADNONCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
|
if (!mSolvedChallenges.insert(powMap_vt(now, challenge)).second)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "PoW " << token << " has been reused";
|
||||||
|
return powREUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return powOK;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE(ProofOfWork_suite)
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE( ProofOfWork_test )
|
||||||
|
{
|
||||||
|
ProofOfWorkGenerator gen;
|
||||||
|
ProofOfWork pow = gen.getProof();
|
||||||
|
cLog(lsINFO) << "Estimated difficulty: " << pow.getDifficulty();
|
||||||
|
uint256 solution = pow.solve(16777216);
|
||||||
|
if (solution.isZero())
|
||||||
|
BOOST_FAIL("Unable to solve proof of work");
|
||||||
|
if (!pow.checkSolution(solution))
|
||||||
|
BOOST_FAIL("Solution did not check");
|
||||||
|
|
||||||
|
cLog(lsDEBUG) << "A bad nonce error is expected";
|
||||||
|
if (gen.checkProof(pow.getToken(), uint256()) != powBADNONCE)
|
||||||
|
BOOST_FAIL("Empty solution didn't show bad nonce");
|
||||||
|
if (gen.checkProof(pow.getToken(), solution) != powOK)
|
||||||
|
BOOST_FAIL("Solution did not check with issuer");
|
||||||
|
cLog(lsDEBUG) << "A reused nonce error is expected";
|
||||||
|
if (gen.checkProof(pow.getToken(), solution) != powREUSED)
|
||||||
|
BOOST_FAIL("Reuse solution not detected");
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -5,11 +5,21 @@
|
|||||||
|
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/bimap.hpp>
|
#include <boost/bimap.hpp>
|
||||||
#include <boost/bimap/set_of.hpp>
|
#include <boost/bimap/unordered_set_of.hpp>
|
||||||
#include <boost/bimap/multiset_of.hpp>
|
#include <boost/bimap/multiset_of.hpp>
|
||||||
|
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
|
|
||||||
|
enum POWResult
|
||||||
|
{
|
||||||
|
powOK = 0,
|
||||||
|
powREUSED = 1,
|
||||||
|
powBADNONCE = 2,
|
||||||
|
powBADTOKEN = 3,
|
||||||
|
powEXPIRED = 4,
|
||||||
|
powCORRUPT = 5,
|
||||||
|
};
|
||||||
|
|
||||||
class ProofOfWork
|
class ProofOfWork
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@@ -32,6 +42,9 @@ public:
|
|||||||
uint256 solve(int maxIterations) const;
|
uint256 solve(int maxIterations) const;
|
||||||
bool checkSolution(const uint256& solution) const;
|
bool checkSolution(const uint256& solution) const;
|
||||||
|
|
||||||
|
const std::string& getToken() const { return mToken; }
|
||||||
|
const uint256& getChallenge() const { return mChallenge; }
|
||||||
|
|
||||||
// approximate number of hashes needed to solve
|
// approximate number of hashes needed to solve
|
||||||
static uint64 getDifficulty(const uint256& target, int iterations);
|
static uint64 getDifficulty(const uint256& target, int iterations);
|
||||||
uint64 getDifficulty() const { return getDifficulty(mTarget, mIterations); }
|
uint64 getDifficulty() const { return getDifficulty(mTarget, mIterations); }
|
||||||
@@ -40,7 +53,7 @@ public:
|
|||||||
class ProofOfWorkGenerator
|
class ProofOfWorkGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::set_of<uint256> > powMap_t;
|
typedef boost::bimap< boost::bimaps::multiset_of<time_t>, boost::bimaps::unordered_set_of<uint256> > powMap_t;
|
||||||
typedef powMap_t::value_type powMap_vt;
|
typedef powMap_t::value_type powMap_vt;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -48,19 +61,23 @@ protected:
|
|||||||
int mIterations;
|
int mIterations;
|
||||||
uint256 mTarget;
|
uint256 mTarget;
|
||||||
time_t mLastDifficultyChange;
|
time_t mLastDifficultyChange;
|
||||||
|
int mValidTime;
|
||||||
|
|
||||||
powMap_t mSolvedChallenges;
|
powMap_t mSolvedChallenges;
|
||||||
boost::mutex mLock;
|
boost::mutex mLock;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ProofOfWorkGenerator(const uint256& secret);
|
ProofOfWorkGenerator();
|
||||||
|
|
||||||
ProofOfWork getProof();
|
ProofOfWork getProof();
|
||||||
bool checkProof(const std::string& token, const uint256& solution);
|
POWResult checkProof(const std::string& token, const uint256& solution);
|
||||||
|
uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); }
|
||||||
|
|
||||||
void loadHigh();
|
void loadHigh();
|
||||||
void loadLow();
|
void loadLow();
|
||||||
uint64 getDifficulty() { return ProofOfWork::getDifficulty(mTarget, mIterations); }
|
void sweep(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
class RPCCommands
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
HttpReply& handleCommand();
|
|
||||||
};
|
|
||||||
@@ -1312,13 +1312,15 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
|
|||||||
cLog(lsTRACE) << "RPC:" << command;
|
cLog(lsTRACE) << "RPC:" << command;
|
||||||
cLog(lsTRACE) << "RPC params:" << params;
|
cLog(lsTRACE) << "RPC params:" << params;
|
||||||
|
|
||||||
|
mRole = role;
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
const char* pCommand;
|
const char* pCommand;
|
||||||
doFuncPtr dfpFunc;
|
doFuncPtr dfpFunc;
|
||||||
int iMinParams;
|
int iMinParams;
|
||||||
int iMaxParams;
|
int iMaxParams;
|
||||||
bool mAdminRequired;
|
bool bAdminRequired;
|
||||||
bool mEvented;
|
bool bEvented;
|
||||||
unsigned int iOptions;
|
unsigned int iOptions;
|
||||||
} commandsA[] = {
|
} commandsA[] = {
|
||||||
// Request-response methods
|
// Request-response methods
|
||||||
@@ -1335,6 +1337,7 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
|
|||||||
{ "ledger_closed", &RPCHandler::doLedgerClosed, 0, 0, false, false, optClosed },
|
{ "ledger_closed", &RPCHandler::doLedgerClosed, 0, 0, false, false, optClosed },
|
||||||
{ "ledger_current", &RPCHandler::doLedgerCurrent, 0, 0, false, false, optCurrent },
|
{ "ledger_current", &RPCHandler::doLedgerCurrent, 0, 0, false, false, optCurrent },
|
||||||
{ "ledger_entry", &RPCHandler::doLedgerEntry, -1, -1, false, false, optCurrent },
|
{ "ledger_entry", &RPCHandler::doLedgerEntry, -1, -1, false, false, optCurrent },
|
||||||
|
{ "ledger_header", &RPCHandler::doLedgerHeader, -1, -1, false, false, optCurrent },
|
||||||
{ "log_level", &RPCHandler::doLogLevel, 0, 2, true },
|
{ "log_level", &RPCHandler::doLogLevel, 0, 2, true },
|
||||||
{ "logrotate", &RPCHandler::doLogRotate, 0, 0, true },
|
{ "logrotate", &RPCHandler::doLogRotate, 0, 0, true },
|
||||||
{ "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, false, optCurrent },
|
{ "nickname_info", &RPCHandler::doNicknameInfo, 1, 1, false, false, optCurrent },
|
||||||
@@ -1380,11 +1383,11 @@ Json::Value RPCHandler::doCommand(const std::string& command, Json::Value& param
|
|||||||
{
|
{
|
||||||
return rpcError(rpcUNKNOWN_COMMAND);
|
return rpcError(rpcUNKNOWN_COMMAND);
|
||||||
}
|
}
|
||||||
else if (commandsA[i].mAdminRequired && role != ADMIN)
|
else if (commandsA[i].bAdminRequired && mRole != ADMIN)
|
||||||
{
|
{
|
||||||
return rpcError(rpcNO_PERMISSION);
|
return rpcError(rpcNO_PERMISSION);
|
||||||
}
|
}
|
||||||
else if (commandsA[i].mEvented && mInfoSub == NULL)
|
else if (commandsA[i].bEvented && mInfoSub == NULL)
|
||||||
{
|
{
|
||||||
return rpcError(rpcNO_EVENTS);
|
return rpcError(rpcNO_EVENTS);
|
||||||
}
|
}
|
||||||
@@ -1705,15 +1708,13 @@ Json::Value RPCHandler::doTransactionEntry(const Json::Value& jvRequest)
|
|||||||
return jvResult;
|
return jvResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest)
|
Json::Value RPCHandler::lookupLedger(const Json::Value& jvRequest, Ledger::pointer& lpLedger)
|
||||||
{
|
{
|
||||||
Json::Value jvResult;
|
Json::Value jvResult;
|
||||||
|
|
||||||
uint256 uLedger = jvRequest.isMember("ledger_hash") ? uint256(jvRequest["ledger_hash"].asString()) : 0;
|
uint256 uLedger = jvRequest.isMember("ledger_hash") ? uint256(jvRequest["ledger_hash"].asString()) : 0;
|
||||||
uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0;
|
uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0;
|
||||||
|
|
||||||
Ledger::pointer lpLedger;
|
|
||||||
|
|
||||||
if (!!uLedger)
|
if (!!uLedger)
|
||||||
{
|
{
|
||||||
// Ledger directly specified.
|
// Ledger directly specified.
|
||||||
@@ -1756,6 +1757,17 @@ Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest)
|
|||||||
jvResult["ledger_current_index"] = uLedgerIndex;
|
jvResult["ledger_current_index"] = uLedgerIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return jvResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest)
|
||||||
|
{
|
||||||
|
Ledger::pointer lpLedger;
|
||||||
|
Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
|
||||||
|
|
||||||
|
if (!lpLedger)
|
||||||
|
return jvResult;
|
||||||
|
|
||||||
uint256 uNodeIndex;
|
uint256 uNodeIndex;
|
||||||
bool bNodeBinary = false;
|
bool bNodeBinary = false;
|
||||||
|
|
||||||
@@ -1951,6 +1963,25 @@ Json::Value RPCHandler::doLedgerEntry(const Json::Value& jvRequest)
|
|||||||
return jvResult;
|
return jvResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Json::Value RPCHandler::doLedgerHeader(const Json::Value& jvRequest)
|
||||||
|
{
|
||||||
|
Ledger::pointer lpLedger;
|
||||||
|
Json::Value jvResult = lookupLedger(jvRequest, lpLedger);
|
||||||
|
|
||||||
|
if (!lpLedger)
|
||||||
|
return jvResult;
|
||||||
|
|
||||||
|
Serializer s;
|
||||||
|
|
||||||
|
lpLedger->addRaw(s);
|
||||||
|
|
||||||
|
jvResult["ledger_data"] = strHex(s.peekData());
|
||||||
|
|
||||||
|
if (mRole == ADMIN)
|
||||||
|
lpLedger->addJson(jvResult, 0);
|
||||||
|
|
||||||
|
return jvRequest;
|
||||||
|
}
|
||||||
|
|
||||||
boost::unordered_set<RippleAddress> RPCHandler::parseAccountIds(const Json::Value& jvArray)
|
boost::unordered_set<RippleAddress> RPCHandler::parseAccountIds(const Json::Value& jvArray)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class RPCHandler
|
|||||||
{
|
{
|
||||||
NetworkOPs* mNetOps;
|
NetworkOPs* mNetOps;
|
||||||
InfoSub* mInfoSub;
|
InfoSub* mInfoSub;
|
||||||
|
int mRole;
|
||||||
|
|
||||||
typedef Json::Value (RPCHandler::*doFuncPtr)(const Json::Value ¶ms);
|
typedef Json::Value (RPCHandler::*doFuncPtr)(const Json::Value ¶ms);
|
||||||
enum {
|
enum {
|
||||||
@@ -22,6 +23,8 @@ class RPCHandler
|
|||||||
int getParamCount(const Json::Value& params);
|
int getParamCount(const Json::Value& params);
|
||||||
bool extractString(std::string& param, const Json::Value& params, int index);
|
bool extractString(std::string& param, const Json::Value& params, int index);
|
||||||
|
|
||||||
|
Json::Value lookupLedger(const Json::Value& jvRequest, Ledger::pointer& lpLedger);
|
||||||
|
|
||||||
Json::Value getMasterGenerator(const uint256& uLedger, const RippleAddress& naRegularSeed, RippleAddress& naMasterGenerator);
|
Json::Value getMasterGenerator(const uint256& uLedger, const RippleAddress& naRegularSeed, RippleAddress& naMasterGenerator);
|
||||||
Json::Value authorize(const uint256& uLedger, const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID,
|
Json::Value authorize(const uint256& uLedger, const RippleAddress& naRegularSeed, const RippleAddress& naSrcAccountID,
|
||||||
RippleAddress& naAccountPublic, RippleAddress& naAccountPrivate,
|
RippleAddress& naAccountPublic, RippleAddress& naAccountPrivate,
|
||||||
@@ -86,6 +89,7 @@ class RPCHandler
|
|||||||
Json::Value doLedgerClosed(const Json::Value& params);
|
Json::Value doLedgerClosed(const Json::Value& params);
|
||||||
Json::Value doLedgerCurrent(const Json::Value& params);
|
Json::Value doLedgerCurrent(const Json::Value& params);
|
||||||
Json::Value doLedgerEntry(const Json::Value& params);
|
Json::Value doLedgerEntry(const Json::Value& params);
|
||||||
|
Json::Value doLedgerHeader(const Json::Value& params);
|
||||||
Json::Value doTransactionEntry(const Json::Value& params);
|
Json::Value doTransactionEntry(const Json::Value& params);
|
||||||
|
|
||||||
Json::Value doSubscribe(const Json::Value& params);
|
Json::Value doSubscribe(const Json::Value& params);
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ uint160 RippleAddress::getNodeID() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getNodeID");
|
||||||
|
|
||||||
case VER_NODE_PUBLIC:
|
case VER_NODE_PUBLIC:
|
||||||
// Note, we are encoding the left.
|
// Note, we are encoding the left.
|
||||||
@@ -129,7 +129,7 @@ const std::vector<unsigned char>& RippleAddress::getNodePublic() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getNodePublic");
|
||||||
|
|
||||||
case VER_NODE_PUBLIC:
|
case VER_NODE_PUBLIC:
|
||||||
return vchData;
|
return vchData;
|
||||||
@@ -143,7 +143,7 @@ std::string RippleAddress::humanNodePublic() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanNodePublic");
|
||||||
|
|
||||||
case VER_NODE_PUBLIC:
|
case VER_NODE_PUBLIC:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -209,7 +209,7 @@ const std::vector<unsigned char>& RippleAddress::getNodePrivateData() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getNodePrivateData");
|
||||||
|
|
||||||
case VER_NODE_PRIVATE:
|
case VER_NODE_PRIVATE:
|
||||||
return vchData;
|
return vchData;
|
||||||
@@ -223,7 +223,7 @@ uint256 RippleAddress::getNodePrivate() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source = getNodePrivate");
|
||||||
|
|
||||||
case VER_NODE_PRIVATE:
|
case VER_NODE_PRIVATE:
|
||||||
return uint256(vchData);
|
return uint256(vchData);
|
||||||
@@ -237,7 +237,7 @@ std::string RippleAddress::humanNodePrivate() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanNodePrivate");
|
||||||
|
|
||||||
case VER_NODE_PRIVATE:
|
case VER_NODE_PRIVATE:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -279,7 +279,7 @@ uint160 RippleAddress::getAccountID() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getAccountID");
|
||||||
|
|
||||||
case VER_ACCOUNT_ID:
|
case VER_ACCOUNT_ID:
|
||||||
return uint160(vchData);
|
return uint160(vchData);
|
||||||
@@ -297,7 +297,7 @@ std::string RippleAddress::humanAccountID() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanAccountID");
|
||||||
|
|
||||||
case VER_ACCOUNT_ID:
|
case VER_ACCOUNT_ID:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -353,7 +353,7 @@ const std::vector<unsigned char>& RippleAddress::getAccountPublic() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getAccountPublic");
|
||||||
|
|
||||||
case VER_ACCOUNT_ID:
|
case VER_ACCOUNT_ID:
|
||||||
throw std::runtime_error("public not available from account id");
|
throw std::runtime_error("public not available from account id");
|
||||||
@@ -371,7 +371,7 @@ std::string RippleAddress::humanAccountPublic() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanAccountPublic");
|
||||||
|
|
||||||
case VER_ACCOUNT_ID:
|
case VER_ACCOUNT_ID:
|
||||||
throw std::runtime_error("public not available from account id");
|
throw std::runtime_error("public not available from account id");
|
||||||
@@ -446,7 +446,7 @@ uint256 RippleAddress::getAccountPrivate() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getAccountPrivate");
|
||||||
|
|
||||||
case VER_ACCOUNT_PRIVATE:
|
case VER_ACCOUNT_PRIVATE:
|
||||||
return uint256(vchData);
|
return uint256(vchData);
|
||||||
@@ -460,7 +460,7 @@ std::string RippleAddress::humanAccountPrivate() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanAccountPrivate");
|
||||||
|
|
||||||
case VER_ACCOUNT_PRIVATE:
|
case VER_ACCOUNT_PRIVATE:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -606,7 +606,7 @@ BIGNUM* RippleAddress::getGeneratorBN() const
|
|||||||
{ // returns the public generator
|
{ // returns the public generator
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getGeneratorBN");
|
||||||
|
|
||||||
case VER_FAMILY_GENERATOR:
|
case VER_FAMILY_GENERATOR:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
@@ -625,7 +625,7 @@ const std::vector<unsigned char>& RippleAddress::getGenerator() const
|
|||||||
{ // returns the public generator
|
{ // returns the public generator
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getGenerator");
|
||||||
|
|
||||||
case VER_FAMILY_GENERATOR:
|
case VER_FAMILY_GENERATOR:
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
@@ -640,7 +640,7 @@ std::string RippleAddress::humanGenerator() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanGenerator");
|
||||||
|
|
||||||
case VER_FAMILY_GENERATOR:
|
case VER_FAMILY_GENERATOR:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -678,7 +678,7 @@ uint128 RippleAddress::getSeed() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - getSeed");
|
||||||
|
|
||||||
case VER_FAMILY_SEED:
|
case VER_FAMILY_SEED:
|
||||||
return uint128(vchData);
|
return uint128(vchData);
|
||||||
@@ -692,7 +692,7 @@ std::string RippleAddress::humanSeed1751() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanSeed1751");
|
||||||
|
|
||||||
case VER_FAMILY_SEED:
|
case VER_FAMILY_SEED:
|
||||||
{
|
{
|
||||||
@@ -719,7 +719,7 @@ std::string RippleAddress::humanSeed() const
|
|||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source - humanSeed");
|
||||||
|
|
||||||
case VER_FAMILY_SEED:
|
case VER_FAMILY_SEED:
|
||||||
return ToString();
|
return ToString();
|
||||||
@@ -792,7 +792,7 @@ void RippleAddress::setSeedRandom()
|
|||||||
// XXX Maybe we should call MakeNewKey
|
// XXX Maybe we should call MakeNewKey
|
||||||
uint128 key;
|
uint128 key;
|
||||||
|
|
||||||
RAND_bytes((unsigned char *) &key, sizeof(key));
|
RAND_bytes(key.begin(), key.size());
|
||||||
|
|
||||||
RippleAddress::setSeed(key);
|
RippleAddress::setSeed(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ std::size_t hash_value(const aciSource& asValue)
|
|||||||
// - Set bEntryAdvance to advance to next entry.
|
// - Set bEntryAdvance to advance to next entry.
|
||||||
// <-- uOfferIndex : 0=end of list.
|
// <-- uOfferIndex : 0=end of list.
|
||||||
TER RippleCalc::calcNodeAdvance(
|
TER RippleCalc::calcNodeAdvance(
|
||||||
const unsigned int uIndex, // 0 < uIndex < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const bool bReverse)
|
const bool bReverse)
|
||||||
{
|
{
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode-1];
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
|
|
||||||
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
const uint160& uPrvCurrencyID = pnPrv.uCurrencyID;
|
||||||
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
const uint160& uPrvIssuerID = pnPrv.uIssuerID;
|
||||||
@@ -181,7 +181,7 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
curIssuerNodeConstIterator itForward = pspCur->umForward.find(asLine);
|
curIssuerNodeConstIterator itForward = pspCur->umForward.find(asLine);
|
||||||
const bool bFoundForward = itForward != pspCur->umForward.end();
|
const bool bFoundForward = itForward != pspCur->umForward.end();
|
||||||
|
|
||||||
if (bFoundForward && itForward->second != uIndex)
|
if (bFoundForward && itForward->second != uNode)
|
||||||
{
|
{
|
||||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (forward)";
|
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (forward)";
|
||||||
@@ -193,7 +193,7 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
curIssuerNodeConstIterator itPast = mumSource.find(asLine);
|
curIssuerNodeConstIterator itPast = mumSource.find(asLine);
|
||||||
bool bFoundPast = itPast != mumSource.end();
|
bool bFoundPast = itPast != mumSource.end();
|
||||||
|
|
||||||
if (bFoundPast && itPast->second != uIndex)
|
if (bFoundPast && itPast->second != uNode)
|
||||||
{
|
{
|
||||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (past)";
|
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (past)";
|
||||||
@@ -205,7 +205,7 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
curIssuerNodeConstIterator itReverse = pspCur->umReverse.find(asLine);
|
curIssuerNodeConstIterator itReverse = pspCur->umReverse.find(asLine);
|
||||||
bool bFoundReverse = itReverse != pspCur->umReverse.end();
|
bool bFoundReverse = itReverse != pspCur->umReverse.end();
|
||||||
|
|
||||||
if (bFoundReverse && itReverse->second != uIndex)
|
if (bFoundReverse && itReverse->second != uNode)
|
||||||
{
|
{
|
||||||
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
// Temporarily unfunded. Another node uses this source, ignore in this offer.
|
||||||
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (reverse)";
|
cLog(lsINFO) << "calcNodeAdvance: temporarily unfunded offer (reverse)";
|
||||||
@@ -245,7 +245,7 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
% STAmount::createHumanCurrency(uCurCurrencyID)
|
% STAmount::createHumanCurrency(uCurCurrencyID)
|
||||||
% RippleAddress::createHumanAccountID(uCurIssuerID));
|
% RippleAddress::createHumanAccountID(uCurIssuerID));
|
||||||
|
|
||||||
pspCur->umReverse.insert(std::make_pair(asLine, uIndex));
|
pspCur->umReverse.insert(std::make_pair(asLine, uNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
bFundsDirty = false;
|
bFundsDirty = false;
|
||||||
@@ -270,7 +270,7 @@ TER RippleCalc::calcNodeAdvance(
|
|||||||
// requirements to the previous node. The previous node adjusts the amount output and the amount spent on fees. Continue process
|
// requirements to the previous node. The previous node adjusts the amount output and the amount spent on fees. Continue process
|
||||||
// till request is satisified while we the rate does not increase past the initial rate.
|
// till request is satisified while we the rate does not increase past the initial rate.
|
||||||
TER RippleCalc::calcNodeDeliverRev(
|
TER RippleCalc::calcNodeDeliverRev(
|
||||||
const unsigned int uIndex, // 0 < uIndex < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const uint160& uOutAccountID, // --> Output owner's account.
|
const uint160& uOutAccountID, // --> Output owner's account.
|
||||||
@@ -279,8 +279,8 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
{
|
{
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
|
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode-1];
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
|
|
||||||
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
||||||
const uint160& uPrvAccountID = pnPrv.uAccountID;
|
const uint160& uPrvAccountID = pnPrv.uAccountID;
|
||||||
@@ -308,7 +308,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
STAmount& saTakerGets = pnCur.saTakerGets;
|
STAmount& saTakerGets = pnCur.saTakerGets;
|
||||||
STAmount& saRateMax = pnCur.saRateMax;
|
STAmount& saRateMax = pnCur.saRateMax;
|
||||||
|
|
||||||
terResult = calcNodeAdvance(uIndex, pspCur, bMultiQuality, true); // If needed, advance to next funded offer.
|
terResult = calcNodeAdvance(uNode, pspCur, bMultiQuality, true); // If needed, advance to next funded offer.
|
||||||
|
|
||||||
if (tesSUCCESS != terResult || !uOfferIndex)
|
if (tesSUCCESS != terResult || !uOfferIndex)
|
||||||
{
|
{
|
||||||
@@ -413,7 +413,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
// Chain and compute the previous offer now.
|
// Chain and compute the previous offer now.
|
||||||
|
|
||||||
terResult = calcNodeDeliverRev(
|
terResult = calcNodeDeliverRev(
|
||||||
uIndex-1,
|
uNode-1,
|
||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
uOfrOwnerID,
|
uOfrOwnerID,
|
||||||
@@ -474,7 +474,7 @@ TER RippleCalc::calcNodeDeliverRev(
|
|||||||
// Deliver maximum amount of funds from previous node.
|
// Deliver maximum amount of funds from previous node.
|
||||||
// Goal: Make progress consuming the offer.
|
// Goal: Make progress consuming the offer.
|
||||||
TER RippleCalc::calcNodeDeliverFwd(
|
TER RippleCalc::calcNodeDeliverFwd(
|
||||||
const unsigned int uIndex, // 0 < uIndex < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const uint160& uInAccountID, // --> Input owner's account.
|
const uint160& uInAccountID, // --> Input owner's account.
|
||||||
@@ -485,9 +485,9 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
{
|
{
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
|
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode-1];
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
PaymentNode& pnNxt = pspCur->vpnNodes[uIndex+1];
|
PaymentNode& pnNxt = pspCur->vpnNodes[uNode+1];
|
||||||
|
|
||||||
const uint160& uNxtAccountID = pnNxt.uAccountID;
|
const uint160& uNxtAccountID = pnNxt.uAccountID;
|
||||||
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
const uint160& uCurIssuerID = pnCur.uIssuerID;
|
||||||
@@ -507,7 +507,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
&& saInAct != saInReq // Did not deliver limit.
|
&& saInAct != saInReq // Did not deliver limit.
|
||||||
&& saInAct + saInFees != saInFunds) // Did not deliver all funds.
|
&& saInAct + saInFees != saInFunds) // Did not deliver all funds.
|
||||||
{
|
{
|
||||||
terResult = calcNodeAdvance(uIndex, pspCur, bMultiQuality, false); // If needed, advance to next funded offer.
|
terResult = calcNodeAdvance(uNode, pspCur, bMultiQuality, false); // If needed, advance to next funded offer.
|
||||||
|
|
||||||
if (tesSUCCESS == terResult)
|
if (tesSUCCESS == terResult)
|
||||||
{
|
{
|
||||||
@@ -570,7 +570,7 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
STAmount saOutPassFees;
|
STAmount saOutPassFees;
|
||||||
|
|
||||||
terResult = RippleCalc::calcNodeDeliverFwd(
|
terResult = RippleCalc::calcNodeDeliverFwd(
|
||||||
uIndex+1,
|
uNode+1,
|
||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
uOfrOwnerID,
|
uOfrOwnerID,
|
||||||
@@ -628,14 +628,14 @@ TER RippleCalc::calcNodeDeliverFwd(
|
|||||||
|
|
||||||
// Called to drive from the last offer node in a chain.
|
// Called to drive from the last offer node in a chain.
|
||||||
TER RippleCalc::calcNodeOfferRev(
|
TER RippleCalc::calcNodeOfferRev(
|
||||||
const unsigned int uIndex, // 0 < uIndex < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality)
|
const bool bMultiQuality)
|
||||||
{
|
{
|
||||||
TER terResult;
|
TER terResult;
|
||||||
|
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
PaymentNode& pnNxt = pspCur->vpnNodes[uIndex+1];
|
PaymentNode& pnNxt = pspCur->vpnNodes[uNode+1];
|
||||||
|
|
||||||
if (!!pnNxt.uAccountID)
|
if (!!pnNxt.uAccountID)
|
||||||
{
|
{
|
||||||
@@ -643,7 +643,7 @@ TER RippleCalc::calcNodeOfferRev(
|
|||||||
STAmount saDeliverAct;
|
STAmount saDeliverAct;
|
||||||
|
|
||||||
terResult = calcNodeDeliverRev(
|
terResult = calcNodeDeliverRev(
|
||||||
uIndex,
|
uNode,
|
||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
|
|
||||||
@@ -668,13 +668,13 @@ TER RippleCalc::calcNodeOfferRev(
|
|||||||
// - Payout to issuer or limbo.
|
// - Payout to issuer or limbo.
|
||||||
// - Deliver is set without transfer fees.
|
// - Deliver is set without transfer fees.
|
||||||
TER RippleCalc::calcNodeOfferFwd(
|
TER RippleCalc::calcNodeOfferFwd(
|
||||||
const unsigned int uIndex, // 0 < uIndex < uLast
|
const unsigned int uNode, // 0 < uNode < uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality
|
const bool bMultiQuality
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
TER terResult;
|
TER terResult;
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex-1];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode-1];
|
||||||
|
|
||||||
if (!!pnPrv.uAccountID)
|
if (!!pnPrv.uAccountID)
|
||||||
{
|
{
|
||||||
@@ -683,7 +683,7 @@ TER RippleCalc::calcNodeOfferFwd(
|
|||||||
STAmount saInFees;
|
STAmount saInFees;
|
||||||
|
|
||||||
terResult = calcNodeDeliverFwd(
|
terResult = calcNodeDeliverFwd(
|
||||||
uIndex,
|
uNode,
|
||||||
pspCur,
|
pspCur,
|
||||||
bMultiQuality,
|
bMultiQuality,
|
||||||
pnPrv.uAccountID,
|
pnPrv.uAccountID,
|
||||||
@@ -822,20 +822,20 @@ void RippleCalc::calcNodeRipple(
|
|||||||
// Issues are limited based on credit limits and amount owed.
|
// Issues are limited based on credit limits and amount owed.
|
||||||
// No account balance adjustments as we don't know how much is going to actually be pushed through yet.
|
// No account balance adjustments as we don't know how much is going to actually be pushed through yet.
|
||||||
// <-- tesSUCCESS or tepPATH_DRY
|
// <-- tesSUCCESS or tepPATH_DRY
|
||||||
TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
|
TER RippleCalc::calcNodeAccountRev(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality)
|
||||||
{
|
{
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
|
const unsigned int uLast = pspCur->vpnNodes.size() - 1;
|
||||||
|
|
||||||
uint64 uRateMax = 0;
|
uint64 uRateMax = 0;
|
||||||
|
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode ? uNode-1 : 0];
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
PaymentNode& pnNxt = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1];
|
PaymentNode& pnNxt = pspCur->vpnNodes[uNode == uLast ? uLast : uNode+1];
|
||||||
|
|
||||||
// Current is allowed to redeem to next.
|
// Current is allowed to redeem to next.
|
||||||
const bool bPrvAccount = !uIndex || isSetBit(pnPrv.uFlags, STPathElement::typeAccount);
|
const bool bPrvAccount = !uNode || isSetBit(pnPrv.uFlags, STPathElement::typeAccount);
|
||||||
const bool bNxtAccount = uIndex == uLast || isSetBit(pnNxt.uFlags, STPathElement::typeAccount);
|
const bool bNxtAccount = uNode == uLast || isSetBit(pnNxt.uFlags, STPathElement::typeAccount);
|
||||||
|
|
||||||
const uint160& uCurAccountID = pnCur.uAccountID;
|
const uint160& uCurAccountID = pnCur.uAccountID;
|
||||||
const uint160& uPrvAccountID = bPrvAccount ? pnPrv.uAccountID : uCurAccountID;
|
const uint160& uPrvAccountID = bPrvAccount ? pnPrv.uAccountID : uCurAccountID;
|
||||||
@@ -843,24 +843,24 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref psp
|
|||||||
|
|
||||||
const uint160& uCurrencyID = pnCur.uCurrencyID;
|
const uint160& uCurrencyID = pnCur.uCurrencyID;
|
||||||
|
|
||||||
const uint32 uQualityIn = uIndex ? lesActive.rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : QUALITY_ONE;
|
const uint32 uQualityIn = uNode ? lesActive.rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : QUALITY_ONE;
|
||||||
const uint32 uQualityOut = uIndex != uLast ? lesActive.rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : QUALITY_ONE;
|
const uint32 uQualityOut = uNode != uLast ? lesActive.rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : QUALITY_ONE;
|
||||||
|
|
||||||
// For bPrvAccount
|
// For bPrvAccount
|
||||||
const STAmount saPrvOwed = bPrvAccount && uIndex // Previous account is owed.
|
const STAmount saPrvOwed = bPrvAccount && uNode // Previous account is owed.
|
||||||
? lesActive.rippleOwed(uCurAccountID, uPrvAccountID, uCurrencyID)
|
? lesActive.rippleOwed(uCurAccountID, uPrvAccountID, uCurrencyID)
|
||||||
: STAmount(uCurrencyID, uCurAccountID);
|
: STAmount(uCurrencyID, uCurAccountID);
|
||||||
|
|
||||||
const STAmount saPrvLimit = bPrvAccount && uIndex // Previous account may owe.
|
const STAmount saPrvLimit = bPrvAccount && uNode // Previous account may owe.
|
||||||
? lesActive.rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID)
|
? lesActive.rippleLimit(uCurAccountID, uPrvAccountID, uCurrencyID)
|
||||||
: STAmount(uCurrencyID, uCurAccountID);
|
: STAmount(uCurrencyID, uCurAccountID);
|
||||||
|
|
||||||
const STAmount saNxtOwed = bNxtAccount && uIndex != uLast // Next account is owed.
|
const STAmount saNxtOwed = bNxtAccount && uNode != uLast // Next account is owed.
|
||||||
? lesActive.rippleOwed(uCurAccountID, uNxtAccountID, uCurrencyID)
|
? lesActive.rippleOwed(uCurAccountID, uNxtAccountID, uCurrencyID)
|
||||||
: STAmount(uCurrencyID, uCurAccountID);
|
: STAmount(uCurrencyID, uCurAccountID);
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev> uIndex=%d/%d uPrvAccountID=%s uCurAccountID=%s uNxtAccountID=%s uCurrencyID=%s uQualityIn=%d uQualityOut=%d saPrvOwed=%s saPrvLimit=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountRev> uNode=%d/%d uPrvAccountID=%s uCurAccountID=%s uNxtAccountID=%s uCurrencyID=%s uQualityIn=%d uQualityOut=%d saPrvOwed=%s saPrvLimit=%s")
|
||||||
% uIndex
|
% uNode
|
||||||
% uLast
|
% uLast
|
||||||
% RippleAddress::createHumanAccountID(uPrvAccountID)
|
% RippleAddress::createHumanAccountID(uPrvAccountID)
|
||||||
% RippleAddress::createHumanAccountID(uCurAccountID)
|
% RippleAddress::createHumanAccountID(uCurAccountID)
|
||||||
@@ -910,13 +910,13 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref psp
|
|||||||
|
|
||||||
if (bPrvAccount && bNxtAccount)
|
if (bPrvAccount && bNxtAccount)
|
||||||
{
|
{
|
||||||
if (!uIndex)
|
if (!uNode)
|
||||||
{
|
{
|
||||||
// ^ --> ACCOUNT --> account|offer
|
// ^ --> ACCOUNT --> account|offer
|
||||||
// Nothing to do, there is no previous to adjust.
|
// Nothing to do, there is no previous to adjust.
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
else if (uIndex == uLast)
|
else if (uNode == uLast)
|
||||||
{
|
{
|
||||||
// account --> ACCOUNT --> $
|
// account --> ACCOUNT --> $
|
||||||
// Overall deliverable.
|
// Overall deliverable.
|
||||||
@@ -1081,7 +1081,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref psp
|
|||||||
{
|
{
|
||||||
saPrvDeliverAct.zero(saCurRedeemReq);
|
saPrvDeliverAct.zero(saCurRedeemReq);
|
||||||
|
|
||||||
if (uIndex == uLast)
|
if (uNode == uLast)
|
||||||
{
|
{
|
||||||
// offer --> ACCOUNT --> $
|
// offer --> ACCOUNT --> $
|
||||||
const STAmount& saCurWantedReq = bPrvAccount
|
const STAmount& saCurWantedReq = bPrvAccount
|
||||||
@@ -1166,7 +1166,7 @@ TER RippleCalc::calcNodeAccountRev(const unsigned int uIndex, PathState::ref psp
|
|||||||
// - Current node: specify what to push through to next.
|
// - Current node: specify what to push through to next.
|
||||||
// - Output to next node is computed as input minus quality or transfer fee.
|
// - Output to next node is computed as input minus quality or transfer fee.
|
||||||
TER RippleCalc::calcNodeAccountFwd(
|
TER RippleCalc::calcNodeAccountFwd(
|
||||||
const unsigned int uIndex, // 0 <= uIndex <= uLast
|
const unsigned int uNode, // 0 <= uNode <= uLast
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality)
|
const bool bMultiQuality)
|
||||||
{
|
{
|
||||||
@@ -1175,9 +1175,9 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
|
|
||||||
uint64 uRateMax = 0;
|
uint64 uRateMax = 0;
|
||||||
|
|
||||||
PaymentNode& pnPrv = pspCur->vpnNodes[uIndex ? uIndex-1 : 0];
|
PaymentNode& pnPrv = pspCur->vpnNodes[uNode ? uNode-1 : 0];
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
PaymentNode& pnNxt = pspCur->vpnNodes[uIndex == uLast ? uLast : uIndex+1];
|
PaymentNode& pnNxt = pspCur->vpnNodes[uNode == uLast ? uLast : uNode+1];
|
||||||
|
|
||||||
const bool bPrvAccount = isSetBit(pnPrv.uFlags, STPathElement::typeAccount);
|
const bool bPrvAccount = isSetBit(pnPrv.uFlags, STPathElement::typeAccount);
|
||||||
const bool bNxtAccount = isSetBit(pnNxt.uFlags, STPathElement::typeAccount);
|
const bool bNxtAccount = isSetBit(pnNxt.uFlags, STPathElement::typeAccount);
|
||||||
@@ -1188,8 +1188,8 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
|
|
||||||
const uint160& uCurrencyID = pnCur.uCurrencyID;
|
const uint160& uCurrencyID = pnCur.uCurrencyID;
|
||||||
|
|
||||||
uint32 uQualityIn = uIndex ? lesActive.rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : QUALITY_ONE;
|
uint32 uQualityIn = uNode ? lesActive.rippleQualityIn(uCurAccountID, uPrvAccountID, uCurrencyID) : QUALITY_ONE;
|
||||||
uint32 uQualityOut = uIndex == uLast ? lesActive.rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : QUALITY_ONE;
|
uint32 uQualityOut = uNode == uLast ? lesActive.rippleQualityOut(uCurAccountID, uNxtAccountID, uCurrencyID) : QUALITY_ONE;
|
||||||
|
|
||||||
// When looking backward (prv) for req we care about what we just calculated: use fwd
|
// When looking backward (prv) for req we care about what we just calculated: use fwd
|
||||||
// When looking forward (cur) for req we care about what was desired: use rev
|
// When looking forward (cur) for req we care about what was desired: use rev
|
||||||
@@ -1216,8 +1216,8 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
|
const STAmount& saCurDeliverReq = pnCur.saRevDeliver;
|
||||||
STAmount& saCurDeliverAct = pnCur.saFwdDeliver;
|
STAmount& saCurDeliverAct = pnCur.saFwdDeliver;
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd> uIndex=%d/%d saPrvRedeemReq=%s saPrvIssueReq=%s saPrvDeliverReq=%s saCurRedeemReq=%s saCurIssueReq=%s saCurDeliverReq=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd> uNode=%d/%d saPrvRedeemReq=%s saPrvIssueReq=%s saPrvDeliverReq=%s saCurRedeemReq=%s saCurIssueReq=%s saCurDeliverReq=%s")
|
||||||
% uIndex
|
% uNode
|
||||||
% uLast
|
% uLast
|
||||||
% saPrvRedeemReq.getFullText()
|
% saPrvRedeemReq.getFullText()
|
||||||
% saPrvIssueReq.getFullText()
|
% saPrvIssueReq.getFullText()
|
||||||
@@ -1232,7 +1232,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
{
|
{
|
||||||
// Next is an account, must be rippling.
|
// Next is an account, must be rippling.
|
||||||
|
|
||||||
if (!uIndex)
|
if (!uNode)
|
||||||
{
|
{
|
||||||
// ^ --> ACCOUNT --> account
|
// ^ --> ACCOUNT --> account
|
||||||
|
|
||||||
@@ -1274,7 +1274,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
% saCurIssueAct.getFullText()
|
% saCurIssueAct.getFullText()
|
||||||
% saCurSendMaxPass.getFullText());
|
% saCurSendMaxPass.getFullText());
|
||||||
}
|
}
|
||||||
else if (uIndex == uLast)
|
else if (uNode == uLast)
|
||||||
{
|
{
|
||||||
// account --> ACCOUNT --> $
|
// account --> ACCOUNT --> $
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: account --> ACCOUNT --> $ : uPrvAccountID=%s uCurAccountID=%s saPrvRedeemReq=%s saPrvIssueReq=%s")
|
||||||
@@ -1371,7 +1371,7 @@ TER RippleCalc::calcNodeAccountFwd(
|
|||||||
}
|
}
|
||||||
else if (!bPrvAccount && bNxtAccount)
|
else if (!bPrvAccount && bNxtAccount)
|
||||||
{
|
{
|
||||||
if (uIndex == uLast)
|
if (uNode == uLast)
|
||||||
{
|
{
|
||||||
// offer --> ACCOUNT --> $
|
// offer --> ACCOUNT --> $
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $ : %s") % saPrvDeliverReq.getFullText());
|
cLog(lsINFO) << boost::str(boost::format("calcNodeAccountFwd: offer --> ACCOUNT --> $ : %s") % saPrvDeliverReq.getFullText());
|
||||||
@@ -1472,26 +1472,27 @@ TER PathState::pushImply(
|
|||||||
{
|
{
|
||||||
// Currency is different, need to convert via an offer.
|
// Currency is different, need to convert via an offer.
|
||||||
|
|
||||||
terResult = pushNode(
|
terResult = pushNode( // Offer.
|
||||||
STPathElement::typeCurrency // Offer.
|
!!uCurrencyID
|
||||||
| STPathElement::typeIssuer,
|
? STPathElement::typeCurrency | STPathElement::typeIssuer
|
||||||
ACCOUNT_ONE, // Placeholder for offers.
|
: STPathElement::typeCurrency,
|
||||||
|
ACCOUNT_XRP, // Placeholder for offers.
|
||||||
uCurrencyID, // The offer's output is what is now wanted.
|
uCurrencyID, // The offer's output is what is now wanted.
|
||||||
uIssuerID);
|
uIssuerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PaymentNode& pnBck = vpnNodes.back();
|
const PaymentNode& pnBck = vpnNodes.back();
|
||||||
|
|
||||||
// For ripple, non-stamps, ensure the issuer is on at least one side of the transaction.
|
// For ripple, non-XRP, ensure the issuer is on at least one side of the transaction.
|
||||||
if (tesSUCCESS == terResult
|
if (tesSUCCESS == terResult
|
||||||
&& !!uCurrencyID // Not stamps.
|
&& !!uCurrencyID // Not XRP.
|
||||||
&& (pnBck.uAccountID != uIssuerID // Previous is not issuing own IOUs.
|
&& (pnBck.uAccountID != uIssuerID // Previous is not issuing own IOUs.
|
||||||
&& uAccountID != uIssuerID)) // Current is not receiving own IOUs.
|
&& uAccountID != uIssuerID)) // Current is not receiving own IOUs.
|
||||||
{
|
{
|
||||||
// Need to ripple through uIssuerID's account.
|
// Need to ripple through uIssuerID's account.
|
||||||
|
|
||||||
terResult = pushNode(
|
terResult = pushNode(
|
||||||
STPathElement::typeAccount,
|
STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer,
|
||||||
uIssuerID, // Intermediate account is the needed issuer.
|
uIssuerID, // Intermediate account is the needed issuer.
|
||||||
uCurrencyID,
|
uCurrencyID,
|
||||||
uIssuerID);
|
uIssuerID);
|
||||||
@@ -1511,10 +1512,6 @@ TER PathState::pushNode(
|
|||||||
const uint160& uCurrencyID,
|
const uint160& uCurrencyID,
|
||||||
const uint160& uIssuerID)
|
const uint160& uIssuerID)
|
||||||
{
|
{
|
||||||
cLog(lsINFO) << "pushNode> "
|
|
||||||
<< RippleAddress::createHumanAccountID(uAccountID)
|
|
||||||
<< " " << STAmount::createHumanCurrency(uCurrencyID)
|
|
||||||
<< "/" << RippleAddress::createHumanAccountID(uIssuerID);
|
|
||||||
PaymentNode pnCur;
|
PaymentNode pnCur;
|
||||||
const bool bFirst = vpnNodes.empty();
|
const bool bFirst = vpnNodes.empty();
|
||||||
const PaymentNode& pnPrv = bFirst ? PaymentNode() : vpnNodes.back();
|
const PaymentNode& pnPrv = bFirst ? PaymentNode() : vpnNodes.back();
|
||||||
@@ -1527,11 +1524,30 @@ TER PathState::pushNode(
|
|||||||
const bool bIssuer = isSetBit(iType, STPathElement::typeIssuer);
|
const bool bIssuer = isSetBit(iType, STPathElement::typeIssuer);
|
||||||
TER terResult = tesSUCCESS;
|
TER terResult = tesSUCCESS;
|
||||||
|
|
||||||
|
cLog(lsDEBUG) << "pushNode> "
|
||||||
|
<< iType
|
||||||
|
<< ": " << (bAccount ? RippleAddress::createHumanAccountID(uAccountID) : "-")
|
||||||
|
<< " " << (bCurrency ? STAmount::createHumanCurrency(uCurrencyID) : "-")
|
||||||
|
<< "/" << (bIssuer ? RippleAddress::createHumanAccountID(uIssuerID) : "-");
|
||||||
|
|
||||||
pnCur.uFlags = iType;
|
pnCur.uFlags = iType;
|
||||||
|
pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID;
|
||||||
|
|
||||||
if (iType & ~STPathElement::typeValidBits)
|
if (iType & ~STPathElement::typeValidBits)
|
||||||
{
|
{
|
||||||
cLog(lsINFO) << "pushNode: bad bits.";
|
cLog(lsDEBUG) << "pushNode: bad bits.";
|
||||||
|
|
||||||
|
terResult = temBAD_PATH;
|
||||||
|
}
|
||||||
|
else if (bIssuer && !pnCur.uCurrencyID)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "pushNode: issuer specified for XRP.";
|
||||||
|
|
||||||
|
terResult = temBAD_PATH;
|
||||||
|
}
|
||||||
|
else if (bIssuer && !uIssuerID)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "pushNode: specified bad issuer.";
|
||||||
|
|
||||||
terResult = temBAD_PATH;
|
terResult = temBAD_PATH;
|
||||||
}
|
}
|
||||||
@@ -1540,8 +1556,11 @@ TER PathState::pushNode(
|
|||||||
// Account link
|
// Account link
|
||||||
|
|
||||||
pnCur.uAccountID = uAccountID;
|
pnCur.uAccountID = uAccountID;
|
||||||
pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID;
|
pnCur.uIssuerID = bIssuer
|
||||||
pnCur.uIssuerID = bIssuer ? uIssuerID : uAccountID;
|
? uIssuerID
|
||||||
|
: !!pnCur.uCurrencyID
|
||||||
|
? uAccountID
|
||||||
|
: ACCOUNT_XRP;
|
||||||
pnCur.saRevRedeem = STAmount(uCurrencyID, uAccountID);
|
pnCur.saRevRedeem = STAmount(uCurrencyID, uAccountID);
|
||||||
pnCur.saRevIssue = STAmount(uCurrencyID, uAccountID);
|
pnCur.saRevIssue = STAmount(uCurrencyID, uAccountID);
|
||||||
|
|
||||||
@@ -1551,6 +1570,12 @@ TER PathState::pushNode(
|
|||||||
|
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
|
else if (!uAccountID)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "pushNode: specified bad account.";
|
||||||
|
|
||||||
|
terResult = temBAD_PATH;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Add required intermediate nodes to deliver to current account.
|
// Add required intermediate nodes to deliver to current account.
|
||||||
@@ -1612,19 +1637,28 @@ TER PathState::pushNode(
|
|||||||
{
|
{
|
||||||
// Offer link
|
// Offer link
|
||||||
// Offers bridge a change in currency & issuer or just a change in issuer.
|
// Offers bridge a change in currency & issuer or just a change in issuer.
|
||||||
pnCur.uCurrencyID = bCurrency ? uCurrencyID : pnPrv.uCurrencyID;
|
pnCur.uIssuerID = bIssuer
|
||||||
pnCur.uIssuerID = bIssuer ? uIssuerID : pnCur.uAccountID;
|
? uIssuerID
|
||||||
|
: !!pnCur.uCurrencyID
|
||||||
|
? !!pnPrv.uIssuerID
|
||||||
|
? pnPrv.uIssuerID // Default to previous issuer
|
||||||
|
: pnPrv.uAccountID // Or previous account if no previous issuer.
|
||||||
|
: ACCOUNT_XRP;
|
||||||
pnCur.saRateMax = saZero;
|
pnCur.saRateMax = saZero;
|
||||||
|
|
||||||
if (!!pnPrv.uAccountID)
|
if (!!pnCur.uCurrencyID != !!pnCur.uIssuerID)
|
||||||
|
{
|
||||||
|
cLog(lsDEBUG) << "pushNode: currency is inconsistent with issuer.";
|
||||||
|
|
||||||
|
terResult = temBAD_PATH;
|
||||||
|
}
|
||||||
|
else if (!!pnPrv.uAccountID)
|
||||||
{
|
{
|
||||||
// Previous is an account.
|
// Previous is an account.
|
||||||
|
|
||||||
// Insert intermediary issuer account if needed.
|
// Insert intermediary issuer account if needed.
|
||||||
terResult = pushImply(
|
terResult = pushImply(
|
||||||
!!pnPrv.uCurrencyID
|
ACCOUNT_XRP, // Rippling, but offer's don't have an account.
|
||||||
? ACCOUNT_ONE // Rippling, but offer's don't have an account.
|
|
||||||
: ACCOUNT_XRP,
|
|
||||||
pnPrv.uCurrencyID,
|
pnPrv.uCurrencyID,
|
||||||
pnPrv.uIssuerID);
|
pnPrv.uIssuerID);
|
||||||
}
|
}
|
||||||
@@ -1655,30 +1689,37 @@ PathState::PathState(
|
|||||||
saInReq(saSendMax),
|
saInReq(saSendMax),
|
||||||
saOutReq(saSend)
|
saOutReq(saSend)
|
||||||
{
|
{
|
||||||
const uint160 uInCurrencyID = saSendMax.getCurrency();
|
const uint160 uMaxCurrencyID = saSendMax.getCurrency();
|
||||||
|
const uint160 uMaxIssuerID = saSendMax.getIssuer();
|
||||||
|
|
||||||
const uint160 uOutCurrencyID = saSend.getCurrency();
|
const uint160 uOutCurrencyID = saSend.getCurrency();
|
||||||
const uint160 uInIssuerID = !!uInCurrencyID ? saSendMax.getIssuer() : ACCOUNT_XRP;
|
const uint160 uOutIssuerID = saSend.getIssuer();
|
||||||
const uint160 uOutIssuerID = !!uOutCurrencyID ? saSend.getIssuer() : ACCOUNT_XRP;
|
const uint160 uSenderIssuerID = !!uMaxCurrencyID ? uSenderID : ACCOUNT_XRP; // Sender is always issuer for non-XRP.
|
||||||
|
|
||||||
lesEntries = lesSource.duplicate();
|
lesEntries = lesSource.duplicate();
|
||||||
|
|
||||||
|
terStatus = tesSUCCESS;
|
||||||
|
|
||||||
|
if ((!uMaxCurrencyID && !!uMaxIssuerID) || (!uOutCurrencyID && !!uOutIssuerID))
|
||||||
|
terStatus = temBAD_PATH;
|
||||||
|
|
||||||
// Push sending node.
|
// Push sending node.
|
||||||
terStatus = pushNode(
|
if (tesSUCCESS == terStatus)
|
||||||
STPathElement::typeAccount
|
terStatus = pushNode(
|
||||||
| STPathElement::typeCurrency
|
!!uMaxCurrencyID
|
||||||
| STPathElement::typeIssuer,
|
? STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer
|
||||||
uSenderID,
|
: STPathElement::typeAccount | STPathElement::typeCurrency,
|
||||||
uInCurrencyID,
|
uSenderID,
|
||||||
uSenderID);
|
uMaxCurrencyID, // Max specifes the currency.
|
||||||
|
uSenderIssuerID);
|
||||||
|
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("PathState: pushed: account=%s currency=%s issuer=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("PathState: pushed: account=%s currency=%s issuer=%s")
|
||||||
% RippleAddress::createHumanAccountID(uSenderID)
|
% RippleAddress::createHumanAccountID(uSenderID)
|
||||||
% STAmount::createHumanCurrency(uInCurrencyID)
|
% STAmount::createHumanCurrency(uMaxCurrencyID)
|
||||||
% RippleAddress::createHumanAccountID(uSenderID));
|
% RippleAddress::createHumanAccountID(uSenderIssuerID));
|
||||||
|
|
||||||
if (tesSUCCESS == terStatus
|
if (tesSUCCESS == terStatus
|
||||||
&& !!uInCurrencyID // First was not XRC
|
&& uMaxIssuerID != uSenderIssuerID) { // Issuer was not same as sender
|
||||||
&& uInIssuerID != uSenderID) { // Issuer was not same as sender
|
|
||||||
// May have an implied node.
|
// May have an implied node.
|
||||||
|
|
||||||
// Figure out next node properties for implied node.
|
// Figure out next node properties for implied node.
|
||||||
@@ -1698,22 +1739,22 @@ cLog(lsDEBUG) << boost::str(boost::format("PathState: implied check: uNxtCurrenc
|
|||||||
% RippleAddress::createHumanAccountID(uNxtAccountID));
|
% RippleAddress::createHumanAccountID(uNxtAccountID));
|
||||||
|
|
||||||
// Can't just use push implied, because it can't compensate for next account.
|
// Can't just use push implied, because it can't compensate for next account.
|
||||||
if (!uNxtCurrencyID // Next is XRC - will have offer next
|
if (!uNxtCurrencyID // Next is XRP - will have offer next
|
||||||
|| uInCurrencyID != uNxtCurrencyID // Next is different current - will have offer next
|
|| uMaxCurrencyID != uNxtCurrencyID // Next is different current - will have offer next
|
||||||
|| uInIssuerID != uNxtAccountID) // Next is not implied issuer
|
|| uMaxIssuerID != uNxtAccountID) // Next is not implied issuer
|
||||||
{
|
{
|
||||||
cLog(lsDEBUG) << boost::str(boost::format("PathState: implied: account=%s currency=%s issuer=%s")
|
cLog(lsDEBUG) << boost::str(boost::format("PathState: sender implied: account=%s currency=%s issuer=%s")
|
||||||
% RippleAddress::createHumanAccountID(uInIssuerID)
|
% RippleAddress::createHumanAccountID(uMaxIssuerID)
|
||||||
% RippleAddress::createHumanAccountID(uInCurrencyID)
|
% RippleAddress::createHumanAccountID(uMaxCurrencyID)
|
||||||
% RippleAddress::createHumanAccountID(uInIssuerID));
|
% RippleAddress::createHumanAccountID(uMaxIssuerID));
|
||||||
// Add implied account.
|
// Add account implied by SendMax.
|
||||||
terStatus = pushNode(
|
terStatus = pushNode(
|
||||||
STPathElement::typeAccount
|
!!uMaxCurrencyID
|
||||||
| STPathElement::typeCurrency
|
? STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer
|
||||||
| STPathElement::typeIssuer,
|
: STPathElement::typeAccount | STPathElement::typeCurrency,
|
||||||
uInIssuerID,
|
uMaxIssuerID,
|
||||||
uInCurrencyID,
|
uMaxCurrencyID,
|
||||||
uInIssuerID);
|
uMaxIssuerID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,32 +1767,37 @@ cLog(lsDEBUG) << boost::str(boost::format("PathState: implied: account=%s curren
|
|||||||
const PaymentNode& pnPrv = vpnNodes.back();
|
const PaymentNode& pnPrv = vpnNodes.back();
|
||||||
|
|
||||||
if (tesSUCCESS == terStatus
|
if (tesSUCCESS == terStatus
|
||||||
&& !!uOutCurrencyID // Next is not XRC
|
&& !!uOutCurrencyID // Next is not XRP
|
||||||
&& uOutIssuerID != uReceiverID // Out issuer is not reciever
|
&& uOutIssuerID != uReceiverID // Out issuer is not reciever
|
||||||
&& (pnPrv.uCurrencyID != uOutCurrencyID // Previous will be an offer.
|
&& (pnPrv.uCurrencyID != uOutCurrencyID // Previous will be an offer.
|
||||||
|| pnPrv.uAccountID != uOutIssuerID)) // Need the implied issuer.
|
|| pnPrv.uAccountID != uOutIssuerID)) // Need the implied issuer.
|
||||||
{
|
{
|
||||||
// Add implied account.
|
// Add implied account.
|
||||||
|
cLog(lsDEBUG) << boost::str(boost::format("PathState: receiver implied: account=%s currency=%s issuer=%s")
|
||||||
|
% RippleAddress::createHumanAccountID(uOutIssuerID)
|
||||||
|
% RippleAddress::createHumanAccountID(uOutCurrencyID)
|
||||||
|
% RippleAddress::createHumanAccountID(uOutIssuerID));
|
||||||
terStatus = pushNode(
|
terStatus = pushNode(
|
||||||
STPathElement::typeAccount
|
!!uOutCurrencyID
|
||||||
| STPathElement::typeCurrency
|
? STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer
|
||||||
| STPathElement::typeIssuer,
|
: STPathElement::typeAccount | STPathElement::typeCurrency,
|
||||||
uOutIssuerID,
|
uOutIssuerID,
|
||||||
uInCurrencyID,
|
uOutCurrencyID,
|
||||||
uOutIssuerID);
|
uOutIssuerID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tesSUCCESS == terStatus)
|
if (tesSUCCESS == terStatus)
|
||||||
{
|
{
|
||||||
// Create receiver node.
|
// Create receiver node.
|
||||||
|
// Last node is always an account.
|
||||||
|
|
||||||
terStatus = pushNode(
|
terStatus = pushNode(
|
||||||
STPathElement::typeAccount // Last node is always an account.
|
!!uOutCurrencyID
|
||||||
| STPathElement::typeCurrency
|
? STPathElement::typeAccount | STPathElement::typeCurrency | STPathElement::typeIssuer
|
||||||
| STPathElement::typeIssuer,
|
: STPathElement::typeAccount | STPathElement::typeCurrency,
|
||||||
uReceiverID, // Receive to output
|
uReceiverID, // Receive to output
|
||||||
uOutCurrencyID, // Desired currency
|
uOutCurrencyID, // Desired currency
|
||||||
!!uOutCurrencyID ? uReceiverID : ACCOUNT_XRP);
|
uReceiverID);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tesSUCCESS == terStatus)
|
if (tesSUCCESS == terStatus)
|
||||||
@@ -1761,19 +1807,19 @@ cLog(lsDEBUG) << boost::str(boost::format("PathState: implied: account=%s curren
|
|||||||
|
|
||||||
const unsigned int uNodes = vpnNodes.size();
|
const unsigned int uNodes = vpnNodes.size();
|
||||||
|
|
||||||
for (unsigned int uIndex = 0; tesSUCCESS == terStatus && uIndex != uNodes; ++uIndex)
|
for (unsigned int uNode = 0; tesSUCCESS == terStatus && uNode != uNodes; ++uNode)
|
||||||
{
|
{
|
||||||
const PaymentNode& pnCur = vpnNodes[uIndex];
|
const PaymentNode& pnCur = vpnNodes[uNode];
|
||||||
|
|
||||||
if (!!pnCur.uAccountID)
|
if (!!pnCur.uAccountID)
|
||||||
{
|
{
|
||||||
// Source is a ripple line
|
// Source is a ripple line
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
else if (!umForward.insert(std::make_pair(boost::make_tuple(pnCur.uAccountID, pnCur.uCurrencyID, pnCur.uIssuerID), uIndex)).second)
|
else if (!umForward.insert(std::make_pair(boost::make_tuple(pnCur.uAccountID, pnCur.uCurrencyID, pnCur.uIssuerID), uNode)).second)
|
||||||
{
|
{
|
||||||
// Failed to insert. Have a loop.
|
// Failed to insert. Have a loop.
|
||||||
cLog(lsINFO) << boost::str(boost::format("PathState: loop detected: %s")
|
cLog(lsDEBUG) << boost::str(boost::format("PathState: loop detected: %s")
|
||||||
% getJson());
|
% getJson());
|
||||||
|
|
||||||
terStatus = temBAD_PATH_LOOP;
|
terStatus = temBAD_PATH_LOOP;
|
||||||
@@ -1782,8 +1828,8 @@ cLog(lsDEBUG) << boost::str(boost::format("PathState: implied: account=%s curren
|
|||||||
}
|
}
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("PathState: in=%s/%s out=%s/%s %s")
|
cLog(lsINFO) << boost::str(boost::format("PathState: in=%s/%s out=%s/%s %s")
|
||||||
% STAmount::createHumanCurrency(uInCurrencyID)
|
% STAmount::createHumanCurrency(uMaxCurrencyID)
|
||||||
% RippleAddress::createHumanAccountID(uInIssuerID)
|
% RippleAddress::createHumanAccountID(uMaxIssuerID)
|
||||||
% STAmount::createHumanCurrency(uOutCurrencyID)
|
% STAmount::createHumanCurrency(uOutCurrencyID)
|
||||||
% RippleAddress::createHumanAccountID(uOutIssuerID)
|
% RippleAddress::createHumanAccountID(uOutIssuerID)
|
||||||
% getJson());
|
% getJson());
|
||||||
@@ -1863,23 +1909,23 @@ Json::Value PathState::getJson() const
|
|||||||
return jvPathState;
|
return jvPathState;
|
||||||
}
|
}
|
||||||
|
|
||||||
TER RippleCalc::calcNodeFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
|
TER RippleCalc::calcNodeFwd(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality)
|
||||||
{
|
{
|
||||||
const PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
const PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
|
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd> uIndex=%d") % uIndex);
|
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd> uNode=%d") % uNode);
|
||||||
|
|
||||||
TER terResult = bCurAccount
|
TER terResult = bCurAccount
|
||||||
? calcNodeAccountFwd(uIndex, pspCur, bMultiQuality)
|
? calcNodeAccountFwd(uNode, pspCur, bMultiQuality)
|
||||||
: calcNodeOfferFwd(uIndex, pspCur, bMultiQuality);
|
: calcNodeOfferFwd(uNode, pspCur, bMultiQuality);
|
||||||
|
|
||||||
if (tesSUCCESS == terResult && uIndex + 1 != pspCur->vpnNodes.size())
|
if (tesSUCCESS == terResult && uNode + 1 != pspCur->vpnNodes.size())
|
||||||
{
|
{
|
||||||
terResult = calcNodeFwd(uIndex+1, pspCur, bMultiQuality);
|
terResult = calcNodeFwd(uNode+1, pspCur, bMultiQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd< uIndex=%d terResult=%d") % uIndex % terResult);
|
cLog(lsINFO) << boost::str(boost::format("calcNodeFwd< uNode=%d terResult=%d") % uNode % terResult);
|
||||||
|
|
||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
@@ -1893,9 +1939,9 @@ TER RippleCalc::calcNodeFwd(const unsigned int uIndex, PathState::ref pspCur, co
|
|||||||
// --> [all]saWanted.mCurrency
|
// --> [all]saWanted.mCurrency
|
||||||
// --> [all]saAccount
|
// --> [all]saAccount
|
||||||
// <-> [0]saWanted.mAmount : --> limit, <-- actual
|
// <-> [0]saWanted.mAmount : --> limit, <-- actual
|
||||||
TER RippleCalc::calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality)
|
TER RippleCalc::calcNodeRev(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality)
|
||||||
{
|
{
|
||||||
PaymentNode& pnCur = pspCur->vpnNodes[uIndex];
|
PaymentNode& pnCur = pspCur->vpnNodes[uNode];
|
||||||
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
|
const bool bCurAccount = isSetBit(pnCur.uFlags, STPathElement::typeAccount);
|
||||||
TER terResult;
|
TER terResult;
|
||||||
|
|
||||||
@@ -1905,14 +1951,14 @@ TER RippleCalc::calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, co
|
|||||||
|
|
||||||
saTransferRate = STAmount::saFromRate(lesActive.rippleTransferRate(uCurIssuerID));
|
saTransferRate = STAmount::saFromRate(lesActive.rippleTransferRate(uCurIssuerID));
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRev> uIndex=%d uIssuerID=%s saTransferRate=%s")
|
cLog(lsINFO) << boost::str(boost::format("calcNodeRev> uNode=%d uIssuerID=%s saTransferRate=%s")
|
||||||
% uIndex
|
% uNode
|
||||||
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
% RippleAddress::createHumanAccountID(uCurIssuerID)
|
||||||
% saTransferRate.getFullText());
|
% saTransferRate.getFullText());
|
||||||
|
|
||||||
terResult = bCurAccount
|
terResult = bCurAccount
|
||||||
? calcNodeAccountRev(uIndex, pspCur, bMultiQuality)
|
? calcNodeAccountRev(uNode, pspCur, bMultiQuality)
|
||||||
: calcNodeOfferRev(uIndex, pspCur, bMultiQuality);
|
: calcNodeOfferRev(uNode, pspCur, bMultiQuality);
|
||||||
|
|
||||||
// Do previous.
|
// Do previous.
|
||||||
if (tesSUCCESS != terResult)
|
if (tesSUCCESS != terResult)
|
||||||
@@ -1920,14 +1966,14 @@ TER RippleCalc::calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, co
|
|||||||
// Error, don't continue.
|
// Error, don't continue.
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
else if (uIndex)
|
else if (uNode)
|
||||||
{
|
{
|
||||||
// Continue in reverse.
|
// Continue in reverse.
|
||||||
|
|
||||||
terResult = calcNodeRev(uIndex-1, pspCur, bMultiQuality);
|
terResult = calcNodeRev(uNode-1, pspCur, bMultiQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
cLog(lsINFO) << boost::str(boost::format("calcNodeRev< uIndex=%d terResult=%s/%d") % uIndex % transToken(terResult) % terResult);
|
cLog(lsINFO) << boost::str(boost::format("calcNodeRev< uNode=%d terResult=%s/%d") % uNode % transToken(terResult) % terResult);
|
||||||
|
|
||||||
return terResult;
|
return terResult;
|
||||||
}
|
}
|
||||||
@@ -2024,7 +2070,7 @@ TER RippleCalc::rippleCalc(
|
|||||||
if (!bNoRippleDirect)
|
if (!bNoRippleDirect)
|
||||||
{
|
{
|
||||||
// Direct path.
|
// Direct path.
|
||||||
// XXX Might also make a stamp bridge by default.
|
// XXX Might also make a XRP bridge by default.
|
||||||
|
|
||||||
PathState::pointer pspDirect = PathState::createPathState(
|
PathState::pointer pspDirect = PathState::createPathState(
|
||||||
vpsPaths.size(),
|
vpsPaths.size(),
|
||||||
@@ -2274,7 +2320,7 @@ TER calcOfferFill(PaymentNode& pnSrc, PaymentNode& pnDst, bool bAllowPartial)
|
|||||||
|
|
||||||
if (pnDst.saWanted.isNative())
|
if (pnDst.saWanted.isNative())
|
||||||
{
|
{
|
||||||
// Transfer stamps.
|
// Transfer XRP.
|
||||||
|
|
||||||
STAmount saSrcFunds = pnSrc.saAccount->accountHolds(pnSrc.saAccount, uint160(0), uint160(0));
|
STAmount saSrcFunds = pnSrc.saAccount->accountHolds(pnSrc.saAccount, uint160(0), uint160(0));
|
||||||
|
|
||||||
@@ -2366,7 +2412,7 @@ void TransactionEngine::calcOfferBridgeNext(
|
|||||||
|
|
||||||
if (saOfferPays.isNative())
|
if (saOfferPays.isNative())
|
||||||
{
|
{
|
||||||
// No additional fees for stamps.
|
// No additional fees for XRP.
|
||||||
|
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
@@ -2427,7 +2473,7 @@ void TransactionEngine::calcOfferBridgeNext(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// If either currency is not stamps, then also calculates vs stamp bridge.
|
// If either currency is not XRP, then also calculates vs XRP bridge.
|
||||||
// --> saWanted: Limit of how much is wanted out.
|
// --> saWanted: Limit of how much is wanted out.
|
||||||
// <-- saPay: How much to pay into the offer.
|
// <-- saPay: How much to pay into the offer.
|
||||||
// <-- saGot: How much to the offer pays out. Never more than saWanted.
|
// <-- saGot: How much to the offer pays out. Never more than saWanted.
|
||||||
|
|||||||
@@ -142,16 +142,16 @@ public:
|
|||||||
|
|
||||||
PathState::pointer pathCreate(const STPath& spPath);
|
PathState::pointer pathCreate(const STPath& spPath);
|
||||||
void pathNext(PathState::ref pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent);
|
void pathNext(PathState::ref pspCur, const int iPaths, const LedgerEntrySet& lesCheckpoint, LedgerEntrySet& lesCurrent);
|
||||||
TER calcNode(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNode(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeRev(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeFwd(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeOfferRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeOfferRev(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeOfferFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeOfferFwd(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeAccountRev(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeAccountRev(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeAccountFwd(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality);
|
TER calcNodeAccountFwd(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality);
|
||||||
TER calcNodeAdvance(const unsigned int uIndex, PathState::ref pspCur, const bool bMultiQuality, const bool bReverse);
|
TER calcNodeAdvance(const unsigned int uNode, PathState::ref pspCur, const bool bMultiQuality, const bool bReverse);
|
||||||
TER calcNodeDeliverRev(
|
TER calcNodeDeliverRev(
|
||||||
const unsigned int uIndex,
|
const unsigned int uNode,
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const uint160& uOutAccountID,
|
const uint160& uOutAccountID,
|
||||||
@@ -159,7 +159,7 @@ public:
|
|||||||
STAmount& saOutAct);
|
STAmount& saOutAct);
|
||||||
|
|
||||||
TER calcNodeDeliverFwd(
|
TER calcNodeDeliverFwd(
|
||||||
const unsigned int uIndex,
|
const unsigned int uNode,
|
||||||
PathState::ref pspCur,
|
PathState::ref pspCur,
|
||||||
const bool bMultiQuality,
|
const bool bMultiQuality,
|
||||||
const uint160& uInAccountID,
|
const uint160& uInAccountID,
|
||||||
|
|||||||
@@ -133,7 +133,8 @@
|
|||||||
FIELD(ModifiedNode, OBJECT, 5)
|
FIELD(ModifiedNode, OBJECT, 5)
|
||||||
FIELD(PreviousFields, OBJECT, 6)
|
FIELD(PreviousFields, OBJECT, 6)
|
||||||
FIELD(FinalFields, OBJECT, 7)
|
FIELD(FinalFields, OBJECT, 7)
|
||||||
FIELD(TemplateEntry, OBJECT, 8)
|
FIELD(NewFields, OBJECT, 8)
|
||||||
|
FIELD(TemplateEntry, OBJECT, 9)
|
||||||
|
|
||||||
// array of objects
|
// array of objects
|
||||||
// ARRAY/1 is reserved for end of array
|
// ARRAY/1 is reserved for end of array
|
||||||
|
|||||||
@@ -8,13 +8,17 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "HashPrefixes.h"
|
#include "HashPrefixes.h"
|
||||||
|
|
||||||
|
SETUP_LOG();
|
||||||
DECLARE_INSTANCE(SerializedTransaction);
|
DECLARE_INSTANCE(SerializedTransaction);
|
||||||
|
|
||||||
SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type)
|
SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type)
|
||||||
{
|
{
|
||||||
mFormat = TransactionFormat::getTxnFormat(type);
|
mFormat = TransactionFormat::getTxnFormat(type);
|
||||||
if (mFormat == NULL)
|
if (mFormat == NULL)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "Transaction type: " << type;
|
||||||
throw std::runtime_error("invalid transaction type");
|
throw std::runtime_error("invalid transaction type");
|
||||||
|
}
|
||||||
set(mFormat->elements);
|
set(mFormat->elements);
|
||||||
setFieldU16(sfTransactionType, mFormat->t_type);
|
setFieldU16(sfTransactionType, mFormat->t_type);
|
||||||
}
|
}
|
||||||
@@ -24,7 +28,10 @@ SerializedTransaction::SerializedTransaction(const STObject& object) : STObject(
|
|||||||
mType = static_cast<TransactionType>(getFieldU16(sfTransactionType));
|
mType = static_cast<TransactionType>(getFieldU16(sfTransactionType));
|
||||||
mFormat = TransactionFormat::getTxnFormat(mType);
|
mFormat = TransactionFormat::getTxnFormat(mType);
|
||||||
if (!mFormat)
|
if (!mFormat)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "Transaction type: " << mType;
|
||||||
throw std::runtime_error("invalid transaction type");
|
throw std::runtime_error("invalid transaction type");
|
||||||
|
}
|
||||||
if (!setType(mFormat->elements))
|
if (!setType(mFormat->elements))
|
||||||
{
|
{
|
||||||
throw std::runtime_error("transaction not valid");
|
throw std::runtime_error("transaction not valid");
|
||||||
@@ -45,7 +52,10 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject
|
|||||||
|
|
||||||
mFormat = TransactionFormat::getTxnFormat(mType);
|
mFormat = TransactionFormat::getTxnFormat(mType);
|
||||||
if (!mFormat)
|
if (!mFormat)
|
||||||
|
{
|
||||||
|
cLog(lsWARNING) << "Transaction type: " << mType;
|
||||||
throw std::runtime_error("invalid transaction type");
|
throw std::runtime_error("invalid transaction type");
|
||||||
|
}
|
||||||
if (!setType(mFormat->elements))
|
if (!setType(mFormat->elements))
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
@@ -206,10 +216,10 @@ BOOST_AUTO_TEST_CASE( STrans_test )
|
|||||||
RippleAddress publicAcct = RippleAddress::createAccountPublic(generator, 1);
|
RippleAddress publicAcct = RippleAddress::createAccountPublic(generator, 1);
|
||||||
RippleAddress privateAcct = RippleAddress::createAccountPrivate(generator, seed, 1);
|
RippleAddress privateAcct = RippleAddress::createAccountPrivate(generator, seed, 1);
|
||||||
|
|
||||||
SerializedTransaction j(ttCLAIM);
|
SerializedTransaction j(ttACCOUNT_SET);
|
||||||
j.setSourceAccount(publicAcct);
|
j.setSourceAccount(publicAcct);
|
||||||
j.setSigningPubKey(publicAcct);
|
j.setSigningPubKey(publicAcct);
|
||||||
j.setFieldVL(sfPublicKey, publicAcct.getAccountPublic());
|
j.setFieldVL(sfMessageKey, publicAcct.getAccountPublic());
|
||||||
j.sign(privateAcct);
|
j.sign(privateAcct);
|
||||||
|
|
||||||
if (!j.checkSign()) BOOST_FAIL("Transaction fails signature test");
|
if (!j.checkSign()) BOOST_FAIL("Transaction fails signature test");
|
||||||
|
|||||||
@@ -39,26 +39,32 @@ SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSi
|
|||||||
}
|
}
|
||||||
|
|
||||||
SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime,
|
SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime,
|
||||||
const RippleAddress& naPub, const RippleAddress& naPriv, bool isFull, uint256& signingHash)
|
const RippleAddress& raPub, bool isFull)
|
||||||
: STObject(sValidationFormat, sfValidation), mTrusted(false)
|
: STObject(sValidationFormat, sfValidation), mTrusted(false)
|
||||||
{
|
{ // Does not sign
|
||||||
setFieldH256(sfLedgerHash, ledgerHash);
|
setFieldH256(sfLedgerHash, ledgerHash);
|
||||||
setFieldU32(sfSigningTime, signTime);
|
setFieldU32(sfSigningTime, signTime);
|
||||||
|
|
||||||
setFieldVL(sfSigningPubKey, naPub.getNodePublic());
|
setFieldVL(sfSigningPubKey, raPub.getNodePublic());
|
||||||
mNodeID = naPub.getNodeID();
|
mNodeID = raPub.getNodeID();
|
||||||
assert(mNodeID.isNonZero());
|
assert(mNodeID.isNonZero());
|
||||||
|
|
||||||
if (!isFull)
|
if (!isFull)
|
||||||
setFlag(sFullFlag);
|
setFlag(sFullFlag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializedValidation::sign(const RippleAddress& raPriv)
|
||||||
|
{
|
||||||
|
uint256 signingHash;
|
||||||
|
sign(signingHash, raPriv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializedValidation::sign(uint256& signingHash, const RippleAddress& raPriv)
|
||||||
|
{
|
||||||
signingHash = getSigningHash();
|
signingHash = getSigningHash();
|
||||||
std::vector<unsigned char> signature;
|
std::vector<unsigned char> signature;
|
||||||
naPriv.signNodePrivate(signingHash, signature);
|
raPriv.signNodePrivate(signingHash, signature);
|
||||||
setFieldVL(sfSignature, signature);
|
setFieldVL(sfSignature, signature);
|
||||||
// XXX Check if this can fail.
|
|
||||||
// if (!RippleAddress::createNodePrivate(naSeed).signNodePrivate(getSigningHash(), mSignature.peekValue()))
|
|
||||||
// throw std::runtime_error("Unable to sign validation");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 SerializedValidation::getSigningHash() const
|
uint256 SerializedValidation::getSigningHash() const
|
||||||
@@ -90,8 +96,8 @@ bool SerializedValidation::isValid(const uint256& signingHash) const
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
RippleAddress naPublicKey = RippleAddress::createNodePublic(getFieldVL(sfSigningPubKey));
|
RippleAddress raPublicKey = RippleAddress::createNodePublic(getFieldVL(sfSigningPubKey));
|
||||||
return naPublicKey.isValid() && naPublicKey.verifyNodePublic(signingHash, getFieldVL(sfSignature));
|
return raPublicKey.isValid() && raPublicKey.verifyNodePublic(signingHash, getFieldVL(sfSignature));
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ public:
|
|||||||
|
|
||||||
// These throw if the object is not valid
|
// These throw if the object is not valid
|
||||||
SerializedValidation(SerializerIterator& sit, bool checkSignature = true);
|
SerializedValidation(SerializerIterator& sit, bool checkSignature = true);
|
||||||
SerializedValidation(const uint256& ledgerHash, uint32 signTime, const RippleAddress& naPub,
|
|
||||||
const RippleAddress& naPriv, bool isFull, uint256& signingHash);
|
// Does not sign the validation
|
||||||
|
SerializedValidation(const uint256& ledgerHash, uint32 signTime, const RippleAddress& raPub, bool isFull);
|
||||||
|
|
||||||
uint256 getLedgerHash() const;
|
uint256 getLedgerHash() const;
|
||||||
uint32 getSignTime() const;
|
uint32 getSignTime() const;
|
||||||
uint32 getFlags() const;
|
uint32 getFlags() const;
|
||||||
RippleAddress getSignerPublic() const;
|
RippleAddress getSignerPublic() const;
|
||||||
uint160 getNodeID() const { return mNodeID; }
|
uint160 getNodeID() const { return mNodeID; }
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isFull() const;
|
bool isFull() const;
|
||||||
@@ -41,6 +42,8 @@ public:
|
|||||||
void setTrusted() { mTrusted = true; }
|
void setTrusted() { mTrusted = true; }
|
||||||
std::vector<unsigned char> getSigned() const;
|
std::vector<unsigned char> getSigned() const;
|
||||||
std::vector<unsigned char> getSignature() const;
|
std::vector<unsigned char> getSignature() const;
|
||||||
|
void sign(uint256& signingHash, const RippleAddress& raPrivate);
|
||||||
|
void sign(const RippleAddress& raPrivate);
|
||||||
|
|
||||||
// The validation this replaced
|
// The validation this replaced
|
||||||
const uint256& getPreviousHash() { return mPreviousHash; }
|
const uint256& getPreviousHash() { return mPreviousHash; }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
extern LogPartition TaggedCachePartition;
|
extern LogPartition TaggedCachePartition;
|
||||||
|
|
||||||
// This class implemented a cache and a map. The cache keeps objects alive
|
// This class implements a cache and a map. The cache keeps objects alive
|
||||||
// in the map. The map allows multiple code paths that reference objects
|
// in the map. The map allows multiple code paths that reference objects
|
||||||
// with the same tag to get the same actual object.
|
// with the same tag to get the same actual object.
|
||||||
|
|
||||||
@@ -258,4 +258,4 @@ bool TaggedCache<c_Key, c_Data>::retrieve(const key_type& key, c_Data& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,13 +31,14 @@ bool TransactionMetaSet::isNodeAffected(const uint256& node) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type)
|
void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type, uint16 nodeType)
|
||||||
{ // make sure the node exists and force its type
|
{ // make sure the node exists and force its type
|
||||||
BOOST_FOREACH(STObject& it, mNodes)
|
BOOST_FOREACH(STObject& it, mNodes)
|
||||||
{
|
{
|
||||||
if (it.getFieldH256(sfLedgerIndex) == node)
|
if (it.getFieldH256(sfLedgerIndex) == node)
|
||||||
{
|
{
|
||||||
it.setFName(type);
|
it.setFName(type);
|
||||||
|
it.setFieldU16(sfLedgerEntryType, nodeType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -47,6 +48,7 @@ void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type)
|
|||||||
|
|
||||||
assert(obj.getFName() == type);
|
assert(obj.getFName() == type);
|
||||||
obj.setFieldH256(sfLedgerIndex, node);
|
obj.setFieldH256(sfLedgerIndex, node);
|
||||||
|
obj.setFieldU16(sfLedgerEntryType, nodeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public:
|
|||||||
uint32 getLgrSeq() { return mLedger; }
|
uint32 getLgrSeq() { return mLedger; }
|
||||||
|
|
||||||
bool isNodeAffected(const uint256&) const;
|
bool isNodeAffected(const uint256&) const;
|
||||||
void setAffectedNode(const uint256&, SField::ref type);
|
void setAffectedNode(const uint256&, SField::ref type, uint16 nodeType);
|
||||||
STObject& getAffectedNode(const uint256&, SField::ref type);
|
STObject& getAffectedNode(const uint256&, SField::ref type);
|
||||||
STObject& getAffectedNode(const uint256&);
|
STObject& getAffectedNode(const uint256&);
|
||||||
const STObject& peekAffectedNode(const uint256&) const;
|
const STObject& peekAffectedNode(const uint256&) const;
|
||||||
|
|||||||
@@ -97,12 +97,12 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
|||||||
uint32 now = theApp->getOPs().getNetworkTimeNC();
|
uint32 now = theApp->getOPs().getNetworkTimeNC();
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
for (ValidationSet::iterator vit = set->begin(), end = set->end(); vit != end; ++vit)
|
BOOST_FOREACH(u160_val_pair& it, *set)
|
||||||
{
|
{
|
||||||
bool isTrusted = vit->second->isTrusted();
|
bool isTrusted = it.second->isTrusted();
|
||||||
if (isTrusted && currentOnly)
|
if (isTrusted && currentOnly)
|
||||||
{
|
{
|
||||||
uint32 closeTime = vit->second->getSignTime();
|
uint32 closeTime = it.second->getSignTime();
|
||||||
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
|
if ((now < (closeTime - LEDGER_EARLY_INTERVAL)) || (now > (closeTime + LEDGER_VAL_INTERVAL)))
|
||||||
isTrusted = false;
|
isTrusted = false;
|
||||||
else
|
else
|
||||||
@@ -119,6 +119,28 @@ void ValidationCollection::getValidationCount(const uint256& ledger, bool curren
|
|||||||
cLog(lsTRACE) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
|
cLog(lsTRACE) << "VC: " << ledger << "t:" << trusted << " u:" << untrusted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ValidationCollection::getValidationTypes(const uint256& ledger, int& full, int& partial)
|
||||||
|
{
|
||||||
|
full = partial = 0;
|
||||||
|
boost::mutex::scoped_lock sl(mValidationLock);
|
||||||
|
VSpointer set = findSet(ledger);
|
||||||
|
if (set)
|
||||||
|
{
|
||||||
|
BOOST_FOREACH(u160_val_pair& it, *set)
|
||||||
|
{
|
||||||
|
if (it.second->isTrusted())
|
||||||
|
{
|
||||||
|
if (it.second->isFull())
|
||||||
|
++full;
|
||||||
|
else
|
||||||
|
++partial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cLog(lsTRACE) << "VC: " << ledger << "f:" << full << " p:" << partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
|
int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
|
||||||
{
|
{
|
||||||
int trusted = 0;
|
int trusted = 0;
|
||||||
@@ -126,9 +148,9 @@ int ValidationCollection::getTrustedValidationCount(const uint256& ledger)
|
|||||||
VSpointer set = findSet(ledger);
|
VSpointer set = findSet(ledger);
|
||||||
if (set)
|
if (set)
|
||||||
{
|
{
|
||||||
for (ValidationSet::iterator vit = set->begin(), end = set->end(); vit != end; ++vit)
|
BOOST_FOREACH(u160_val_pair& it, *set)
|
||||||
{
|
{
|
||||||
if (vit->second->isTrusted())
|
if (it.second->isTrusted())
|
||||||
++trusted;
|
++trusted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ public:
|
|||||||
bool addValidation(const SerializedValidation::pointer&);
|
bool addValidation(const SerializedValidation::pointer&);
|
||||||
ValidationSet getValidations(const uint256& ledger);
|
ValidationSet getValidations(const uint256& ledger);
|
||||||
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
|
void getValidationCount(const uint256& ledger, bool currentOnly, int& trusted, int& untrusted);
|
||||||
|
void getValidationTypes(const uint256& ledger, int& full, int& partial);
|
||||||
|
|
||||||
int getTrustedValidationCount(const uint256& ledger);
|
int getTrustedValidationCount(const uint256& ledger);
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// These classes all store their values internally
|
// These classes all store their values internally
|
||||||
// in little-endian form
|
// in big-endian form
|
||||||
|
|
||||||
inline int Testuint256AdHoc(std::vector<std::string> vArg);
|
inline int Testuint256AdHoc(std::vector<std::string> vArg);
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ protected:
|
|||||||
enum { WIDTH=BITS/32 };
|
enum { WIDTH=BITS/32 };
|
||||||
|
|
||||||
// This is really big-endian in byte order.
|
// This is really big-endian in byte order.
|
||||||
// We use unsigned int for speed.
|
// We sometimes use unsigned int for speed.
|
||||||
unsigned int pn[WIDTH];
|
unsigned int pn[WIDTH];
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -73,7 +73,7 @@ public:
|
|||||||
zero();
|
zero();
|
||||||
|
|
||||||
// Put in least significant bits.
|
// Put in least significant bits.
|
||||||
((uint64_t *) end())[-1] = htobe64(uHost);
|
((uint64_t *) end())[-1] = htobe64(uHost);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -105,10 +105,12 @@ public:
|
|||||||
base_uint& operator++()
|
base_uint& operator++()
|
||||||
{
|
{
|
||||||
// prefix operator
|
// prefix operator
|
||||||
int i = WIDTH;
|
for (int i = WIDTH - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
while (i-- && !++pn[i])
|
pn[i] = htobe32(be32toh(pn[i]) + 1);
|
||||||
;
|
if (pn[i] != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -124,10 +126,13 @@ public:
|
|||||||
|
|
||||||
base_uint& operator--()
|
base_uint& operator--()
|
||||||
{
|
{
|
||||||
int i = WIDTH;
|
for (int i = WIDTH - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
while (i-- && !pn[i]--)
|
uint32 prev = pn[i];
|
||||||
;
|
pn[i] = htobe32(be32toh(pn[i]) - 1);
|
||||||
|
if (prev != 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -169,10 +174,14 @@ public:
|
|||||||
const unsigned char* pAEnd = a.end();
|
const unsigned char* pAEnd = a.end();
|
||||||
const unsigned char* pB = b.begin();
|
const unsigned char* pB = b.begin();
|
||||||
|
|
||||||
while (pA != pAEnd && *pA == *pB)
|
while (*pA == *pB)
|
||||||
pA++, pB++;
|
{
|
||||||
|
if (++pA == pAEnd)
|
||||||
|
return 0;
|
||||||
|
++pB;
|
||||||
|
}
|
||||||
|
|
||||||
return pA == pAEnd ? 0 : *pA < *pB ? -1 : *pA > *pB ? 1 : 0;
|
return (*pA < *pB) ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend inline bool operator<(const base_uint& a, const base_uint& b)
|
friend inline bool operator<(const base_uint& a, const base_uint& b)
|
||||||
|
|||||||
@@ -530,21 +530,16 @@ Remote.prototype.request = function (request) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_server_info = function () {
|
Remote.prototype.request_server_info = function () {
|
||||||
var request = new Request(this, 'rpc');
|
return new Request(this, 'server_info');
|
||||||
|
|
||||||
request.message.command = 'server_info';
|
|
||||||
|
|
||||||
return request;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_ledger = function (params) {
|
Remote.prototype.request_ledger = function (params) {
|
||||||
// XXX Does this require the server to be trusted?
|
// XXX Does this require the server to be trusted?
|
||||||
//assert(this.trusted);
|
//assert(this.trusted);
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'ledger');
|
||||||
|
|
||||||
request.message.command = 'ledger';
|
request.message.params = params;
|
||||||
request.message.params = params;
|
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
};
|
};
|
||||||
@@ -553,21 +548,19 @@ Remote.prototype.request_ledger = function (params) {
|
|||||||
Remote.prototype.request_ledger_hash = function () {
|
Remote.prototype.request_ledger_hash = function () {
|
||||||
assert(this.trusted); // If not trusted, need to check proof.
|
assert(this.trusted); // If not trusted, need to check proof.
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
return new Request(this, 'ledger_closed');
|
||||||
|
};
|
||||||
request.message.command = 'ledger_closed';
|
|
||||||
|
|
||||||
return request;
|
// .ledger()
|
||||||
|
// .ledger_index()
|
||||||
|
Remote.prototype.request_ledger_header = function () {
|
||||||
|
return new Request(this, 'ledger_header');
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the current proposed ledger entry. May be closed (and revised) at any time (even before returning).
|
// Get the current proposed ledger entry. May be closed (and revised) at any time (even before returning).
|
||||||
// Only for unit testing.
|
// Only for unit testing.
|
||||||
Remote.prototype.request_ledger_current = function () {
|
Remote.prototype.request_ledger_current = function () {
|
||||||
var request = new Request(this, 'rpc');
|
return new Request(this, 'ledger_current');
|
||||||
|
|
||||||
request.message.command = 'ledger_current';
|
|
||||||
|
|
||||||
return request;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// --> type : the type of ledger entry.
|
// --> type : the type of ledger entry.
|
||||||
@@ -578,9 +571,7 @@ Remote.prototype.request_ledger_entry = function (type) {
|
|||||||
assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol.
|
assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol.
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'ledger_entry');
|
||||||
|
|
||||||
request.message.command = 'ledger_entry';
|
|
||||||
|
|
||||||
if (type)
|
if (type)
|
||||||
this.type = type;
|
this.type = type;
|
||||||
@@ -662,11 +653,7 @@ Remote.prototype.request_unsubscribe = function (streams) {
|
|||||||
Remote.prototype.request_transaction_entry = function (hash) {
|
Remote.prototype.request_transaction_entry = function (hash) {
|
||||||
assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol.
|
assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol.
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
return (new Request(this, 'transaction_entry'))
|
||||||
|
|
||||||
request.message.command = 'transaction_entry';
|
|
||||||
|
|
||||||
return request
|
|
||||||
.tx_hash(hash);
|
.tx_hash(hash);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -674,9 +661,8 @@ Remote.prototype.request_ripple_lines_get = function (accountID) {
|
|||||||
// XXX Does this require the server to be trusted?
|
// XXX Does this require the server to be trusted?
|
||||||
//assert(this.trusted);
|
//assert(this.trusted);
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'ripple_lines_get');
|
||||||
|
|
||||||
request.message.command = 'ripple_lines_get';
|
|
||||||
// XXX Convert API call to JSON
|
// XXX Convert API call to JSON
|
||||||
request.message.params = [accountID];
|
request.message.params = [accountID];
|
||||||
|
|
||||||
@@ -687,9 +673,8 @@ Remote.prototype.request_wallet_accounts = function (key) {
|
|||||||
// XXX Does this require the server to be trusted?
|
// XXX Does this require the server to be trusted?
|
||||||
//assert(this.trusted);
|
//assert(this.trusted);
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'wallet_accounts');
|
||||||
|
|
||||||
request.message.command = 'wallet_accounts';
|
|
||||||
// XXX Convert API call to JSON
|
// XXX Convert API call to JSON
|
||||||
request.message.params = [key];
|
request.message.params = [key];
|
||||||
|
|
||||||
@@ -700,9 +685,8 @@ Remote.prototype.request_account_tx = function (accountID, minLedger, maxLedger)
|
|||||||
// XXX Does this require the server to be trusted?
|
// XXX Does this require the server to be trusted?
|
||||||
//assert(this.trusted);
|
//assert(this.trusted);
|
||||||
|
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'account_tx');
|
||||||
|
|
||||||
request.message.command = 'account_tx';
|
|
||||||
// XXX Convert API call to JSON
|
// XXX Convert API call to JSON
|
||||||
request.message.params = [accountID, minLedger, maxLedger];
|
request.message.params = [accountID, minLedger, maxLedger];
|
||||||
|
|
||||||
@@ -751,9 +735,7 @@ Remote.prototype.submit = function (transaction) {
|
|||||||
.request();
|
.request();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var submit_request = new Request(this, 'rpc');
|
var submit_request = new Request(this, 'submit_json');
|
||||||
|
|
||||||
submit_request.message.command = 'submit_json';
|
|
||||||
|
|
||||||
submit_request.tx_json(transaction.tx_json);
|
submit_request.tx_json(transaction.tx_json);
|
||||||
submit_request.secret(transaction.secret);
|
submit_request.secret(transaction.secret);
|
||||||
@@ -808,9 +790,7 @@ Remote.prototype._server_subscribe = function () {
|
|||||||
Remote.prototype.ledger_accept = function () {
|
Remote.prototype.ledger_accept = function () {
|
||||||
if (this.stand_alone || undefined === this.stand_alone)
|
if (this.stand_alone || undefined === this.stand_alone)
|
||||||
{
|
{
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'ledger_accept');
|
||||||
|
|
||||||
request.message.command = 'ledger_accept';
|
|
||||||
|
|
||||||
request
|
request
|
||||||
.request();
|
.request();
|
||||||
@@ -957,43 +937,32 @@ Remote.prototype.request_ripple_balance = function (account, issuer, currency, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
Remote.prototype.request_unl_list = function () {
|
Remote.prototype.request_unl_list = function () {
|
||||||
var request = new Request(this, 'rpc');
|
return new Request(this, 'unl_list');
|
||||||
|
|
||||||
request.message.command = 'unl_list';
|
|
||||||
|
|
||||||
return request;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_unl_add = function (addr, note) {
|
Remote.prototype.request_unl_add = function (addr, note) {
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'unl_add');
|
||||||
|
|
||||||
request.message.command = 'unl_add';
|
|
||||||
request.message.params = [addr, note];
|
request.message.params = [addr, note];
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_unl_delete = function (publicKey) {
|
Remote.prototype.request_unl_delete = function (publicKey) {
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'unl_delete');
|
||||||
|
|
||||||
request.message.command = 'unl_delete';
|
|
||||||
request.message.params = [publicKey];
|
request.message.params = [publicKey];
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_peers = function () {
|
Remote.prototype.request_peers = function () {
|
||||||
var request = new Request(this, 'rpc');
|
return new Request(this, 'peers');
|
||||||
|
|
||||||
request.message.command = 'peers';
|
|
||||||
|
|
||||||
return request;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Remote.prototype.request_connect = function (ip, port) {
|
Remote.prototype.request_connect = function (ip, port) {
|
||||||
var request = new Request(this, 'rpc');
|
var request = new Request(this, 'connect');
|
||||||
|
|
||||||
request.message.command = 'connect';
|
|
||||||
request.message.params = [ip, port];
|
request.message.params = [ip, port];
|
||||||
|
|
||||||
return request;
|
return request;
|
||||||
@@ -1421,7 +1390,7 @@ Transaction.prototype.payment = function (src, dst, deliver_amount) {
|
|||||||
|
|
||||||
Transaction.prototype.ripple_line_set = function (src, limit, quality_in, quality_out) {
|
Transaction.prototype.ripple_line_set = function (src, limit, quality_in, quality_out) {
|
||||||
this.secret = this._account_secret(src);
|
this.secret = this._account_secret(src);
|
||||||
this.tx_json.TransactionType = 'CreditSet';
|
this.tx_json.TransactionType = 'TrustSet';
|
||||||
this.tx_json.Account = UInt160.json_rewrite(src);
|
this.tx_json.Account = UInt160.json_rewrite(src);
|
||||||
|
|
||||||
// Allow limit of 0 through.
|
// Allow limit of 0 through.
|
||||||
|
|||||||
Reference in New Issue
Block a user