mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'master' of github.com:jedmccaleb/NewCoin
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#include <limits.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@@ -257,134 +258,77 @@ std::string STAmount::createHumanCurrency(const uint160& uCurrency)
|
||||
return sCurrency;
|
||||
}
|
||||
|
||||
// Assumes trusted input.
|
||||
bool STAmount::setValue(const std::string& sAmount)
|
||||
{ // Note: mIsNative and mCurrency must be set already!
|
||||
uint64 uValue;
|
||||
int iOffset;
|
||||
size_t uDecimal = sAmount.find_first_of(mIsNative ? "^" : ".");
|
||||
size_t uExp = uDecimal == std::string::npos ? sAmount.find_first_of("e") : std::string::npos;
|
||||
bool bInteger = uDecimal == std::string::npos && uExp == std::string::npos;
|
||||
|
||||
mIsNegative = false;
|
||||
if (bInteger)
|
||||
static boost::regex reNumber("\\`([+-]?)(\\d*)(\\.(\\d*))?([eE]([+-]?)(\\d+))?\\'");
|
||||
boost::smatch smMatch;
|
||||
|
||||
if (!boost::regex_match(sAmount, smMatch, reNumber))
|
||||
{
|
||||
// Integer input: does not necessarily mean native.
|
||||
cLog(lsWARNING) << "Number not valid: \"" << sAmount << "\"";
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
// Match fields: 0 = whole input, 1 = sign, 2 = integer portion, 3 = whole fraction (with '.')
|
||||
// 4 = fraction (without '.'), 5 = whole exponent (with 'e'), 6 = exponent sign, 7 = exponent number
|
||||
|
||||
try
|
||||
{
|
||||
if ((smMatch[2].length() + smMatch[4].length()) > 18)
|
||||
{
|
||||
int64 a = sAmount.empty() ? 0 : lexical_cast_st<int64>(sAmount);
|
||||
if (a >= 0)
|
||||
{
|
||||
uValue = static_cast<uint64>(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
uValue = static_cast<uint64>(-a);
|
||||
mIsNegative = true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cLog(lsINFO) << "Bad integer amount: " << sAmount;
|
||||
|
||||
cLog(lsWARNING) << "Overlong number: " << sAmount;
|
||||
return false;
|
||||
}
|
||||
iOffset = 0;
|
||||
}
|
||||
else if (uExp != std::string::npos)
|
||||
{
|
||||
// e input
|
||||
|
||||
try
|
||||
mIsNegative = (smMatch[1].matched && (smMatch[1] == "-"));
|
||||
|
||||
if (!smMatch[4].matched) // integer only
|
||||
{
|
||||
int64 iInteger = uExp ? lexical_cast_st<uint64>(sAmount.substr(0, uExp)) : 0;
|
||||
if (iInteger >= 0)
|
||||
{
|
||||
uValue = static_cast<uint64>(iInteger);
|
||||
}
|
||||
mValue = lexical_cast_s<uint64>(smMatch[2]);
|
||||
mOffset = 0;
|
||||
}
|
||||
else
|
||||
{ // integer and fraction
|
||||
mValue = lexical_cast_s<uint64>(smMatch[2] + smMatch[4]);
|
||||
mOffset = -(smMatch[4].length());
|
||||
}
|
||||
|
||||
if (smMatch[5].matched)
|
||||
{ // we have an exponent
|
||||
if (smMatch[6].matched && (smMatch[6] == "-"))
|
||||
mOffset -= lexical_cast_s<int>(smMatch[7]);
|
||||
else
|
||||
{
|
||||
uValue = static_cast<uint64>(-iInteger);
|
||||
mIsNegative = true;
|
||||
}
|
||||
|
||||
iOffset = lexical_cast_st<uint64>(sAmount.substr(uExp+1));
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cLog(lsINFO) << "Bad e amount: " << sAmount;
|
||||
|
||||
return false;
|
||||
mOffset += lexical_cast_s<int>(smMatch[7]);
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (...)
|
||||
{
|
||||
// Float input: has a decimal
|
||||
|
||||
// Example size decimal size-decimal offset
|
||||
// ^1 2 0 2 -1
|
||||
// 123^ 4 3 1 0
|
||||
// 1^23 4 1 3 -2
|
||||
try
|
||||
{
|
||||
iOffset = -int(sAmount.size() - uDecimal - 1);
|
||||
|
||||
// Issolate integer and fraction.
|
||||
uint64 uInteger;
|
||||
int64 iInteger = uDecimal ? lexical_cast_st<uint64>(sAmount.substr(0, uDecimal)) : 0;
|
||||
if (iInteger >= 0)
|
||||
{
|
||||
uInteger = static_cast<uint64>(iInteger);
|
||||
}
|
||||
else
|
||||
{
|
||||
uInteger = static_cast<uint64>(-iInteger);
|
||||
mIsNegative = true;
|
||||
}
|
||||
|
||||
uint64 uFraction = iOffset ? lexical_cast_st<uint64>(sAmount.substr(uDecimal+1)) : 0;
|
||||
|
||||
// Scale the integer portion to the same offset as the fraction.
|
||||
uValue = uInteger;
|
||||
for (int i = -iOffset; i--;)
|
||||
uValue *= 10;
|
||||
|
||||
// Add in the fraction.
|
||||
uValue += uFraction;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
cLog(lsINFO) << "Bad float amount: " << sAmount;
|
||||
|
||||
return false;
|
||||
}
|
||||
cLog(lsWARNING) << "Number not parsed: \"" << sAmount << "\"";
|
||||
return false;
|
||||
}
|
||||
|
||||
cLog(lsTRACE) << "Float \"" << sAmount << "\" parsed to " << mValue << " : " << mOffset;
|
||||
|
||||
if (mIsNative)
|
||||
{
|
||||
if (bInteger)
|
||||
iOffset = -SYSTEM_CURRENCY_PRECISION;
|
||||
if (smMatch[3].matched)
|
||||
mOffset -= SYSTEM_CURRENCY_PRECISION;
|
||||
|
||||
while (iOffset > -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue *= 10;
|
||||
--iOffset;
|
||||
while (mOffset > 0)
|
||||
{
|
||||
mValue *= 10;
|
||||
--mOffset;
|
||||
}
|
||||
|
||||
while (iOffset < -SYSTEM_CURRENCY_PRECISION) {
|
||||
uValue /= 10;
|
||||
++iOffset;
|
||||
while (mOffset < 0) {
|
||||
mValue /= 10;
|
||||
++mOffset;
|
||||
}
|
||||
|
||||
mValue = uValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
mValue = uValue;
|
||||
mOffset = iOffset;
|
||||
canonicalize();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1287,11 +1231,13 @@ BOOST_AUTO_TEST_CASE( setValue_test )
|
||||
{
|
||||
STAmount saTmp;
|
||||
|
||||
#if 0
|
||||
// Check native floats
|
||||
saTmp.setFullValue("1^0"); BOOST_CHECK_MESSAGE(SYSTEM_CURRENCY_PARTS == saTmp.getNValue(), "float integer failed");
|
||||
saTmp.setFullValue("0^1"); BOOST_CHECK_MESSAGE(SYSTEM_CURRENCY_PARTS/10 == saTmp.getNValue(), "float fraction failed");
|
||||
saTmp.setFullValue("0^12"); BOOST_CHECK_MESSAGE(12*SYSTEM_CURRENCY_PARTS/100 == saTmp.getNValue(), "float fraction failed");
|
||||
saTmp.setFullValue("1^2"); BOOST_CHECK_MESSAGE(SYSTEM_CURRENCY_PARTS+(2*SYSTEM_CURRENCY_PARTS/10) == saTmp.getNValue(), "float combined failed");
|
||||
#endif
|
||||
|
||||
// Check native integer
|
||||
saTmp.setFullValue("1"); BOOST_CHECK_MESSAGE(1 == saTmp.getNValue(), "integer failed");
|
||||
|
||||
@@ -564,7 +564,7 @@ Json::Value NetworkOPs::getOwnerInfo(Ledger::pointer lpLedger, const RippleAddre
|
||||
//
|
||||
|
||||
void NetworkOPs::setStateTimer()
|
||||
{ // set timer early if ledger is closing
|
||||
{
|
||||
mNetTimer.expires_from_now(boost::posix_time::milliseconds(LEDGER_GRANULARITY));
|
||||
mNetTimer.async_wait(boost::bind(&NetworkOPs::checkState, this, boost::asio::placeholders::error));
|
||||
}
|
||||
@@ -594,36 +594,41 @@ void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||
{ // Network state machine
|
||||
|
||||
if ((result == boost::asio::error::operation_aborted) || theConfig.RUN_STANDALONE)
|
||||
{
|
||||
cLog(lsFATAL) << "Network state timer error: " << result;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
ScopedLock(theApp->getMasterLock());
|
||||
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
|
||||
// do we have sufficient peers? If not, we are disconnected.
|
||||
if (peerList.size() < theConfig.NETWORK_QUORUM)
|
||||
{
|
||||
if (mMode != omDISCONNECTED)
|
||||
{
|
||||
setMode(omDISCONNECTED);
|
||||
cLog(lsWARNING) << "Node count (" << peerList.size() <<
|
||||
") has fallen below quorum (" << theConfig.NETWORK_QUORUM << ").";
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mMode == omDISCONNECTED)
|
||||
{
|
||||
setMode(omCONNECTED);
|
||||
cLog(lsINFO) << "Node count (" << peerList.size() << ") is sufficient.";
|
||||
}
|
||||
|
||||
if (!mConsensus)
|
||||
tryStartConsensus();
|
||||
|
||||
if (mConsensus)
|
||||
mConsensus->timerEntry();
|
||||
}
|
||||
|
||||
setStateTimer();
|
||||
|
||||
ScopedLock(theApp->getMasterLock());
|
||||
|
||||
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||
|
||||
// do we have sufficient peers? If not, we are disconnected.
|
||||
if (peerList.size() < theConfig.NETWORK_QUORUM)
|
||||
{
|
||||
if (mMode != omDISCONNECTED)
|
||||
{
|
||||
setMode(omDISCONNECTED);
|
||||
cLog(lsWARNING) << "Node count (" << peerList.size() <<
|
||||
") has fallen below quorum (" << theConfig.NETWORK_QUORUM << ").";
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (mMode == omDISCONNECTED)
|
||||
{
|
||||
setMode(omCONNECTED);
|
||||
cLog(lsINFO) << "Node count (" << peerList.size() << ") is sufficient.";
|
||||
}
|
||||
|
||||
if (!mConsensus)
|
||||
tryStartConsensus();
|
||||
|
||||
if (mConsensus)
|
||||
mConsensus->timerEntry();
|
||||
}
|
||||
|
||||
void NetworkOPs::tryStartConsensus()
|
||||
|
||||
11
src/cpp/ripple/TransactionCheck.cpp
Normal file
11
src/cpp/ripple/TransactionCheck.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
#include "TransactionErr.h"
|
||||
#include "TransactionEngine.h"
|
||||
|
||||
// Double check a transaction's metadata to make sure no system invariants were broken
|
||||
// Call right before 'calcRawMeta'
|
||||
|
||||
bool TransactionEngine::checkInvariants(TER result, const SerializedTransaction& txn, TransactionEngineParams params)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -93,7 +93,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
}
|
||||
#endif
|
||||
|
||||
UPTR_T<Transactor> transactor = Transactor::makeTransactor(txn,params,this);
|
||||
UPTR_T<Transactor> transactor = Transactor::makeTransactor(txn, params, this);
|
||||
if (transactor.get() != NULL)
|
||||
{
|
||||
uint256 txID = txn.getTransactionID();
|
||||
@@ -153,28 +153,39 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
|
||||
|
||||
if (didApply)
|
||||
{
|
||||
// Transaction succeeded fully or (retries are not allowed and the transaction could claim a fee)
|
||||
Serializer m;
|
||||
mNodes.calcRawMeta(m, terResult, mTxnSeq++);
|
||||
|
||||
txnWrite();
|
||||
|
||||
Serializer s;
|
||||
txn.add(s);
|
||||
|
||||
if (isSetBit(params, tapOPEN_LEDGER))
|
||||
if (!checkInvariants(terResult, txn, params))
|
||||
{
|
||||
if (!mLedger->addTransaction(txID, s))
|
||||
assert(false);
|
||||
cLog(lsFATAL) << "Transaction violates invariants";
|
||||
cLog(lsFATAL) << txn.getJson(0);
|
||||
cLog(lsFATAL) << transToken(terResult) << ": " << transHuman(terResult);
|
||||
cLog(lsFATAL) << mNodes.getJson(0);
|
||||
didApply = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mLedger->addTransaction(txID, s, m))
|
||||
// Transaction succeeded fully or (retries are not allowed and the transaction could claim a fee)
|
||||
Serializer m;
|
||||
mNodes.calcRawMeta(m, terResult, mTxnSeq++);
|
||||
|
||||
txnWrite();
|
||||
|
||||
Serializer s;
|
||||
txn.add(s);
|
||||
|
||||
if (isSetBit(params, tapOPEN_LEDGER))
|
||||
{
|
||||
if (!mLedger->addTransaction(txID, s))
|
||||
assert(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mLedger->addTransaction(txID, s, m))
|
||||
assert(false);
|
||||
|
||||
// Charge whatever fee they specified.
|
||||
STAmount saPaid = txn.getTransactionFee();
|
||||
mLedger->destroyCoins(saPaid.getNValue());
|
||||
// Charge whatever fee they specified.
|
||||
STAmount saPaid = txn.getTransactionFee();
|
||||
mLedger->destroyCoins(saPaid.getNValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
void entryModify(SLE::ref sleEntry) { mNodes.entryModify(sleEntry); }
|
||||
|
||||
TER applyTransaction(const SerializedTransaction&, TransactionEngineParams, bool& didApply);
|
||||
bool checkInvariants(TER result, const SerializedTransaction& txn, TransactionEngineParams params);
|
||||
};
|
||||
|
||||
inline TransactionEngineParams operator|(const TransactionEngineParams& l1, const TransactionEngineParams& l2)
|
||||
|
||||
Reference in New Issue
Block a user