Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
Arthur Britto
2013-03-26 19:02:59 -07:00
9 changed files with 130 additions and 148 deletions

View File

@@ -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");

View File

@@ -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()

View 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;
}

View File

@@ -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());
}
}
}

View File

@@ -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)