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

This commit is contained in:
Arthur Britto
2012-11-13 02:32:48 -08:00
17 changed files with 257 additions and 843 deletions

View File

@@ -181,9 +181,9 @@ bool TransactionAcquire::takeNodes(const std::list<SHAMapNode>& nodeIDs,
}
void LCTransaction::setVote(const uint160& peer, bool votesYes)
{ // Tracke a peer's yes/no vote on a particular disputed transaction
std::pair<boost::unordered_map<uint160, bool>::iterator, bool> res =
mVotes.insert(std::make_pair<uint160, bool>(peer, votesYes));
{ // Track a peer's yes/no vote on a particular disputed transaction
std::pair<boost::unordered_map<const uint160, bool>::iterator, bool> res =
mVotes.insert(std::pair<const uint160, bool>(peer, votesYes));
if (res.second)
{ // new vote

View File

@@ -2,9 +2,16 @@
#include <string>
#include <boost/test/unit_test.hpp>
#include <boost/format.hpp>
#include <openssl/rand.h>
#include "Serializer.h"
#include "Log.h"
SETUP_LOG();
const uint256 ProofOfWork::sMinTarget("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
const int ProofOfWork::sMaxIterations(1 << 23);
@@ -16,26 +23,35 @@ bool ProofOfWork::isValid() const
uint64 ProofOfWork::getDifficulty(const uint256& target, int iterations)
{ // 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");
}
// 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();
while (*ptr == 0)
{
difficulty *= 16;
ptr++;
difficulty *= 256;
++ptr;
}
// If the first digit after a zero isn't an F, multiply
difficulty *= (16 - *ptr);
difficulty = (difficulty * 256) / (*ptr + 1);
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
{
if (!isValid())
@@ -44,23 +60,94 @@ uint256 ProofOfWork::solve(int maxIterations) const
uint256 nonce;
RAND_bytes(nonce.begin(), nonce.size());
Serializer s1, s2;
std::vector<unsigned char> buf;
buf.reserve((256 / 8) * mIterations);
std::vector<uint256> buf2;
buf2.resize(mIterations);
while (maxIterations > 8)
std::vector<uint256> buf1;
buf1.resize(3);
buf1[0] = mChallenge;
while (maxIterations > 0)
{
s1.add256(mChallenge);
s1.add256(nonce);
// uint256 base = s1.getSHA512Half();
for (int i = 0; i < mIterations; ++i)
buf1[1] = nonce;
buf1[2] = uint256();
for (int i = (mIterations - 1); i >= 0; --i)
{
// WRITEME
buf1[2] = getSHA512Half(buf1);
buf2[i] = buf1[2];
}
s1.erase();
nonce++;
if (getSHA512Half(buf2) <= mTarget)
return nonce;
++nonce;
--maxIterations;
}
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);
}
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");
}
BOOST_AUTO_TEST_SUITE_END()
// vim:ts=4

View File

@@ -10,6 +10,15 @@
#include "uint256.h"
enum POWResult
{
powOK = 0,
powREUSED = 1,
powBADNONCE = 2,
powBADTOKEN = 3,
powEXPIRED = 4,
};
class ProofOfWork
{
protected:
@@ -48,12 +57,13 @@ protected:
int mIterations;
uint256 mTarget;
time_t mLastDifficultyChange;
int mValidTime;
powMap_t mSolvedChallenges;
boost::mutex mLock;
public:
ProofOfWorkGenerator(const uint256& secret);
ProofOfWorkGenerator();
ProofOfWork getProof();
bool checkProof(const std::string& token, const uint256& solution);
@@ -64,3 +74,5 @@ public:
};
#endif
// vim:ts=4

View File

@@ -1,3 +1,6 @@
#ifndef __RPC_h__
#define __RPC_h__
#include <string>
#include <map>
@@ -37,3 +40,5 @@ extern std::string HTTPReply(int nStatus, const std::string& strMsg);
extern std::string JSONRPCReply(const Json::Value& result, const Json::Value& error, const Json::Value& id);
extern Json::Value JSONRPCError(int code, const std::string& message);
#endif

View File

@@ -541,6 +541,7 @@ Json::Value RPCHandler::doPeers(const Json::Value& params)
// Prior to running allow each to have a credit line of what they will be getting from the other account.
Json::Value RPCHandler::doProfile(const Json::Value &params)
{
/* need to fix now that sharedOfferCreate is gone
int iArgs = params.size();
RippleAddress naSeedA;
RippleAddress naAccountA;
@@ -620,7 +621,8 @@ Json::Value RPCHandler::doProfile(const Json::Value &params)
obj["end"] = boost::posix_time::to_simple_string(ptEnd);
obj["interval"] = boost::posix_time::to_simple_string(tdInterval);
obj["rate_per_second"] = fRate;
*/
Json::Value obj(Json::objectValue);
return obj;
}

View File

@@ -8,13 +8,17 @@
#include "Log.h"
#include "HashPrefixes.h"
SETUP_LOG();
DECLARE_INSTANCE(SerializedTransaction);
SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type)
{
mFormat = TransactionFormat::getTxnFormat(type);
if (mFormat == NULL)
{
cLog(lsWARNING) << "Transaction type: " << type;
throw std::runtime_error("invalid transaction type");
}
set(mFormat->elements);
setFieldU16(sfTransactionType, mFormat->t_type);
}
@@ -24,7 +28,10 @@ SerializedTransaction::SerializedTransaction(const STObject& object) : STObject(
mType = static_cast<TransactionType>(getFieldU16(sfTransactionType));
mFormat = TransactionFormat::getTxnFormat(mType);
if (!mFormat)
{
cLog(lsWARNING) << "Transaction type: " << mType;
throw std::runtime_error("invalid transaction type");
}
if (!setType(mFormat->elements))
{
throw std::runtime_error("transaction not valid");
@@ -45,7 +52,10 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject
mFormat = TransactionFormat::getTxnFormat(mType);
if (!mFormat)
{
cLog(lsWARNING) << "Transaction type: " << mType;
throw std::runtime_error("invalid transaction type");
}
if (!setType(mFormat->elements))
{
assert(false);
@@ -206,10 +216,10 @@ BOOST_AUTO_TEST_CASE( STrans_test )
RippleAddress publicAcct = RippleAddress::createAccountPublic(generator, 1);
RippleAddress privateAcct = RippleAddress::createAccountPrivate(generator, seed, 1);
SerializedTransaction j(ttCLAIM);
SerializedTransaction j(ttACCOUNT_SET);
j.setSourceAccount(publicAcct);
j.setSigningPubKey(publicAcct);
j.setFieldVL(sfPublicKey, publicAcct.getAccountPublic());
j.setFieldVL(sfMessageKey, publicAcct.getAccountPublic());
j.sign(privateAcct);
if (!j.checkSign()) BOOST_FAIL("Transaction fails signature test");

View File

@@ -131,7 +131,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
if (TaggedCachePartition.doLog(lsTRACE) && (mapRemovals || cacheRemovals))
Log(lsTRACE, TaggedCachePartition) << mName << ": cache = " << mCache.size() << "-" << cacheRemovals <<
", map = " << mMap.size() << "-" << mapRemovals;
", map = " << mMap.size() << "-" << mapRemovals;
}
template<typename c_Key, typename c_Data> bool TaggedCache<c_Key, c_Data>::touch(const key_type& key)
@@ -230,7 +230,7 @@ boost::shared_ptr<c_Data> TaggedCache<c_Key, c_Data>::fetch(const key_type& key)
mMap.erase(mit);
return cachedData;
}
// Valid in map, is it in the cache?
typename boost::unordered_map<key_type, cache_entry>::iterator cit = mCache.find(key);
if (cit != mCache.end())

View File

@@ -106,441 +106,9 @@ bool Transaction::sign(const RippleAddress& naAccountPrivate)
return bResult;
}
//
// AccountSet
//
Transaction::pointer Transaction::setAccountSet(
const RippleAddress& naPrivateKey,
bool bEmailHash,
const uint128& uEmailHash,
bool bWalletLocator,
const uint256& uWalletLocator,
const uint32 uWalletSize,
const RippleAddress& naMessagePublic,
bool bDomain,
const std::vector<unsigned char>& vucDomain,
bool bTransferRate,
const uint32 uTransferRate)
{
if (!bEmailHash)
mTransaction->setFieldH128(sfEmailHash, uEmailHash);
if (!bWalletLocator)
{
mTransaction->setFieldH256(sfWalletLocator, uWalletLocator);
mTransaction->setFieldU32(sfWalletSize, uWalletSize);
}
if (naMessagePublic.isValid())
mTransaction->setFieldVL(sfMessageKey, naMessagePublic.getAccountPublic());
if (bDomain)
mTransaction->setFieldVL(sfDomain, vucDomain);
if (bTransferRate)
mTransaction->setFieldU32(sfTransferRate, uTransferRate);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedAccountSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
bool bEmailHash,
const uint128& uEmailHash,
bool bWalletLocator,
const uint256& uWalletLocator,
const uint32 uWalletSize,
const RippleAddress& naMessagePublic,
bool bDomain,
const std::vector<unsigned char>& vucDomain,
bool bTransferRate,
const uint32 uTransferRate)
{
pointer tResult = boost::make_shared<Transaction>(ttACCOUNT_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setAccountSet(naPrivateKey, bEmailHash, uEmailHash,
bWalletLocator, uWalletLocator, uWalletSize,
naMessagePublic,
bDomain, vucDomain, bTransferRate, uTransferRate);
}
//
// Claim
//
Transaction::pointer Transaction::setClaim(
const RippleAddress& naPrivateKey,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature)
{
mTransaction->setFieldVL(sfGenerator, vucGenerator);
mTransaction->setFieldVL(sfPublicKey, vucPubKey);
mTransaction->setFieldVL(sfSignature, vucSignature);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedClaim(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
uint32 uSourceTag,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature)
{
pointer tResult = boost::make_shared<Transaction>(ttCLAIM,
naPublicKey, naPublicKey,
0, // Sequence of 0.
0, // Free.
uSourceTag);
return tResult->setClaim(naPrivateKey, vucGenerator, vucPubKey, vucSignature);
}
//
// Create
//
Transaction::pointer Transaction::setCreate(
const RippleAddress& naPrivateKey,
const RippleAddress& naCreateAccountID,
const STAmount& saFund)
{
mTransaction->setFieldU32(sfFlags, tfCreateAccount);
mTransaction->setFieldAccount(sfDestination, naCreateAccountID);
mTransaction->setFieldAmount(sfAmount, saFund);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedCreate(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naCreateAccountID,
const STAmount& saFund)
{
pointer tResult = boost::make_shared<Transaction>(ttPAYMENT, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setCreate(naPrivateKey, naCreateAccountID, saFund);
}
//
// CreditSet
//
Transaction::pointer Transaction::setCreditSet(
const RippleAddress& naPrivateKey,
const STAmount& saLimitAmount,
bool bQualityIn,
uint32 uQualityIn,
bool bQualityOut,
uint32 uQualityOut)
{
mTransaction->setFieldAmount(sfLimitAmount, saLimitAmount);
if (bQualityIn)
mTransaction->setFieldU32(sfQualityIn, uQualityIn);
if (bQualityOut)
mTransaction->setFieldU32(sfQualityOut, uQualityOut);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedCreditSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const STAmount& saLimitAmount,
bool bQualityIn,
uint32 uQualityIn,
bool bQualityOut,
uint32 uQualityOut)
{
pointer tResult = boost::make_shared<Transaction>(ttCREDIT_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setCreditSet(naPrivateKey,
saLimitAmount,
bQualityIn, uQualityIn,
bQualityOut, uQualityOut);
}
//
// NicknameSet
//
Transaction::pointer Transaction::setNicknameSet(
const RippleAddress& naPrivateKey,
const uint256& uNickname,
bool bSetOffer,
const STAmount& saMinimumOffer)
{
mTransaction->setFieldH256(sfNickname, uNickname);
// XXX Make sure field is present even for 0!
if (bSetOffer)
mTransaction->setFieldAmount(sfMinimumOffer, saMinimumOffer);
sign(naPrivateKey);
return shared_from_this();
}
// --> bSetOffer: true, change offer
// --> saMinimumOffer: 0 to remove.
Transaction::pointer Transaction::sharedNicknameSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const uint256& uNickname,
bool bSetOffer,
const STAmount& saMinimumOffer)
{
pointer tResult = boost::make_shared<Transaction>(ttNICKNAME_SET, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setNicknameSet(naPrivateKey, uNickname, bSetOffer, saMinimumOffer);
}
//
// OfferCreate
//
Transaction::pointer Transaction::setOfferCreate(
const RippleAddress& naPrivateKey,
bool bPassive,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
uint32 uExpiration)
{
if (bPassive)
mTransaction->setFieldU32(sfFlags, tfPassive);
mTransaction->setFieldAmount(sfTakerPays, saTakerPays);
mTransaction->setFieldAmount(sfTakerGets, saTakerGets);
if (uExpiration)
mTransaction->setFieldU32(sfExpiration, uExpiration);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedOfferCreate(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
bool bPassive,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
uint32 uExpiration)
{
pointer tResult = boost::make_shared<Transaction>(ttOFFER_CREATE, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setOfferCreate(naPrivateKey, bPassive, saTakerPays, saTakerGets, uExpiration);
}
//
// OfferCancel
//
Transaction::pointer Transaction::setOfferCancel(
const RippleAddress& naPrivateKey,
uint32 uSequence)
{
mTransaction->setFieldU32(sfOfferSequence, uSequence);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedOfferCancel(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
uint32 uSequence)
{
pointer tResult = boost::make_shared<Transaction>(ttOFFER_CANCEL, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setOfferCancel(naPrivateKey, uSequence);
}
//
// PasswordFund
//
Transaction::pointer Transaction::setPasswordFund(
const RippleAddress& naPrivateKey,
const RippleAddress& naDstAccountID)
{
mTransaction->setFieldAccount(sfDestination, naDstAccountID);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedPasswordFund(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naDstAccountID)
{
pointer tResult = boost::make_shared<Transaction>(ttPASSWORD_FUND, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setPasswordFund(naPrivateKey, naDstAccountID);
}
//
// PasswordSet
//
Transaction::pointer Transaction::setPasswordSet(
const RippleAddress& naPrivateKey,
const RippleAddress& naAuthKeyID,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature)
{
mTransaction->setFieldAccount(sfAuthorizedKey, naAuthKeyID);
mTransaction->setFieldVL(sfGenerator, vucGenerator);
mTransaction->setFieldVL(sfPublicKey, vucPubKey);
mTransaction->setFieldVL(sfSignature, vucSignature);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedPasswordSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
uint32 uSourceTag,
const RippleAddress& naAuthKeyID,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature)
{
pointer tResult = boost::make_shared<Transaction>(ttPASSWORD_SET,
naPublicKey, naPublicKey,
0, // Sequence of 0.
0, // Free.
uSourceTag);
return tResult->setPasswordSet(naPrivateKey, naAuthKeyID, vucGenerator, vucPubKey, vucSignature);
}
//
// Payment
//
Transaction::pointer Transaction::setPayment(
const RippleAddress& naPrivateKey,
const RippleAddress& naDstAccountID,
const STAmount& saAmount,
const STAmount& saSendMax,
const STPathSet& spsPaths,
const bool bPartial,
const bool bLimit)
{
mTransaction->setFieldAccount(sfDestination, naDstAccountID);
mTransaction->setFieldAmount(sfAmount, saAmount);
if (saAmount != saSendMax || saAmount.getCurrency() != saSendMax.getCurrency())
{
mTransaction->setFieldAmount(sfSendMax, saSendMax);
}
if (spsPaths.getPathCount())
{
mTransaction->setFieldPathSet(sfPaths, spsPaths);
}
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedPayment(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naDstAccountID,
const STAmount& saAmount,
const STAmount& saSendMax,
const STPathSet& spsPaths,
const bool bPartial,
const bool bLimit)
{
pointer tResult = boost::make_shared<Transaction>(ttPAYMENT, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setPayment(naPrivateKey, naDstAccountID, saAmount, saSendMax, spsPaths, bPartial, bLimit);
}
//
// WalletAdd
//
Transaction::pointer Transaction::setWalletAdd(
const RippleAddress& naPrivateKey,
const STAmount& saAmount,
const RippleAddress& naAuthKeyID,
const RippleAddress& naNewPubKey,
const std::vector<unsigned char>& vucSignature)
{
mTransaction->setFieldAmount(sfAmount, saAmount);
mTransaction->setFieldAccount(sfAuthorizedKey, naAuthKeyID);
mTransaction->setFieldVL(sfPublicKey, naNewPubKey.getAccountPublic());
mTransaction->setFieldVL(sfSignature, vucSignature);
sign(naPrivateKey);
return shared_from_this();
}
Transaction::pointer Transaction::sharedWalletAdd(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const STAmount& saAmount,
const RippleAddress& naAuthKeyID,
const RippleAddress& naNewPubKey,
const std::vector<unsigned char>& vucSignature)
{
pointer tResult = boost::make_shared<Transaction>(ttWALLET_ADD, naPublicKey, naSourceAccount, uSeq, saFee, uSourceTag);
return tResult->setWalletAdd(naPrivateKey, saAmount, naAuthKeyID, naNewPubKey, vucSignature);
}
//
// Misc.

View File

@@ -58,82 +58,6 @@ private:
SerializedTransaction::pointer mTransaction;
Transaction::pointer setAccountSet(
const RippleAddress& naPrivateKey,
bool bEmailHash,
const uint128& uEmailHash,
bool bWalletLocator,
const uint256& uWalletLocator,
const uint32 uWalletSize,
const RippleAddress& naMessagePublic,
bool bDomain,
const std::vector<unsigned char>& vucDomain,
bool bTransferRate,
const uint32 uTransferRate);
Transaction::pointer setClaim(
const RippleAddress& naPrivateKey,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature);
Transaction::pointer setCreate(
const RippleAddress& naPrivateKey,
const RippleAddress& naCreateAccountID,
const STAmount& saFund);
Transaction::pointer setCreditSet(
const RippleAddress& naPrivateKey,
const STAmount& saLimitAmount,
bool bQualityIn,
uint32 uQualityIn,
bool bQualityOut,
uint32 uQualityOut);
Transaction::pointer setNicknameSet(
const RippleAddress& naPrivateKey,
const uint256& uNickname,
bool bSetOffer,
const STAmount& saMinimumOffer);
Transaction::pointer setOfferCreate(
const RippleAddress& naPrivateKey,
bool bPassive,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
uint32 uExpiration);
Transaction::pointer setOfferCancel(
const RippleAddress& naPrivateKey,
uint32 uSequence);
Transaction::pointer setPasswordFund(
const RippleAddress& naPrivateKey,
const RippleAddress& naDstAccountID);
Transaction::pointer setPasswordSet(
const RippleAddress& naPrivateKey,
const RippleAddress& naAuthKeyID,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature);
Transaction::pointer setPayment(
const RippleAddress& naPrivateKey,
const RippleAddress& naDstAccountID,
const STAmount& saAmount,
const STAmount& saSendMax,
const STPathSet& spsPaths,
const bool bPartial,
const bool bLimit);
Transaction::pointer setWalletAdd(
const RippleAddress& naPrivateKey,
const STAmount& saAmount,
const RippleAddress& naAuthKeyID,
const RippleAddress& naNewPubKey,
const std::vector<unsigned char>& vucSignature);
public:
Transaction(SerializedTransaction::ref st, bool bValidate);
@@ -148,130 +72,6 @@ public:
const STAmount& saFee, // Transaction fee.
uint32 uSourceTag); // User call back value.
// Change account settings.
static Transaction::pointer sharedAccountSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
bool bEmailHash,
const uint128& uEmailHash,
bool bWalletLocator,
const uint256& uWalletLocator,
const uint32 uWalletSize,
const RippleAddress& naMessagePublic,
bool bDomain,
const std::vector<unsigned char>& vucDomain,
bool bTransferRate,
const uint32 uTransferRate);
// Claim a wallet.
static Transaction::pointer sharedClaim(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
uint32 uSourceTag,
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature);
// Create an account.
static Transaction::pointer sharedCreate(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naCreateAccountID, // Account to create.
const STAmount& saFund); // Initial funds in XNC.
// Set credit limit and borrow fees.
static Transaction::pointer sharedCreditSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const STAmount& saLimitAmount,
bool bQualityIn,
uint32 uQualityIn,
bool bQualityOut,
uint32 uQualityOut);
// Set Nickname
static Transaction::pointer sharedNicknameSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const uint256& uNickname,
bool bSetOffer,
const STAmount& saMinimumOffer);
// Pre-fund password change.
static Transaction::pointer sharedPasswordFund(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naDstAccountID);
// Change a password.
static Transaction::pointer sharedPasswordSet(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
uint32 uSourceTag,
const RippleAddress& naAuthKeyID, // ID of regular public to auth.
const std::vector<unsigned char>& vucGenerator,
const std::vector<unsigned char>& vucPubKey,
const std::vector<unsigned char>& vucSignature);
// Make a payment.
static Transaction::pointer sharedPayment(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const RippleAddress& naDstAccountID,
const STAmount& saAmount,
const STAmount& saSendMax,
const STPathSet& spsPaths,
const bool bPartial = false,
const bool bLimit = false);
// Place an offer.
static Transaction::pointer sharedOfferCreate(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
bool bPassive,
const STAmount& saTakerPays,
const STAmount& saTakerGets,
uint32 uExpiration);
// Cancel an offer
static Transaction::pointer sharedOfferCancel(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
uint32 uSequence);
// Add an account to a wallet.
static Transaction::pointer sharedWalletAdd(
const RippleAddress& naPublicKey, const RippleAddress& naPrivateKey,
const RippleAddress& naSourceAccount,
uint32 uSeq,
const STAmount& saFee,
uint32 uSourceTag,
const STAmount& saAmount, // Initial funds in XNC.
const RippleAddress& naAuthKeyID, // ID of regular public to auth.
const RippleAddress& naNewPubKey, // Public key of new account
const std::vector<unsigned char>& vucSignature); // Proof know new account's private key.
bool sign(const RippleAddress& naAccountPrivate);
bool checkSign() const;

View File

@@ -28,7 +28,7 @@ TER TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMus
// Verify that submitter knows the private key for the generator.
// Otherwise, people could deny access to generators.
//
/* JED: taking out generator stuff until we have a better idea of how people will use this
std::vector<unsigned char> vucCipher = txn.getFieldVL(sfGenerator);
std::vector<unsigned char> vucPubKey = txn.getFieldVL(sfPublicKey);
std::vector<unsigned char> vucSignature = txn.getFieldVL(sfSignature);
@@ -42,6 +42,7 @@ TER TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMus
return tefBAD_GEN_AUTH;
}
// Create generator.
uint160 hGeneratorID = naAccountPublic.getAccountID();
@@ -69,6 +70,8 @@ TER TransactionEngine::setAuthorized(const SerializedTransaction& txn, bool bMus
? hGeneratorID // Claim
: txn.getFieldAccount160(sfAuthorizedKey); // PasswordSet
*/
uint160 uAuthKeyID=txn.getFieldAccount160(sfAuthorizedKey);
mTxnAccount->setFieldAccount(sfAuthorizedKey, uAuthKeyID);
return tesSUCCESS;
@@ -196,17 +199,18 @@ TER TransactionEngine::doClaim(const SerializedTransaction& txn)
{
Log(lsINFO) << "doClaim>";
TER terResult = setAuthorized(txn, true);
//TER terResult = setAuthorized(txn, true);
TER terResult=tefEXCEPTION;
Log(lsINFO) << "doClaim<";
return terResult;
}
TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
TER TransactionEngine::doTrustSet(const SerializedTransaction& txn)
{
TER terResult = tesSUCCESS;
Log(lsINFO) << "doCreditSet>";
Log(lsINFO) << "doTrustSet>";
const STAmount saLimitAmount = txn.getFieldAmount(sfLimitAmount);
const bool bQualityIn = txn.isFieldPresent(sfQualityIn);
@@ -222,19 +226,19 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
if (saLimitAmount.isNegative())
{
Log(lsINFO) << "doCreditSet: Malformed transaction: Negatived credit limit.";
Log(lsINFO) << "doTrustSet: Malformed transaction: Negatived credit limit.";
return temBAD_AMOUNT;
}
else if (!uDstAccountID)
{
Log(lsINFO) << "doCreditSet: Malformed transaction: Destination account not specifed.";
Log(lsINFO) << "doTrustSet: Malformed transaction: Destination account not specified.";
return temDST_NEEDED;
}
else if (mTxnAccountID == uDstAccountID)
{
Log(lsINFO) << "doCreditSet: Malformed transaction: Can not extend credit to self.";
Log(lsINFO) << "doTrustSet: Malformed transaction: Can not extend credit to self.";
return temDST_IS_SRC;
}
@@ -242,7 +246,7 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
SLE::pointer sleDst = entryCache(ltACCOUNT_ROOT, Ledger::getAccountRootIndex(uDstAccountID));
if (!sleDst)
{
Log(lsINFO) << "doCreditSet: Delay transaction: Destination account does not exist.";
Log(lsINFO) << "doTrustSet: Delay transaction: Destination account does not exist.";
return terNO_DST;
}
@@ -311,12 +315,12 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
entryModify(sleRippleState);
}
Log(lsINFO) << "doCreditSet: Modifying ripple line: bDelIndex=" << bDelIndex;
Log(lsINFO) << "doTrustSet: Modifying ripple line: bDelIndex=" << bDelIndex;
}
// Line does not exist.
else if (!saLimitAmount)
{
Log(lsINFO) << "doCreditSet: Redundant: Setting non-existant ripple line to 0.";
Log(lsINFO) << "doTrustSet: Redundant: Setting non-existent ripple line to 0.";
return terNO_LINE_NO_ZERO;
}
@@ -325,7 +329,7 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
// Create a new ripple line.
sleRippleState = entryCreate(ltRIPPLE_STATE, Ledger::getRippleStateIndex(mTxnAccountID, uDstAccountID, uCurrencyID));
Log(lsINFO) << "doCreditSet: Creating ripple line: " << sleRippleState->getIndex().ToString();
Log(lsINFO) << "doTrustSet: Creating ripple line: " << sleRippleState->getIndex().ToString();
sleRippleState->setFieldAmount(sfBalance, STAmount(uCurrencyID, ACCOUNT_ONE)); // Zero balance in currency.
sleRippleState->setFieldAmount(bFlipped ? sfHighLimit : sfLowLimit, saLimitAllow);
@@ -344,57 +348,13 @@ TER TransactionEngine::doCreditSet(const SerializedTransaction& txn)
terResult = mNodes.dirAdd(uSrcRef, Ledger::getOwnerDirIndex(uDstAccountID), sleRippleState->getIndex());
}
Log(lsINFO) << "doCreditSet<";
Log(lsINFO) << "doTrustSet<";
return terResult;
}
TER TransactionEngine::doNicknameSet(const SerializedTransaction& txn)
{
std::cerr << "doNicknameSet>" << std::endl;
const uint256 uNickname = txn.getFieldH256(sfNickname);
const bool bMinOffer = txn.isFieldPresent(sfMinimumOffer);
const STAmount saMinOffer = bMinOffer ? txn.getFieldAmount(sfAmount) : STAmount();
SLE::pointer sleNickname = entryCache(ltNICKNAME, uNickname);
if (sleNickname)
{
// Edit old entry.
sleNickname->setFieldAccount(sfAccount, mTxnAccountID);
if (bMinOffer && saMinOffer)
{
sleNickname->setFieldAmount(sfMinimumOffer, saMinOffer);
}
else
{
sleNickname->makeFieldAbsent(sfMinimumOffer);
}
entryModify(sleNickname);
}
else
{
// Make a new entry.
// XXX Need to include authorization limiting for first year.
sleNickname = entryCreate(ltNICKNAME, Ledger::getNicknameIndex(uNickname));
std::cerr << "doNicknameSet: Creating nickname node: " << sleNickname->getIndex().ToString() << std::endl;
sleNickname->setFieldAccount(sfAccount, mTxnAccountID);
if (bMinOffer && saMinOffer)
sleNickname->setFieldAmount(sfMinimumOffer, saMinOffer);
}
std::cerr << "doNicknameSet<" << std::endl;
return tesSUCCESS;
}
/*
TER TransactionEngine::doPasswordFund(const SerializedTransaction& txn)
{
std::cerr << "doPasswordFund>" << std::endl;
@@ -428,14 +388,16 @@ TER TransactionEngine::doPasswordFund(const SerializedTransaction& txn)
return tesSUCCESS;
}
*/
TER TransactionEngine::doPasswordSet(const SerializedTransaction& txn)
// TODO: change to take a fee if there is one there
TER TransactionEngine::doRegularKeySet(const SerializedTransaction& txn)
{
std::cerr << "doPasswordSet>" << std::endl;
std::cerr << "doRegularKeySet>" << std::endl;
if (mTxnAccount->getFlags() & lsfPasswordSpent)
{
std::cerr << "doPasswordSet: Delay transaction: Funds already spent." << std::endl;
std::cerr << "doRegularKeySet: Delay transaction: Funds already spent." << std::endl;
return terFUNDS_SPENT;
}
@@ -444,7 +406,7 @@ TER TransactionEngine::doPasswordSet(const SerializedTransaction& txn)
TER terResult = setAuthorized(txn, false);
std::cerr << "doPasswordSet<" << std::endl;
std::cerr << "doRegularKeySet<" << std::endl;
return terResult;
}
@@ -477,7 +439,7 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
if (!uDstAccountID)
{
Log(lsINFO) << "doPayment: Invalid transaction: Payment destination account not specifed.";
Log(lsINFO) << "doPayment: Invalid transaction: Payment destination account not specified.";
return temDST_NEEDED;
}
@@ -495,7 +457,7 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
}
else if (mTxnAccountID == uDstAccountID && uSrcCurrency == uDstCurrency && !bPaths)
{
Log(lsINFO) << boost::str(boost::format("doPayment: Invalid transaction: Redunant transaction: src=%s, dst=%s, src_cur=%s, dst_cur=%s")
Log(lsINFO) << boost::str(boost::format("doPayment: Invalid transaction: Redundant transaction: src=%s, dst=%s, src_cur=%s, dst_cur=%s")
% mTxnAccountID.ToString()
% uDstAccountID.ToString()
% uSrcCurrency.ToString()
@@ -577,7 +539,7 @@ TER TransactionEngine::doPayment(const SerializedTransaction& txn, const Transac
if (saSrcXRPBalance < saDstAmount)
{
// Transaction might succeed, if applied in a different order.
Log(lsINFO) << "doPayment: Delay transaction: Insufficent funds.";
Log(lsINFO) << "doPayment: Delay transaction: Insufficient funds.";
terResult = terUNFUNDED;
}
@@ -638,7 +600,7 @@ TER TransactionEngine::doWalletAdd(const SerializedTransaction& txn)
if (saSrcBalance < saAmount)
{
std::cerr
<< boost::str(boost::format("WalletAdd: Delay transaction: insufficent balance: balance=%s amount=%s")
<< boost::str(boost::format("WalletAdd: Delay transaction: insufficient balance: balance=%s amount=%s")
% saSrcBalance.getText()
% saAmount.getText())
<< std::endl;
@@ -662,10 +624,6 @@ TER TransactionEngine::doWalletAdd(const SerializedTransaction& txn)
return tesSUCCESS;
}
TER TransactionEngine::doInvoice(const SerializedTransaction& txn)
{
return temUNKNOWN;
}
// Take as much as possible. Adjusts account balances. Charges fees on top to taker.
// --> uBookBase: The order book to take against.

View File

@@ -127,7 +127,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
switch (txn.getTxnType())
{
case ttCLAIM:
case ttPASSWORD_SET:
case ttREGULAR_KEY_SET:
saCost = 0;
break;
@@ -148,7 +148,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
break;
case ttACCOUNT_SET:
case ttCREDIT_SET:
case ttTRUST_SET:
case ttOFFER_CREATE:
case ttOFFER_CANCEL:
case ttPASSWORD_FUND:
@@ -268,7 +268,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
}
break;
case ttPASSWORD_SET:
case ttREGULAR_KEY_SET:
// Transaction's signing public key must be for the source account.
// To prove the master private key made this transaction.
if (naSigningPubKey.getAccountID() != mTxnAccountID)
@@ -388,8 +388,8 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
terResult = doClaim(txn);
break;
case ttCREDIT_SET:
terResult = doCreditSet(txn);
case ttTRUST_SET:
terResult = doTrustSet(txn);
break;
case ttINVALID:
@@ -409,16 +409,8 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa
terResult = doOfferCancel(txn);
break;
case ttNICKNAME_SET:
terResult = doNicknameSet(txn);
break;
case ttPASSWORD_FUND:
terResult = doPasswordFund(txn);
break;
case ttPASSWORD_SET:
terResult = doPasswordSet(txn);
case ttREGULAR_KEY_SET:
terResult = doRegularKeySet(txn);
break;
case ttPAYMENT:

View File

@@ -64,13 +64,10 @@ protected:
TER doAccountSet(const SerializedTransaction& txn);
TER doClaim(const SerializedTransaction& txn);
TER doCreditSet(const SerializedTransaction& txn);
TER doInvoice(const SerializedTransaction& txn);
TER doTrustSet(const SerializedTransaction& txn);
TER doOfferCreate(const SerializedTransaction& txn);
TER doOfferCancel(const SerializedTransaction& txn);
TER doNicknameSet(const SerializedTransaction& txn);
TER doPasswordFund(const SerializedTransaction& txn);
TER doPasswordSet(const SerializedTransaction& txn);
TER doRegularKeySet(const SerializedTransaction& txn);
TER doPayment(const SerializedTransaction& txn, const TransactionEngineParams params);
TER doWalletAdd(const SerializedTransaction& txn);
TER doContractAdd(const SerializedTransaction& txn);

View File

@@ -28,34 +28,12 @@ static bool TFInit()
<< SOElement(sfTransferRate, SOE_OPTIONAL)
;
DECLARE_TF(Claim, ttCLAIM)
<< SOElement(sfGenerator, SOE_REQUIRED)
<< SOElement(sfPublicKey, SOE_REQUIRED)
<< SOElement(sfSignature, SOE_REQUIRED)
;
DECLARE_TF(CreditSet, ttCREDIT_SET)
DECLARE_TF(TrustSet, ttTRUST_SET)
<< SOElement(sfLimitAmount, SOE_OPTIONAL)
<< SOElement(sfQualityIn, SOE_OPTIONAL)
<< SOElement(sfQualityOut, SOE_OPTIONAL)
;
/*
DECLARE_TF(Invoice, ttINVOICE)
<< SOElement(sfTarget, SOE_REQUIRED)
<< SOElement(sfAmount, SOE_REQUIRED)
<< SOElement(sfDestination, SOE_OPTIONAL)
<< SOElement(sfIdentifier, SOE_OPTIONAL)
;
)
*/
DECLARE_TF(NicknameSet, ttNICKNAME_SET)
<< SOElement(sfNickname, SOE_REQUIRED)
<< SOElement(sfMinimumOffer, SOE_OPTIONAL)
;
DECLARE_TF(OfferCreate, ttOFFER_CREATE)
<< SOElement(sfTakerPays, SOE_REQUIRED)
<< SOElement(sfTakerGets, SOE_REQUIRED)
@@ -66,14 +44,8 @@ static bool TFInit()
<< SOElement(sfOfferSequence, SOE_REQUIRED)
;
DECLARE_TF(PasswordFund, ttPASSWORD_FUND)
<< SOElement(sfDestination, SOE_REQUIRED)
;
DECLARE_TF(PasswordSet, ttPASSWORD_SET)
DECLARE_TF(SetRegularKey, ttREGULAR_KEY_SET)
<< SOElement(sfAuthorizedKey, SOE_REQUIRED)
<< SOElement(sfGenerator, SOE_REQUIRED)
<< SOElement(sfPublicKey, SOE_REQUIRED)
;
DECLARE_TF(Payment, ttPAYMENT)
@@ -84,12 +56,6 @@ static bool TFInit()
<< SOElement(sfInvoiceID, SOE_OPTIONAL)
;
DECLARE_TF(WalletAdd, ttWALLET_ADD)
<< SOElement(sfAmount, SOE_REQUIRED)
<< SOElement(sfAuthorizedKey, SOE_REQUIRED)
<< SOElement(sfPublicKey, SOE_REQUIRED)
;
DECLARE_TF(Contract, ttCONTRACT)
<< SOElement(sfExpiration, SOE_REQUIRED)
<< SOElement(sfBondAmount, SOE_REQUIRED)

View File

@@ -7,18 +7,18 @@ enum TransactionType
{
ttINVALID = -1,
ttPAYMENT = 0,
ttCLAIM = 1,
ttCLAIM = 1, // open
ttWALLET_ADD = 2,
ttACCOUNT_SET = 3,
ttPASSWORD_FUND = 4,
ttPASSWORD_SET = 5,
ttNICKNAME_SET = 6,
ttPASSWORD_FUND = 4, // open
ttREGULAR_KEY_SET = 5,
ttNICKNAME_SET = 6, // open
ttOFFER_CREATE = 7,
ttOFFER_CANCEL = 8,
ttCONTRACT = 9,
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
ttCREDIT_SET = 20,
ttTRUST_SET = 20,
};
class TransactionFormat

View File

@@ -23,7 +23,7 @@
#endif
// These classes all store their values internally
// in little-endian form
// in big-endian form
inline int Testuint256AdHoc(std::vector<std::string> vArg);
@@ -36,7 +36,7 @@ protected:
enum { WIDTH=BITS/32 };
// 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];
public:
@@ -73,7 +73,7 @@ public:
zero();
// Put in least significant bits.
((uint64_t *) end())[-1] = htobe64(uHost);
((uint64_t *) end())[-1] = htobe64(uHost);
return *this;
}
@@ -105,10 +105,12 @@ public:
base_uint& operator++()
{
// prefix operator
int i = WIDTH;
while (i-- && !++pn[i])
;
for (int i = WIDTH - 1; i >= 0; --i)
{
pn[i] = htobe32(be32toh(pn[i]) + 1);
if (pn[i] != 0)
break;
}
return *this;
}
@@ -124,10 +126,13 @@ public:
base_uint& operator--()
{
int i = WIDTH;
while (i-- && !pn[i]--)
;
for (int i = WIDTH - 1; i >= 0; --i)
{
uint32 prev = pn[i];
pn[i] = htobe32(be32toh(pn[i]) - 1);
if (prev != 0)
break;
}
return *this;
}
@@ -169,10 +174,14 @@ public:
const unsigned char* pAEnd = a.end();
const unsigned char* pB = b.begin();
while (pA != pAEnd && *pA == *pB)
pA++, pB++;
while (*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)