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:
54
src/Ledger.h
54
src/Ledger.h
@@ -18,17 +18,17 @@
|
||||
|
||||
enum LedgerStateParms
|
||||
{
|
||||
lepNONE = 0, // no special flags
|
||||
lepNONE = 0, // no special flags
|
||||
|
||||
// input flags
|
||||
lepCREATE = 1, // Create if not present
|
||||
lepCREATE = 1, // Create if not present
|
||||
|
||||
// output flags
|
||||
lepOKAY = 2, // success
|
||||
lepMISSING = 4, // No node in that slot
|
||||
lepWRONGTYPE = 8, // Node of different type there
|
||||
lepCREATED = 16, // Node was created
|
||||
lepERROR = 32, // error
|
||||
lepOKAY = 2, // success
|
||||
lepMISSING = 4, // No node in that slot
|
||||
lepWRONGTYPE = 8, // Node of different type there
|
||||
lepCREATED = 16, // Node was created
|
||||
lepERROR = 32, // error
|
||||
};
|
||||
|
||||
class Ledger : public boost::enable_shared_from_this<Ledger>
|
||||
@@ -132,8 +132,6 @@ public:
|
||||
SerializedLedgerEntry::pointer getAccountRoot(LedgerStateParms& parms, const NewcoinAddress& naAccountID);
|
||||
SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const std::string& nickname);
|
||||
SerializedLedgerEntry::pointer getNickname(LedgerStateParms& parms, const uint256& nickHash);
|
||||
// SerializedLedgerEntry::pointer getRippleState(LedgerStateParms parms, const uint160& offeror,
|
||||
// const uint160& borrower, const Currency& currency);
|
||||
|
||||
// database functions
|
||||
static void saveAcceptedLedger(Ledger::pointer);
|
||||
@@ -142,7 +140,7 @@ public:
|
||||
|
||||
// index calculation functions
|
||||
static uint256 getAccountRootIndex(const uint160& account)
|
||||
{ return uint160extend256(account, 0); } // Index is accountID extended to 256 bits
|
||||
{ return uint160extend256(account, lnsAccounts); } // Index is accountID extended to 256 bits
|
||||
|
||||
static uint256 getAccountRootIndex(const NewcoinAddress& account)
|
||||
{ return getAccountRootIndex(account.getAccountID()); }
|
||||
@@ -154,28 +152,48 @@ public:
|
||||
SerializedLedgerEntry::pointer getGenerator(LedgerStateParms& parms, const uint160& uGeneratorID);
|
||||
|
||||
static uint256 getGeneratorIndex(const uint160& uGeneratorID)
|
||||
{ return uint160extend256(uGeneratorID, 1); } // Index is the generator ID extended to 256 bits in namespace 1
|
||||
{ return uint160extend256(uGeneratorID, lnsGenerator); } // Index is the generator ID extended to 256 bits in namespace 1
|
||||
|
||||
//
|
||||
// Ripple functions
|
||||
//
|
||||
|
||||
static uint256 getRippleIndex(const uint160& account, const uint160& extendTo, const uint160& currency);
|
||||
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency);
|
||||
static uint256 getRippleStateIndex(const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
||||
{ return getRippleStateIndex(NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency); }
|
||||
|
||||
static uint256 getRippleIndex(const uint160& account, const uint160& extendTo)
|
||||
{ return getRippleIndex(account, extendTo, uint160()); }
|
||||
|
||||
static uint256 getRippleIndex(const NewcoinAddress& account, const NewcoinAddress& extendTo,
|
||||
const uint160& currency)
|
||||
{ return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); }
|
||||
static uint256 getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB)
|
||||
{ return getRippleStateIndex(naA, naB, uint160()); }
|
||||
|
||||
static uint160 getOfferBase(const uint160& currencyIn, const uint160& accountIn,
|
||||
const uint160& currencyOut, const uint160& accountOut);
|
||||
|
||||
//
|
||||
// Offer functions
|
||||
//
|
||||
|
||||
static uint256 getOfferIndex(const uint160& offerBase, uint64 rate, int skip = 0);
|
||||
|
||||
static int getOfferSkip(const uint256& offerId);
|
||||
|
||||
SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency);
|
||||
SerializedLedgerEntry::pointer getRippleState(LedgerStateParms& parms, const uint160& uiA, const uint160& uiB, const uint160& uCurrency)
|
||||
{
|
||||
return getRippleState(parms, NewcoinAddress::createAccountID(uiA), NewcoinAddress::createAccountID(uiB), uCurrency);
|
||||
}
|
||||
|
||||
//
|
||||
// Directory functions
|
||||
//
|
||||
|
||||
static uint256 getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir=0);
|
||||
|
||||
SerializedLedgerEntry::pointer getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex);
|
||||
SerializedLedgerEntry::pointer getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex);
|
||||
|
||||
//
|
||||
// Misc
|
||||
//
|
||||
bool isCompatible(boost::shared_ptr<Ledger> other);
|
||||
// bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko);
|
||||
|
||||
|
||||
@@ -6,48 +6,59 @@
|
||||
LedgerEntryFormat LedgerFormats[]=
|
||||
{
|
||||
{ "AccountRoot", ltACCOUNT_ROOT, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(AuthorizedKey),STI_HASH160, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 4 },
|
||||
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Sequence), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(AuthorizedKey), STI_HASH160, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(WalletLocator), STI_HASH256, SOE_IFFLAG, 4 },
|
||||
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
||||
{ S_FIELD(TransitRate), STI_UINT32, SOE_IFFLAG, 16 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "DirectoryRoot", ltDIR_ROOT, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(FirstNode), STI_UINT64, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LastNode), STI_UINT64, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "DirectoryNode", ltDIR_NODE, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Indexes), STI_VECTOR256, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "GeneratorMap", ltGENERATOR_MAP, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(GeneratorID), STI_HASH160, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "Nickname", ltNICKNAME, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(OfferCurrency),STI_HASH160, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(OfferCurrency), STI_HASH160, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ "RippleState", ltRIPPLE_STATE, {
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Borrower), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Lender), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Limit), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(CurrentRate), STI_UINT32, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(RateLock), STI_UINT32, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(NextRate), STI_UINT32, SOE_IFFLAG, 4 },
|
||||
{ S_FIELD(NextRateLgr), STI_UINT32, SOE_IFFLAG, 8 },
|
||||
{ S_FIELD(NextRateExp), STI_UINT32, SOE_IFFLAG, 16 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LowID), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(HighID), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
},
|
||||
{ NULL, ltINVALID }
|
||||
};
|
||||
|
||||
@@ -5,18 +5,37 @@
|
||||
|
||||
enum LedgerEntryType
|
||||
{
|
||||
ltINVALID =-1,
|
||||
ltACCOUNT_ROOT =0,
|
||||
ltRIPPLE_STATE =1,
|
||||
ltGENERATOR_MAP =2,
|
||||
ltNICKNAME =3
|
||||
ltINVALID = -1,
|
||||
ltACCOUNT_ROOT,
|
||||
ltDIR_ROOT,
|
||||
ltDIR_NODE,
|
||||
ltGENERATOR_MAP,
|
||||
ltRIPPLE_STATE,
|
||||
ltNICKNAME
|
||||
};
|
||||
|
||||
// In the format 160 + namespace + other.
|
||||
enum LedgerNameSpace
|
||||
{
|
||||
lnsGenerator = -1,
|
||||
lnsAccounts,
|
||||
lnsRipple,
|
||||
lnsBonds,
|
||||
lnsInvoices,
|
||||
lnsMultiSig
|
||||
};
|
||||
|
||||
enum LedgerSpecificFlags
|
||||
{
|
||||
lsfLowIndexed = 0x00010000,
|
||||
lsfHighIndexed = 0x00020000,
|
||||
};
|
||||
|
||||
struct LedgerEntryFormat
|
||||
{
|
||||
const char *t_name;
|
||||
LedgerEntryType t_type;
|
||||
SOElement elements[16];
|
||||
SOElement elements[20];
|
||||
};
|
||||
|
||||
extern LedgerEntryFormat LedgerFormats[];
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
|
||||
#include "Ledger.h"
|
||||
|
||||
uint256 Ledger::getRippleIndex(const uint160& accountID, const uint160& extendTo, const uint160& currency)
|
||||
{ // Index is 160-bit account credit extended to, 96-bit XOR of extending account and currency
|
||||
uint256 base = getAccountRootIndex(extendTo);
|
||||
memcpy(base.begin() + (160 / 8), (accountID ^ currency).begin(), (256 / 8) - (160 / 8));
|
||||
return base;
|
||||
uint256 Ledger::getRippleStateIndex(const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency)
|
||||
{
|
||||
uint160 uAID = naA.getAccountID();
|
||||
uint160 uBID = naB.getAccountID();
|
||||
bool bAltB = uAID < uBID;
|
||||
Serializer s;
|
||||
|
||||
s.add160(bAltB ? uAID : uBID);
|
||||
s.add160(bAltB ? uBID : uAID);
|
||||
s.add160(uCurrency);
|
||||
|
||||
return s.getSHA512Half();
|
||||
}
|
||||
|
||||
uint160 Ledger::getOfferBase(const uint160& currencyIn, const uint160& accountIn,
|
||||
|
||||
@@ -137,4 +137,83 @@ SerializedLedgerEntry::pointer Ledger::getGenerator(LedgerStateParms& parms, con
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Ripple State
|
||||
//
|
||||
|
||||
SerializedLedgerEntry::pointer Ledger::getRippleState(LedgerStateParms& parms, const NewcoinAddress& naA, const NewcoinAddress& naB, const uint160& uCurrency)
|
||||
{
|
||||
uint256 nodeID=getRippleStateIndex(naA, naB, uCurrency);
|
||||
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
try
|
||||
{
|
||||
return getASNode(parms, nodeID, ltRIPPLE_STATE);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
parms = lepERROR;
|
||||
return SerializedLedgerEntry::pointer();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Directory
|
||||
//
|
||||
|
||||
uint256 Ledger::getDirIndex(const uint256& uBase, const LedgerEntryType letKind, const uint64 uNodeDir)
|
||||
{
|
||||
// Indexes are stored in little endian format.
|
||||
// The low bytes are indexed first, so when printed as a hex stream the hex is in byte order.
|
||||
// Therefore, we place uNodeDir in the 8 right most bytes.
|
||||
Serializer sKey;
|
||||
|
||||
sKey.add256(uBase);
|
||||
sKey.add8(letKind);
|
||||
|
||||
uint256 uResult = sKey.getSHA512Half();
|
||||
|
||||
Serializer sNode; // Put in a fixed byte order: BIG. YYY
|
||||
|
||||
sNode.add64(uNodeDir);
|
||||
|
||||
// YYY SLOPPY
|
||||
std::vector<unsigned char> vucData = sNode.getData();
|
||||
|
||||
std::copy(vucData.begin(), vucData.end(), uResult.end()-(64/8));
|
||||
|
||||
return uResult;
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::pointer Ledger::getDirRoot(LedgerStateParms& parms, const uint256& uRootIndex)
|
||||
{
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
try
|
||||
{
|
||||
return getASNode(parms, uRootIndex, ltDIR_ROOT);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
parms = lepERROR;
|
||||
return SerializedLedgerEntry::pointer();
|
||||
}
|
||||
}
|
||||
|
||||
SerializedLedgerEntry::pointer Ledger::getDirNode(LedgerStateParms& parms, const uint256& uNodeIndex)
|
||||
{
|
||||
ScopedLock l(mAccountStateMap->Lock());
|
||||
|
||||
try
|
||||
{
|
||||
return getASNode(parms, uNodeIndex, ltDIR_NODE);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
parms = lepERROR;
|
||||
return SerializedLedgerEntry::pointer();
|
||||
}
|
||||
}
|
||||
|
||||
// vim:ts=4
|
||||
|
||||
@@ -322,6 +322,15 @@ bool NewcoinAddress::accountPublicVerify(const uint256& uHash, const std::vector
|
||||
return bVerified;
|
||||
}
|
||||
|
||||
NewcoinAddress NewcoinAddress::createAccountID(const uint160& uiAccountID)
|
||||
{
|
||||
NewcoinAddress na;
|
||||
|
||||
na.setAccountID(uiAccountID);
|
||||
|
||||
return na;
|
||||
}
|
||||
|
||||
//
|
||||
// AccountPrivate
|
||||
//
|
||||
|
||||
@@ -65,6 +65,8 @@ public:
|
||||
bool setAccountID(const std::string& strAccountID);
|
||||
void setAccountID(const uint160& hash160In);
|
||||
|
||||
static NewcoinAddress createAccountID(const uint160& uiAccountID);
|
||||
|
||||
//
|
||||
// Accounts Public
|
||||
//
|
||||
|
||||
@@ -130,6 +130,17 @@ int RPCServer::getParamCount(const Json::Value& params)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// now, expire, n
|
||||
bool RPCServer::parseAcceptRate(const std::string& sAcceptRate)
|
||||
{
|
||||
if (!sAcceptRate.compare("expire"))
|
||||
0;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool RPCServer::extractString(std::string& param, const Json::Value& params, int index)
|
||||
{
|
||||
if (params.isNull()) return false;
|
||||
@@ -363,30 +374,16 @@ Json::Value RPCServer::doPeers(Json::Value& params)
|
||||
return theApp->getConnectionPool().getPeersJson();
|
||||
}
|
||||
|
||||
// credit_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<borrow_rate>] [<borrow_start>] [<borrow_expire>]
|
||||
// credit_set <seed> <paying_account> <destination_account> <limit_amount> [<currency>] [<accept_rate>]
|
||||
Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
{
|
||||
NewcoinAddress naSeed;
|
||||
NewcoinAddress naSrcAccountID;
|
||||
NewcoinAddress naDstAccountID;
|
||||
STAmount saLimitAmount;
|
||||
std::string sBorrowRate;
|
||||
std::string sBorrowStart;
|
||||
std::string sBorrowExpire;
|
||||
uint32 uBorrowRate;
|
||||
uint32 uBorrowStart;
|
||||
uint32 uBorrowExpire;
|
||||
uint32 uAcceptRate = params.size() >= 6 ? boost::lexical_cast<uint32>(params[5u].asString()) : 0;
|
||||
|
||||
if (params.size() >= 6)
|
||||
sBorrowRate = params[6u].asString();
|
||||
|
||||
if (params.size() >= 7)
|
||||
sBorrowStart = params[7u].asString();
|
||||
|
||||
if (params.size() >= 8)
|
||||
sBorrowExpire = params[8u].asString();
|
||||
|
||||
if (params.size() < 5 || params.size() > 8)
|
||||
if (params.size() < 4 || params.size() > 6)
|
||||
{
|
||||
return JSONRPCError(500, "invalid parameters");
|
||||
}
|
||||
@@ -402,7 +399,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
{
|
||||
return JSONRPCError(500, "destination account id needed");
|
||||
}
|
||||
else if (!saLimitAmount.setValue(params[5u].asString(), params[6u].asString()))
|
||||
else if (!saLimitAmount.setValue(params[3u].asString(), params.size() >= 5 ? params[4u].asString() : ""))
|
||||
{
|
||||
return JSONRPCError(500, "bad src amount/currency");
|
||||
}
|
||||
@@ -417,16 +414,10 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
Json::Value obj = authorize(naSeed, naSrcAccountID, naAccountPublic, naAccountPrivate, sleSrc);
|
||||
|
||||
if (!obj.empty())
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
STAmount saSrcBalance = sleSrc->getIValueFieldAmount(sfBalance);
|
||||
|
||||
uBorrowRate = 0;
|
||||
uBorrowStart = 0;
|
||||
uBorrowExpire = 0;
|
||||
|
||||
if (saSrcBalance < theConfig.FEE_DEFAULT)
|
||||
{
|
||||
return JSONRPCError(500, "insufficent funds");
|
||||
@@ -441,9 +432,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
0, // YYY No source tag
|
||||
naDstAccountID,
|
||||
saLimitAmount,
|
||||
uBorrowRate,
|
||||
uBorrowStart,
|
||||
uBorrowExpire);
|
||||
uAcceptRate);
|
||||
|
||||
(void) theApp->getOPs().processTransaction(trans);
|
||||
|
||||
@@ -453,9 +442,7 @@ Json::Value RPCServer::doCreditSet(Json::Value& params)
|
||||
obj["srcAccountID"] = naSrcAccountID.humanAccountID();
|
||||
obj["dstAccountID"] = naDstAccountID.humanAccountID();
|
||||
obj["limitAmount"] = saLimitAmount.getText();
|
||||
obj["borrowRate"] = uBorrowRate;
|
||||
obj["borrowStart"] = uBorrowStart;
|
||||
obj["borrowExpire"] = uBorrowExpire;
|
||||
obj["acceptRate"] = uAcceptRate;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ class RPCServer : public boost::enable_shared_from_this<RPCServer>
|
||||
SerializedLedgerEntry::pointer& sleSrc);
|
||||
|
||||
Json::Value doAccountInfo(Json::Value& params);
|
||||
Json::Value doBorrowSet(Json::Value& params);
|
||||
Json::Value doConnect(Json::Value& params);
|
||||
Json::Value doCreditSet(Json::Value& params);
|
||||
Json::Value doLedger(Json::Value& params);
|
||||
|
||||
@@ -32,6 +32,10 @@ public:
|
||||
void add(Serializer& s) const { mVersion.add(s); mObject.add(s); }
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
|
||||
bool setFlag(uint32 uSet) { return mObject.setFlag(uSet); }
|
||||
bool clearFlag(uint32 uClear) { return mObject.clearFlag(uClear); }
|
||||
uint32 getFlags() const { return mObject.getFlags(); }
|
||||
|
||||
const uint256& getIndex() const { return mIndex; }
|
||||
void setIndex(const uint256& i) { mIndex = i; }
|
||||
|
||||
@@ -55,6 +59,8 @@ public:
|
||||
std::vector<TaggedListItem> getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); }
|
||||
NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); }
|
||||
STAmount getIValueFieldAmount(SOE_Field field) const { return mObject.getValueFieldAmount(field); }
|
||||
STVector256 getIFieldV256(SOE_Field field) { return mObject.getValueFieldV256(field); }
|
||||
|
||||
void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); }
|
||||
void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); }
|
||||
void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); }
|
||||
@@ -71,6 +77,7 @@ public:
|
||||
{ return mObject.setValueFieldAccount(field, account); }
|
||||
void setIFieldAmount(SOE_Field field, const STAmount& amount)
|
||||
{ return mObject.setValueFieldAmount(field, amount); }
|
||||
void setIFieldV256(SOE_Field field, const STVector256& v) { return mObject.setValueFieldV256(field, v); }
|
||||
|
||||
bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); }
|
||||
void makeIFieldPresent(SOE_Field field) { mObject.makeFieldPresent(field); }
|
||||
|
||||
@@ -33,6 +33,9 @@ std::auto_ptr<SerializedType> STObject::makeDefaultObject(SerializedTypeID id, c
|
||||
case STI_HASH256:
|
||||
return std::auto_ptr<SerializedType>(new STHash256(name));
|
||||
|
||||
case STI_VECTOR256:
|
||||
return std::auto_ptr<SerializedType>(new STVector256(name));
|
||||
|
||||
case STI_VL:
|
||||
return std::auto_ptr<SerializedType>(new STVariableLength(name));
|
||||
|
||||
@@ -79,6 +82,9 @@ std::auto_ptr<SerializedType> STObject::makeDeserializedObject(SerializedTypeID
|
||||
case STI_HASH256:
|
||||
return STHash256::deserialize(sit, name);
|
||||
|
||||
case STI_VECTOR256:
|
||||
return STVector256::deserialize(sit, name);
|
||||
|
||||
case STI_VL:
|
||||
return STVariableLength::deserialize(sit, name);
|
||||
|
||||
@@ -464,6 +470,17 @@ STAmount STObject::getValueFieldAmount(SOE_Field field) const
|
||||
return *cf;
|
||||
}
|
||||
|
||||
STVector256 STObject::getValueFieldV256(SOE_Field field) const
|
||||
{
|
||||
const SerializedType* rf = peekAtPField(field);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
SerializedTypeID id = rf->getSType();
|
||||
if (id == STI_NOTPRESENT) return STVector256(); // optional field not present
|
||||
const STVector256 *cf = dynamic_cast<const STVector256 *>(rf);
|
||||
if (!cf) throw std::runtime_error("Wrong field type");
|
||||
return *cf;
|
||||
}
|
||||
|
||||
void STObject::setValueFieldU8(SOE_Field field, unsigned char v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
@@ -524,6 +541,16 @@ void STObject::setValueFieldH256(SOE_Field field, const uint256& v)
|
||||
cf->setValue(v);
|
||||
}
|
||||
|
||||
void STObject::setValueFieldV256(SOE_Field field, const STVector256& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
if (!rf) throw std::runtime_error("Field not found");
|
||||
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||
STVector256* cf = dynamic_cast<STVector256*>(rf);
|
||||
if (!cf) throw std::runtime_error("Wrong field type");
|
||||
cf->setValue(v);
|
||||
}
|
||||
|
||||
void STObject::setValueFieldAccount(SOE_Field field, const uint160& v)
|
||||
{
|
||||
SerializedType* rf = getPField(field);
|
||||
|
||||
@@ -24,6 +24,9 @@ enum SOE_Field
|
||||
sfGeneric = 0,
|
||||
|
||||
// common fields
|
||||
sfAcceptExpire,
|
||||
sfAcceptRate,
|
||||
sfAcceptStart,
|
||||
sfAccount,
|
||||
sfAccountID,
|
||||
sfAmount,
|
||||
@@ -38,32 +41,38 @@ enum SOE_Field
|
||||
sfCurrency,
|
||||
sfCurrencyIn,
|
||||
sfCurrencyOut,
|
||||
sfCurrentRate,
|
||||
sfDestination,
|
||||
sfEmailHash,
|
||||
sfExpireLedger,
|
||||
sfExtensions,
|
||||
sfFirstNode,
|
||||
sfFlags,
|
||||
sfGenerator,
|
||||
sfGeneratorID,
|
||||
sfHighID,
|
||||
sfHighLimit,
|
||||
sfIdentifier,
|
||||
sfIndexes,
|
||||
sfInvoiceID,
|
||||
sfLastNode,
|
||||
sfLastReceive,
|
||||
sfLastTxn,
|
||||
sfLedgerHash,
|
||||
sfLender,
|
||||
sfLimit,
|
||||
sfLimitAmount,
|
||||
sfLowID,
|
||||
sfLowLimit,
|
||||
sfMessageKey,
|
||||
sfMinimumOffer,
|
||||
sfNextRate,
|
||||
sfNextRateExp,
|
||||
sfNextRateLgr,
|
||||
sfNextAcceptExpire,
|
||||
sfNextAcceptRate,
|
||||
sfNextAcceptStart,
|
||||
sfNextTransitExpire,
|
||||
sfNextTransitRate,
|
||||
sfNextTransitStart,
|
||||
sfNickname,
|
||||
sfOfferCurrency,
|
||||
sfPaths,
|
||||
sfPubKey,
|
||||
sfRateLock,
|
||||
sfSendMax,
|
||||
sfSequence,
|
||||
sfSignature,
|
||||
@@ -155,6 +164,7 @@ public:
|
||||
std::vector<unsigned char> getValueFieldVL(SOE_Field field) const;
|
||||
std::vector<TaggedListItem> getValueFieldTL(SOE_Field field) const;
|
||||
STAmount getValueFieldAmount(SOE_Field field) const;
|
||||
STVector256 getValueFieldV256(SOE_Field field) const;
|
||||
|
||||
void setValueFieldU8(SOE_Field field, unsigned char);
|
||||
void setValueFieldU16(SOE_Field field, uint16);
|
||||
@@ -169,6 +179,7 @@ public:
|
||||
{ setValueFieldAccount(field, addr.getAccountID()); }
|
||||
void setValueFieldAmount(SOE_Field field, const STAmount&);
|
||||
void setValueFieldPathSet(SOE_Field field, const STPathSet&);
|
||||
void setValueFieldV256(SOE_Field field, const STVector256& v);
|
||||
|
||||
bool isFieldPresent(SOE_Field field) const;
|
||||
SerializedType* makeFieldPresent(SOE_Field field);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "SerializedTypes.h"
|
||||
@@ -173,15 +174,44 @@ std::string STAccount::getText() const
|
||||
|
||||
STAccount* STAccount::construct(SerializerIterator& u, const char *name)
|
||||
{
|
||||
STAccount *ret = new STAccount(name, u.getVL());
|
||||
if (!ret->isValueH160())
|
||||
{
|
||||
delete ret;
|
||||
throw std::runtime_error("invalid account in transaction");
|
||||
}
|
||||
return ret;
|
||||
return new STAccount(name, u.getVL());
|
||||
}
|
||||
|
||||
//
|
||||
// STVector256
|
||||
//
|
||||
|
||||
// Return a new object from a SerializerIterator.
|
||||
STVector256* STVector256::construct(SerializerIterator& u, const char *name)
|
||||
{
|
||||
return new STVector256(name, u.getVL());
|
||||
}
|
||||
|
||||
void STVector256::add(Serializer& s) const
|
||||
{
|
||||
s.add32(mValue.size());
|
||||
BOOST_FOREACH(const uint256& v, mValue)
|
||||
{
|
||||
s.add256(v);
|
||||
}
|
||||
}
|
||||
|
||||
void STVector256::setValue(const std::vector<unsigned char>& vucData)
|
||||
{
|
||||
Serializer s(vucData);
|
||||
SerializerIterator it(s);
|
||||
uint64 uSize = it.get32();
|
||||
uint64 uIndex = 0;
|
||||
|
||||
mValue.resize(uSize);
|
||||
while (uSize--)
|
||||
mValue[uIndex++] = it.get256();
|
||||
}
|
||||
|
||||
//
|
||||
// STAccount
|
||||
//
|
||||
|
||||
bool STAccount::isValueH160() const
|
||||
{
|
||||
return peekValue().size() == (160/8);
|
||||
|
||||
@@ -12,15 +12,28 @@
|
||||
enum SerializedTypeID
|
||||
{
|
||||
// special types
|
||||
STI_DONE=-1, STI_NOTPRESENT=0,
|
||||
STI_DONE = -1,
|
||||
STI_NOTPRESENT = 0,
|
||||
|
||||
// standard types
|
||||
STI_OBJECT=1, STI_UINT8=2, STI_UINT16=3, STI_UINT32=4, STI_UINT64=5,
|
||||
STI_HASH128=6, STI_HASH160=7, STI_HASH256=8, STI_VL=9, STI_TL=10,
|
||||
STI_AMOUNT=11, STI_PATHSET=12,
|
||||
STI_OBJECT = 1,
|
||||
STI_UINT8 = 2,
|
||||
STI_UINT16 = 3,
|
||||
STI_UINT32 = 4,
|
||||
STI_UINT64 = 5,
|
||||
STI_HASH128 = 6,
|
||||
STI_HASH160 = 7,
|
||||
STI_HASH256 = 8,
|
||||
STI_VL = 9,
|
||||
STI_TL = 10,
|
||||
STI_AMOUNT = 11,
|
||||
STI_PATHSET = 12,
|
||||
STI_VECTOR256 = 13,
|
||||
|
||||
// high level types
|
||||
STI_ACCOUNT=100, STI_TRANSACTION=101, STI_LEDGERENTRY=102
|
||||
STI_ACCOUNT = 100,
|
||||
STI_TRANSACTION = 101,
|
||||
STI_LEDGERENTRY = 102
|
||||
};
|
||||
|
||||
class SerializedType
|
||||
@@ -561,5 +574,40 @@ public:
|
||||
virtual bool isEquivalent(const SerializedType& t) const;
|
||||
};
|
||||
|
||||
class STVector256 : public SerializedType
|
||||
{
|
||||
protected:
|
||||
std::vector<uint256> mValue;
|
||||
|
||||
STVector256* duplicate() const { return new STVector256(name, mValue); }
|
||||
static STVector256* construct(SerializerIterator&, const char* name = NULL);
|
||||
|
||||
public:
|
||||
STVector256() { ; }
|
||||
STVector256(const char* n) : SerializedType(n) { ; }
|
||||
STVector256(const char* n, const std::vector<uint256>& v) : SerializedType(n), mValue(v) { ; }
|
||||
STVector256(const std::vector<uint256>& vector) : mValue(vector) { ; }
|
||||
STVector256(const char* n, const std::vector<unsigned char>& vucSerial) : SerializedType(n)
|
||||
{ setValue(vucSerial); }
|
||||
|
||||
SerializedTypeID getSType() const { return STI_VECTOR256; }
|
||||
int getLength() const { return mValue.size()*(256/8)+(64/8); }
|
||||
void add(Serializer& s) const;
|
||||
|
||||
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, const char* name)
|
||||
{ return std::auto_ptr<SerializedType>(construct(sit, name)); }
|
||||
|
||||
const std::vector<uint256>& peekValue() const { return mValue; }
|
||||
std::vector<uint256>& peekValue() { return mValue; }
|
||||
|
||||
std::vector<uint256> getValue() const { return mValue; }
|
||||
|
||||
bool isEmpty() const { return mValue.empty(); }
|
||||
|
||||
void setValue(const STVector256& v) { mValue = v.mValue; }
|
||||
void setValue(const std::vector<uint256>& v) { mValue = v; }
|
||||
void setValue(const std::vector<unsigned char>& vucData);
|
||||
};
|
||||
|
||||
#endif
|
||||
// vim:ts=4
|
||||
|
||||
@@ -14,13 +14,13 @@ typedef std::pair<int, std::vector<unsigned char> > TaggedListItem;
|
||||
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
public:
|
||||
typedef boost::shared_ptr<Serializer> pointer;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
std::vector<unsigned char> mData;
|
||||
|
||||
public:
|
||||
public:
|
||||
Serializer(int n=256) { mData.reserve(n); }
|
||||
Serializer(const std::vector<unsigned char> &data) : mData(data) { ; }
|
||||
Serializer(const std::string& data) : mData(data.data(), (data.data()) + data.size()) { ; }
|
||||
|
||||
@@ -190,18 +190,12 @@ Transaction::pointer Transaction::setCreditSet(
|
||||
const NewcoinAddress& naPrivateKey,
|
||||
const NewcoinAddress& naDstAccountID,
|
||||
const STAmount& saLimitAmount,
|
||||
uint32 uBorrowRate,
|
||||
uint32 uBorrowStart,
|
||||
uint32 uBorrowExpire)
|
||||
uint32 uAcceptRate)
|
||||
{
|
||||
mTransaction->setITFieldAccount(sfDestination, naDstAccountID);
|
||||
mTransaction->setITFieldAmount(sfLimitAmount, saLimitAmount);
|
||||
if (uBorrowRate)
|
||||
mTransaction->setITFieldU32(sfBorrowRate, uBorrowRate);
|
||||
if (uBorrowStart)
|
||||
mTransaction->setITFieldU32(sfBorrowStart, uBorrowStart);
|
||||
if (uBorrowExpire)
|
||||
mTransaction->setITFieldU32(sfBorrowExpire, uBorrowExpire);
|
||||
if (uAcceptRate)
|
||||
mTransaction->setITFieldU32(sfAcceptRate, uAcceptRate);
|
||||
|
||||
sign(naPrivateKey);
|
||||
|
||||
@@ -216,15 +210,13 @@ Transaction::pointer Transaction::sharedCreditSet(
|
||||
uint32 uSourceTag,
|
||||
const NewcoinAddress& naDstAccountID,
|
||||
const STAmount& saLimitAmount,
|
||||
uint32 uBorrowRate,
|
||||
uint32 uBorrowStart,
|
||||
uint32 uBorrowExpire)
|
||||
uint32 uAcceptRate)
|
||||
{
|
||||
pointer tResult = boost::make_shared<Transaction>(ttCREDIT_SET,
|
||||
naPublicKey, naSourceAccount,
|
||||
uSeq, saFee, uSourceTag);
|
||||
|
||||
return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uBorrowRate, uBorrowStart, uBorrowExpire);
|
||||
return tResult->setCreditSet(naPrivateKey, naDstAccountID, saLimitAmount, uAcceptRate);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -61,9 +61,7 @@ private:
|
||||
const NewcoinAddress& naPrivateKey,
|
||||
const NewcoinAddress& naDstAccountID,
|
||||
const STAmount& saLimitAmount,
|
||||
uint32 uBorrowRate,
|
||||
uint32 uBorrowStart,
|
||||
uint32 uBorrowExpire);
|
||||
uint32 uAcceptRate);
|
||||
|
||||
Transaction::pointer setPayment(
|
||||
const NewcoinAddress& naPrivateKey,
|
||||
@@ -119,9 +117,7 @@ public:
|
||||
uint32 uSourceTag,
|
||||
const NewcoinAddress& naDstAccountID,
|
||||
const STAmount& saLimitAmount,
|
||||
uint32 uBorrowRate,
|
||||
uint32 uBorrowStart,
|
||||
uint32 uBorrowExpire);
|
||||
uint32 uAcceptRate);
|
||||
|
||||
// Make a payment.
|
||||
static Transaction::pointer sharedPayment(
|
||||
|
||||
@@ -2,9 +2,216 @@
|
||||
|
||||
#include "Config.h"
|
||||
#include "TransactionFormats.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
typedef SerializedLedgerEntry SLE;
|
||||
|
||||
#define DIR_NODE_MAX 32
|
||||
|
||||
// We return the uNodeDir so that on delete we can quickly know where the element is mentioned in the directory.
|
||||
TransactionEngineResult TransactionEngine::dirAdd(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
uint64& uNodeDir,
|
||||
const LedgerEntryType letKind,
|
||||
const uint256& uBase,
|
||||
const uint256& uLedgerIndex)
|
||||
{
|
||||
// Get the root.
|
||||
uint256 uRootIndex = Ledger::getDirIndex(uBase, letKind);
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, uRootIndex);
|
||||
bool bRootNew;
|
||||
|
||||
// Get the last node index.
|
||||
if (sleRoot)
|
||||
{
|
||||
bRootNew = false;
|
||||
uNodeDir = sleRoot->getIFieldU64(sfLastNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
bRootNew = true;
|
||||
uNodeDir = 1;
|
||||
|
||||
sleRoot = boost::make_shared<SerializedLedgerEntry>(ltDIR_ROOT);
|
||||
sleRoot->setIndex(uRootIndex);
|
||||
sleRoot->setIFieldU64(sfFirstNode, uNodeDir);
|
||||
sleRoot->setIFieldU64(sfLastNode, uNodeDir);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleRoot));
|
||||
}
|
||||
|
||||
// Get the last node.
|
||||
uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeDir);
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = bRootNew ? SLE::pointer() : mLedger->getDirNode(lspNode, uNodeIndex);
|
||||
|
||||
if (sleNode)
|
||||
{
|
||||
STVector256 svIndexes;
|
||||
|
||||
svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
if (DIR_NODE_MAX != svIndexes.peekValue().size())
|
||||
{
|
||||
// Last node is not full, append.
|
||||
|
||||
svIndexes.peekValue().push_back(uLedgerIndex);
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNode));
|
||||
}
|
||||
// Last node is full, add a new node.
|
||||
else if (!++uNodeDir)
|
||||
{
|
||||
return terDIR_FULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Record new last node.
|
||||
sleNode = SLE::pointer();
|
||||
|
||||
sleRoot->setIFieldU64(sfLastNode, uNodeDir);
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
// Add to last node, which is empty.
|
||||
sleNode = boost::make_shared<SerializedLedgerEntry>(ltDIR_NODE);
|
||||
sleNode->setIndex(uNodeIndex);
|
||||
|
||||
STVector256 svIndexes;
|
||||
|
||||
svIndexes.peekValue().push_back(uLedgerIndex);
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleNode));
|
||||
}
|
||||
|
||||
return terSUCCESS;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::dirDelete(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
const uint64& uNodeDir,
|
||||
const LedgerEntryType letKind,
|
||||
const uint256& uBase,
|
||||
const uint256& uLedgerIndex)
|
||||
{
|
||||
uint64 uNodeCur = uNodeDir;
|
||||
uint256 uNodeIndex = Ledger::getDirIndex(uBase, letKind, uNodeCur);
|
||||
LedgerStateParms lspNode = lepNONE;
|
||||
SLE::pointer sleNode = mLedger->getDirNode(lspNode, uNodeIndex);
|
||||
|
||||
if (!sleNode)
|
||||
{
|
||||
std::cerr << "dirDelete: no such node" << std::endl;
|
||||
return terNODE_NOT_FOUND;
|
||||
}
|
||||
else
|
||||
{
|
||||
STVector256 svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
std::vector<uint256>& vuiIndexes = svIndexes.peekValue();
|
||||
std::vector<uint256>::iterator it;
|
||||
|
||||
it = std::find(vuiIndexes.begin(), vuiIndexes.end(), uLedgerIndex);
|
||||
if (vuiIndexes.end() == it)
|
||||
{
|
||||
std::cerr << "dirDelete: node not mentioned" << std::endl;
|
||||
return terNODE_NOT_MENTIONED;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get root information
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleRoot = mLedger->getDirRoot(lspRoot, Ledger::getDirIndex(uBase, letKind));
|
||||
|
||||
if (!sleRoot)
|
||||
{
|
||||
std::cerr << "dirDelete: root node is missing" << std::endl;
|
||||
return terNODE_NO_ROOT;
|
||||
}
|
||||
|
||||
uint64 uFirstNodeOrig = sleRoot->getIFieldU64(sfFirstNode);
|
||||
uint64 uLastNodeOrig = sleRoot->getIFieldU64(sfLastNode);
|
||||
uint64 uFirstNode = uFirstNodeOrig;
|
||||
uint64 uLastNode = uLastNodeOrig;
|
||||
|
||||
// Remove the element.
|
||||
if (vuiIndexes.size() > 1)
|
||||
{
|
||||
*it = vuiIndexes[vuiIndexes.size()-1];
|
||||
}
|
||||
vuiIndexes.resize(vuiIndexes.size()-1);
|
||||
|
||||
sleNode->setIFieldV256(sfIndexes, svIndexes);
|
||||
|
||||
if (!vuiIndexes.empty() || (uFirstNode != uNodeCur && uLastNode != uNodeCur))
|
||||
{
|
||||
// Node is not being deleted.
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleNode));
|
||||
}
|
||||
|
||||
while (uFirstNode && svIndexes.peekValue().empty()
|
||||
&& (uFirstNode == uNodeCur || uLastNode == uNodeCur))
|
||||
{
|
||||
// Current node is empty and first or last, delete it.
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleNode));
|
||||
|
||||
if (uFirstNode == uLastNode)
|
||||
{
|
||||
// Complete deletion.
|
||||
uFirstNode = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uFirstNode == uNodeCur)
|
||||
{
|
||||
// Advance first node
|
||||
++uNodeCur;
|
||||
++uFirstNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Rewind last node
|
||||
--uNodeCur;
|
||||
--uLastNode;
|
||||
}
|
||||
|
||||
// Get replacement node.
|
||||
lspNode = lepNONE;
|
||||
sleNode = mLedger->getDirNode(lspNode, Ledger::getDirIndex(uBase, letKind, uNodeCur));
|
||||
svIndexes = sleNode->getIFieldV256(sfIndexes);
|
||||
}
|
||||
}
|
||||
|
||||
if (uFirstNode == uFirstNodeOrig && uLastNode == uLastNodeOrig)
|
||||
{
|
||||
// Dir is fine.
|
||||
nothing();
|
||||
}
|
||||
else if (uFirstNode)
|
||||
{
|
||||
// Update root's pointer pointers.
|
||||
sleRoot->setIFieldU64(sfFirstNode, uFirstNode);
|
||||
sleRoot->setIFieldU64(sfLastNode, uLastNode);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRoot));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete the root.
|
||||
accounts.push_back(std::make_pair(taaDELETE, sleRoot));
|
||||
}
|
||||
}
|
||||
|
||||
return terSUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
|
||||
TransactionEngineParams params)
|
||||
{
|
||||
@@ -53,6 +260,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
|
||||
case ttINVOICE:
|
||||
case ttOFFER:
|
||||
case ttCREDIT_SET:
|
||||
case ttTRANSIT_SET:
|
||||
result = terSUCCESS;
|
||||
break;
|
||||
|
||||
@@ -104,8 +313,8 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
|
||||
// find source account
|
||||
// If we are only verifying some transactions, this would be probablistic.
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SerializedLedgerEntry::pointer sleSrc = mLedger->getAccountRoot(qry, srcAccountID);
|
||||
LedgerStateParms lspRoot = lepNONE;
|
||||
SLE::pointer sleSrc = mLedger->getAccountRoot(lspRoot, srcAccountID);
|
||||
if (!sleSrc)
|
||||
{
|
||||
std::cerr << str(boost::format("applyTransaction: Delay transaction: source account does not exisit: %s") % txn.getSourceAccount().humanAccountID()) << std::endl;
|
||||
@@ -176,7 +385,7 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
break;
|
||||
|
||||
case ttCREDIT_SET:
|
||||
result = doCreditSet(txn, accounts);
|
||||
result = doCreditSet(txn, accounts, srcAccountID);
|
||||
break;
|
||||
|
||||
case ttINVALID:
|
||||
@@ -236,11 +445,6 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
||||
return result;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction&, std::vector<AffectedAccount>&)
|
||||
{
|
||||
return tenINVALID;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn,
|
||||
std::vector<AffectedAccount>& accounts)
|
||||
{
|
||||
@@ -259,34 +463,34 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
|
||||
return tenINVALID;
|
||||
}
|
||||
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SerializedLedgerEntry::pointer dest = accounts[0].second;
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleDst = accounts[0].second;
|
||||
|
||||
if (!dest)
|
||||
if (!sleDst)
|
||||
{
|
||||
// Source account does not exist. Could succeed if it was created first.
|
||||
std::cerr << str(boost::format("doClaim: no such account: %s") % txn.getSourceAccount().humanAccountID()) << std::endl;
|
||||
return terNO_ACCOUNT;
|
||||
}
|
||||
|
||||
std::cerr << str(boost::format("doClaim: %s") % dest->getFullText()) << std::endl;
|
||||
std::cerr << str(boost::format("doClaim: %s") % sleDst->getFullText()) << std::endl;
|
||||
|
||||
if (dest->getIFieldPresent(sfAuthorizedKey))
|
||||
if (sleDst->getIFieldPresent(sfAuthorizedKey))
|
||||
{
|
||||
// Source account already claimed.
|
||||
std::cerr << "doClaim: source already claimed" << std::endl;
|
||||
return tenCLAIMED;
|
||||
return terCLAIMED;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify claim is authorized for public key.
|
||||
//
|
||||
|
||||
std::vector<unsigned char> vucCipher = txn.getITFieldVL(sfGenerator);
|
||||
std::vector<unsigned char> vucPubKey = txn.getITFieldVL(sfPubKey);
|
||||
std::vector<unsigned char> vucSignature = txn.getITFieldVL(sfSignature);
|
||||
std::vector<unsigned char> vucCipher = txn.getITFieldVL(sfGenerator);
|
||||
std::vector<unsigned char> vucPubKey = txn.getITFieldVL(sfPubKey);
|
||||
std::vector<unsigned char> vucSignature = txn.getITFieldVL(sfSignature);
|
||||
|
||||
NewcoinAddress naAccountPublic;
|
||||
NewcoinAddress naAccountPublic;
|
||||
|
||||
naAccountPublic.setAccountPublic(vucPubKey);
|
||||
|
||||
@@ -300,11 +504,11 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
|
||||
// Verify generator not already in use.
|
||||
//
|
||||
|
||||
uint160 hGeneratorID = naAccountPublic.getAccountID();
|
||||
uint160 hGeneratorID = naAccountPublic.getAccountID();
|
||||
|
||||
qry = lepNONE;
|
||||
SerializedLedgerEntry::pointer gen = mLedger->getGenerator(qry, hGeneratorID);
|
||||
if (gen)
|
||||
qry = lepNONE;
|
||||
SLE::pointer sleGen = mLedger->getGenerator(qry, hGeneratorID);
|
||||
if (sleGen)
|
||||
{
|
||||
// Generator is already in use. Regular passphrases limited to one wallet.
|
||||
std::cerr << "doClaim: generator already in use" << std::endl;
|
||||
@@ -316,36 +520,132 @@ TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction&
|
||||
//
|
||||
|
||||
// Set the public key needed to use the account.
|
||||
dest->setIFieldH160(sfAuthorizedKey, hGeneratorID);
|
||||
sleDst->setIFieldH160(sfAuthorizedKey, hGeneratorID);
|
||||
|
||||
// Construct a generator map entry.
|
||||
gen = boost::make_shared<SerializedLedgerEntry>(ltGENERATOR_MAP);
|
||||
sleGen = boost::make_shared<SerializedLedgerEntry>(ltGENERATOR_MAP);
|
||||
|
||||
gen->setIndex(Ledger::getGeneratorIndex(hGeneratorID));
|
||||
gen->setIFieldH160(sfGeneratorID, hGeneratorID);
|
||||
gen->setIFieldVL(sfGenerator, vucCipher);
|
||||
sleGen->setIndex(Ledger::getGeneratorIndex(hGeneratorID));
|
||||
sleGen->setIFieldH160(sfGeneratorID, hGeneratorID);
|
||||
sleGen->setIFieldVL(sfGenerator, vucCipher);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, gen));
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleGen));
|
||||
|
||||
std::cerr << "doClaim<" << std::endl;
|
||||
|
||||
return terSUCCESS;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::doCreditSet(const SerializedTransaction& txn,
|
||||
std::vector<AffectedAccount>&accounts,
|
||||
const uint160& uSrcAccountID)
|
||||
{
|
||||
TransactionEngineResult terResult = terSUCCESS;
|
||||
std::cerr << "doCreditSet>" << std::endl;
|
||||
|
||||
// Check if destination makes sense.
|
||||
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
|
||||
|
||||
if (!uDstAccountID)
|
||||
{
|
||||
std::cerr << "doCreditSet: Invalid transaction: Payment destination account not specifed." << std::endl;
|
||||
return tenDST_NEEDED;
|
||||
}
|
||||
else if (uSrcAccountID == uDstAccountID)
|
||||
{
|
||||
std::cerr << "doCreditSet: Invalid transaction: Source account is the same as destination." << std::endl;
|
||||
return tenDST_IS_SRC;
|
||||
}
|
||||
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID);
|
||||
if (!sleDst)
|
||||
{
|
||||
std::cerr << "doCreditSet: Delay transaction: Destination account does not exist." << std::endl;
|
||||
|
||||
return terNO_DST;
|
||||
}
|
||||
|
||||
STAmount saLimitAmount = txn.getITFieldAmount(sfLimitAmount);
|
||||
uint160 uCurrency = saLimitAmount.getCurrency();
|
||||
bool bSltD = uSrcAccountID < uDstAccountID;
|
||||
uint32 uFlags = bSltD ? lsfLowIndexed : lsfHighIndexed;
|
||||
STAmount saBalance(uCurrency);
|
||||
bool bAddIndex;
|
||||
|
||||
qry = lepNONE;
|
||||
SLE::pointer sleRippleState = mLedger->getRippleState(qry, uSrcAccountID, uDstAccountID, uCurrency);
|
||||
if (sleRippleState)
|
||||
{
|
||||
std::cerr << "doCreditSet: Modifying ripple line." << std::endl;
|
||||
|
||||
bAddIndex = !(sleRippleState->getFlags() & uFlags);
|
||||
|
||||
sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighID, saLimitAmount);
|
||||
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleRippleState));
|
||||
|
||||
if (bAddIndex)
|
||||
sleRippleState->setFlag(uFlags);
|
||||
}
|
||||
// Line does not exist.
|
||||
else if (!saLimitAmount.getValue())
|
||||
{
|
||||
std::cerr << "doCreditSet: Setting non-existant ripple line to 0." << std::endl;
|
||||
|
||||
return terNO_LINE_NO_ZERO;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "doCreditSet: Creating ripple line." << std::endl;
|
||||
STAmount saZero(uCurrency);
|
||||
|
||||
bAddIndex = true;
|
||||
sleRippleState = boost::make_shared<SerializedLedgerEntry>(ltRIPPLE_STATE);
|
||||
|
||||
sleRippleState->setIndex(Ledger::getRippleStateIndex(uSrcAccountID, uDstAccountID, uCurrency));
|
||||
|
||||
sleRippleState->setFlag(uFlags);
|
||||
sleRippleState->setIFieldAmount(sfBalance, saZero); // Zero balance in currency.
|
||||
sleRippleState->setIFieldAmount(bSltD ? sfLowLimit : sfHighLimit, saLimitAmount);
|
||||
sleRippleState->setIFieldAmount(bSltD ? sfHighLimit : sfLowLimit, saZero);
|
||||
sleRippleState->setIFieldAccount(bSltD ? sfLowID : sfHighID, uSrcAccountID);
|
||||
sleRippleState->setIFieldAccount(bSltD ? sfHighID : sfLowID, uDstAccountID);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleRippleState));
|
||||
}
|
||||
|
||||
if (bAddIndex)
|
||||
{
|
||||
// Add entries so clients can find lines.
|
||||
// - Client needs to be able to walk who account has given credit to and who has account's credit.
|
||||
// - Client doesn't need to know every account who has extended credit but it owed nothing.
|
||||
uint64 uSrcRef; // Ignored, ripple_state dirs never delete.
|
||||
|
||||
// XXX Verify extend is passing the right bits, not the zero bits.
|
||||
// XXX Make dirAdd more flexiable to take vector.
|
||||
terResult = dirAdd(accounts, uSrcRef, ltRIPPLE_STATE, uint160extend256(uSrcAccountID, 0), sleRippleState->getIndex());
|
||||
}
|
||||
|
||||
std::cerr << "doCreditSet<" << std::endl;
|
||||
|
||||
return terResult;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
uint160 srcAccountID)
|
||||
const uint160& srcAccountID)
|
||||
{
|
||||
uint32 txFlags = txn.getFlags();
|
||||
uint160 dstAccountID = txn.getITFieldAccount(sfDestination);
|
||||
uint160 uDstAccountID = txn.getITFieldAccount(sfDestination);
|
||||
|
||||
// Does the destination account exist?
|
||||
if (!dstAccountID)
|
||||
if (!uDstAccountID)
|
||||
{
|
||||
std::cerr << "doPayment: Invalid transaction: Payment destination account not specifed." << std::endl;
|
||||
return tenINVALID;
|
||||
}
|
||||
// XXX Only bad if no currency conversion in between through other people's offer.
|
||||
else if (srcAccountID == dstAccountID)
|
||||
else if (srcAccountID == uDstAccountID)
|
||||
{
|
||||
std::cerr << "doPayment: Invalid transaction: Source account is the same as destination." << std::endl;
|
||||
return tenINVALID;
|
||||
@@ -353,24 +653,23 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
|
||||
bool bCreate = !!(txFlags & tfCreateAccount);
|
||||
|
||||
uint160 currency;
|
||||
uint160 uCurrency;
|
||||
if (txn.getITFieldPresent(sfCurrency))
|
||||
{
|
||||
currency = txn.getITFieldH160(sfCurrency);
|
||||
if (!currency)
|
||||
uCurrency = txn.getITFieldH160(sfCurrency);
|
||||
if (!uCurrency)
|
||||
{
|
||||
std::cerr << "doPayment: Invalid transaction: XNC explicitly specified." << std::endl;
|
||||
std::cerr << "doPayment: Invalid transaction: " SYSTEM_CURRENCY_CODE " explicitly specified." << std::endl;
|
||||
return tenEXPLICITXNC;
|
||||
}
|
||||
}
|
||||
|
||||
LedgerStateParms qry = lepNONE;
|
||||
|
||||
SerializedLedgerEntry::pointer dest = mLedger->getAccountRoot(qry, dstAccountID);
|
||||
if (!dest)
|
||||
LedgerStateParms qry = lepNONE;
|
||||
SLE::pointer sleDst = mLedger->getAccountRoot(qry, uDstAccountID);
|
||||
if (!sleDst)
|
||||
{
|
||||
// Destination account does not exist.
|
||||
if (bCreate && !!currency)
|
||||
if (bCreate && !!uCurrency)
|
||||
{
|
||||
std::cerr << "doPayment: Invalid transaction: Create account may only fund XBC." << std::endl;
|
||||
return tenCREATEXNC;
|
||||
@@ -378,32 +677,32 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
else if (!bCreate)
|
||||
{
|
||||
std::cerr << "doPayment: Delay transaction: Destination account does not exist." << std::endl;
|
||||
return terNO_TARGET;
|
||||
return terNO_DST;
|
||||
}
|
||||
|
||||
// Create the account.
|
||||
dest = boost::make_shared<SerializedLedgerEntry>(ltACCOUNT_ROOT);
|
||||
sleDst = boost::make_shared<SerializedLedgerEntry>(ltACCOUNT_ROOT);
|
||||
|
||||
dest->setIndex(Ledger::getAccountRootIndex(dstAccountID));
|
||||
dest->setIFieldAccount(sfAccount, dstAccountID);
|
||||
dest->setIFieldU32(sfSequence, 1);
|
||||
sleDst->setIndex(Ledger::getAccountRootIndex(uDstAccountID));
|
||||
sleDst->setIFieldAccount(sfAccount, uDstAccountID);
|
||||
sleDst->setIFieldU32(sfSequence, 1);
|
||||
|
||||
accounts.push_back(std::make_pair(taaCREATE, dest));
|
||||
accounts.push_back(std::make_pair(taaCREATE, sleDst));
|
||||
}
|
||||
// Destination exists.
|
||||
else if (bCreate)
|
||||
{
|
||||
std::cerr << "doPayment: Invalid transaction: Account already created." << std::endl;
|
||||
return tenCREATED;
|
||||
return terCREATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
accounts.push_back(std::make_pair(taaMODIFY, dest));
|
||||
accounts.push_back(std::make_pair(taaMODIFY, sleDst));
|
||||
}
|
||||
|
||||
STAmount saAmount = txn.getITFieldAmount(sfAmount);
|
||||
|
||||
if (!currency)
|
||||
if (!uCurrency)
|
||||
{
|
||||
STAmount saSrcBalance = accounts[0].second->getIValueFieldAmount(sfBalance);
|
||||
|
||||
@@ -425,8 +724,122 @@ TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction
|
||||
return terSUCCESS;
|
||||
}
|
||||
|
||||
TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction&, std::vector<AffectedAccount>&)
|
||||
TransactionEngineResult TransactionEngine::doTransitSet(const SerializedTransaction& st, std::vector<AffectedAccount>&)
|
||||
{
|
||||
std::cerr << "doTransitSet>" << std::endl;
|
||||
#if 0
|
||||
SLE::pointer sleSrc = accounts[0].second;
|
||||
|
||||
bool bTxnTransitRate = st->getIFieldPresent(sfTransitRate);
|
||||
bool bTxnTransitStart = st->getIFieldPresent(sfTransitStart);
|
||||
bool bTxnTransitExpire = st->getIFieldPresent(sfTransitExpire);
|
||||
uint32 uTxnTransitRate = bTxnTransitRate ? st->getIFieldU32(sfTransitRate) : 0;
|
||||
uint32 uTxnTransitStart = bTxnTransitStart ? st->getIFieldU32(sfTransitStart) : 0;
|
||||
uint32 uTxnTransitExpire = bTxnTransitExpire ? st->getIFieldU32(sfTransitExpire) : 0;
|
||||
|
||||
bool bActTransitRate = sleSrc->getIFieldPresent(sfTransitRate);
|
||||
bool bActTransitExpire = sleSrc->getIFieldPresent(sfTransitExpire);
|
||||
bool bActNextTransitRate = sleSrc->getIFieldPresent(sfNextTransitRate);
|
||||
bool bActNextTransitStart = sleSrc->getIFieldPresent(sfNextTransitStart);
|
||||
bool bActNextTransitExpire = sleSrc->getIFieldPresent(sfNextTransitExpire);
|
||||
uint32 uActTransitRate = bActTransitRate ? sleSrc->getIFieldU32(sfTransitRate) : 0;
|
||||
uint32 uActTransitExpire = bActTransitExpire ? sleSrc->getIFieldU32(sfTransitExpire) : 0;
|
||||
uint32 uActNextTransitRate = bActNextTransitRate ? sleSrc->getIFieldU32(sfNextTransitRate) : 0;
|
||||
uint32 uActNextTransitStart = bActNextTransitStart ? sleSrc->getIFieldU32(sfNextTransitStart) : 0;
|
||||
uint32 uActNextTransitExpire = bActNextTransitExpire ? sleSrc->getIFieldU32(sfNextTransitExpire) : 0;
|
||||
|
||||
//
|
||||
// Update view
|
||||
//
|
||||
|
||||
bool bNoCurrent = !bActTransitRate;
|
||||
bool bCurrentExpired =
|
||||
bActTransitExpire // Current can expire
|
||||
&& bActNextTransitStart // Have a replacement
|
||||
&& uActTransitExpire <= uLedger; // Current is expired
|
||||
|
||||
// Replace current with next if need.
|
||||
if (bNoCurrent // No current.
|
||||
&& bActNextTransitRate // Have next.
|
||||
&& uActNextTransitStart <= uLedger) // Next has started.
|
||||
{
|
||||
// Make next current.
|
||||
uActTransitRate = uActNextTransitRate;
|
||||
bActTransitExpire = bActNextTransitStart;
|
||||
uActTransitExpire = uActNextTransitExpire;
|
||||
|
||||
// Remove next.
|
||||
uActNextTransitStart = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine new transaction deposition.
|
||||
//
|
||||
|
||||
bool bBetterThanCurrent =
|
||||
!no current
|
||||
|| (
|
||||
Expires same or later than current
|
||||
Start before or same as current
|
||||
Fee same or less than current
|
||||
)
|
||||
|
||||
bool bBetterThanNext =
|
||||
!no next
|
||||
|| (
|
||||
Expires same or later than next
|
||||
Start before or same as next
|
||||
Fee same or less than next
|
||||
)
|
||||
|
||||
bool bBetterThanBoth =
|
||||
bBetterThanCurrent && bBetterThanNext
|
||||
|
||||
bool bCurrentBlocks =
|
||||
!bBetterThanCurrent
|
||||
&& overlaps with current
|
||||
|
||||
bool bNextBlocks =
|
||||
!bBetterThanNext
|
||||
&& overlaps with next
|
||||
|
||||
if (bBetterThanBoth)
|
||||
{
|
||||
// Erase both and install.
|
||||
|
||||
// If not starting now, install as next.
|
||||
}
|
||||
else if (bCurrentBlocks || bNextBlocks)
|
||||
{
|
||||
// Invalid ignore
|
||||
}
|
||||
else if (bBetterThanCurrent)
|
||||
{
|
||||
// Install over current
|
||||
}
|
||||
else if (bBetterThanNext)
|
||||
{
|
||||
// Install over next
|
||||
}
|
||||
else
|
||||
{
|
||||
// Error.
|
||||
}
|
||||
|
||||
return tenTRANSIT_WORSE;
|
||||
|
||||
// Set current.
|
||||
uDstTransitRate = uTxnTransitRate;
|
||||
uDstTransitExpire = uTxnTransitExpire; // 0 for never expire.
|
||||
|
||||
// Set future.
|
||||
uDstNextTransitRate = uTxnTransitRate;
|
||||
uDstNextTransitStart = uTxnTransitStart;
|
||||
uDstNextTransitExpire = uTxnTransitExpire; // 0 for never expire.
|
||||
|
||||
if (txn.getITFieldPresent(sfCurrency))
|
||||
#endif
|
||||
std::cerr << "doTransitSet<" << std::endl;
|
||||
return tenINVALID;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,13 @@ enum TransactionEngineResult
|
||||
{
|
||||
// tenCAN_NEVER_SUCCEED = <0
|
||||
|
||||
// Malformed
|
||||
tenGEN_IN_USE = -300, // Generator already in use.
|
||||
// Malformed: Fee claimed
|
||||
tenGEN_IN_USE = -300, // Generator already in use.
|
||||
tenCREATEXNC, // Can not specify non XNC for Create.
|
||||
tenEXPLICITXNC, // XNC is used by default, don't specify it.
|
||||
tenDST_NEEDED, // Destination not specified.
|
||||
tenDST_IS_SRC, // Destination may not be source.
|
||||
|
||||
// Not possible due to ledger database.
|
||||
tenCREATED = -200, // Can not create a previously created account.
|
||||
tenCLAIMED, // Can not claim a previously claimed account.
|
||||
|
||||
// Other
|
||||
tenFAILED = -100, // Something broke horribly
|
||||
@@ -29,20 +28,29 @@ enum TransactionEngineResult
|
||||
tenINSUF_FEE_P, // fee totally insufficient
|
||||
tenINVALID, // The transaction is ill-formed
|
||||
|
||||
terSUCCESS = 0, // The transaction was applied
|
||||
terSUCCESS = 0, // The transaction was applied
|
||||
|
||||
// terFAILED_BUT_COULD_SUCEED = >0
|
||||
// terFAILED_BUT_COULD_SUCCEED = >0
|
||||
// Conflict with ledger database: Fee claimed
|
||||
// Might succeed if not conflict is not caused by transaction ordering.
|
||||
terALREADY, // The transaction was already in the ledger
|
||||
terNO_ACCOUNT, // The source account does not exist
|
||||
terNO_TARGET, // The destination does not exist
|
||||
terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load)
|
||||
terINSUF_FEE_B, // Account balance can't pay fee
|
||||
terUNFUNDED, // Source account had insufficient balance for transactin
|
||||
terNO_PATH, // No path existed or met transaction/balance requirements
|
||||
terPAST_SEQ, // This sequence number has already past
|
||||
terBAD_SEQ, // This sequence number should be zero for prepaid transactions.
|
||||
terPRE_SEQ, // Missing/inapplicable prior transaction
|
||||
terCLAIMED, // Can not claim a previously claimed account.
|
||||
terCREATED, // Can not create a previously created account.
|
||||
terDIR_FULL, // Can not add entry to full dir.
|
||||
terINSUF_FEE_B, // Account balance can't pay fee
|
||||
terINSUF_FEE_T, // fee insufficient now (account doesn't exist, network load)
|
||||
terNODE_NOT_FOUND, // Can not delete a dir node.
|
||||
terNODE_NOT_MENTIONED,
|
||||
terNODE_NO_ROOT,
|
||||
terNO_ACCOUNT, // The source account does not exist
|
||||
terNO_DST, // The destination does not exist
|
||||
terNO_PATH, // No path existed or met transaction/balance requirements
|
||||
terPAST_LEDGER, // The transaction expired and can't be applied
|
||||
terPAST_SEQ, // This sequence number has already past
|
||||
terPRE_SEQ, // Missing/inapplicable prior transaction
|
||||
terUNFUNDED, // Source account had insufficient balance for transactin
|
||||
terNO_LINE_NO_ZERO, // Can't zero non-existant line, destination might make it.
|
||||
};
|
||||
|
||||
enum TransactionEngineParams
|
||||
@@ -64,17 +72,33 @@ typedef std::pair<TransactionAccountAction, SerializedLedgerEntry::pointer> Affe
|
||||
|
||||
class TransactionEngine
|
||||
{
|
||||
private:
|
||||
TransactionEngineResult dirAdd(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
uint64& uNodeDir, // Node of entry.
|
||||
const LedgerEntryType letKind,
|
||||
const uint256& uBase,
|
||||
const uint256& uLedgerIndex);
|
||||
|
||||
TransactionEngineResult dirDelete(
|
||||
std::vector<AffectedAccount>& accounts,
|
||||
const uint64& uNodeDir, // Node item is mentioned in.
|
||||
const LedgerEntryType letKind,
|
||||
const uint256& uBase, // Key of item.
|
||||
const uint256& uLedgerIndex); // Item being deleted
|
||||
|
||||
protected:
|
||||
Ledger::pointer mLedger;
|
||||
|
||||
TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doCancel(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doClaim(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doCreditSet(const SerializedTransaction&, std::vector<AffectedAccount>&,
|
||||
const uint160& srcAccountID);
|
||||
TransactionEngineResult doDelete(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doPayment(const SerializedTransaction&, std::vector<AffectedAccount>&,
|
||||
uint160 srcAccountID);
|
||||
const uint160& srcAccountID);
|
||||
TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
TransactionEngineResult doTransitSet(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||
|
||||
@@ -18,9 +18,9 @@ TransactionFormat InnerTxnFormats[]=
|
||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||
{ S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(LimitAmount), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||
{ S_FIELD(BorrowRate), STI_UINT32, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(BorrowStart), STI_UINT32, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(BorrowExpire), STI_UINT32, SOE_IFFLAG, 4 },
|
||||
{ S_FIELD(AcceptRate), STI_UINT32, SOE_IFFLAG, 1 },
|
||||
{ S_FIELD(AcceptStart), STI_UINT32, SOE_IFFLAG, 2 },
|
||||
{ S_FIELD(AcceptExpire), STI_UINT32, SOE_IFFLAG, 4 },
|
||||
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 8 },
|
||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||
|
||||
@@ -40,7 +40,7 @@ void printHelp(const po::options_description& desc)
|
||||
cout << " account_info <account>|<nickname>" << endl;
|
||||
cout << " account_info <seed>|<pass_phrase>|<key> [<index>]" << endl;
|
||||
cout << " connect <ip> [<port>]" << endl;
|
||||
cout << " credit_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<borrow_rate>] [<borrow_start>] [<borrow_expire>]" << endl;
|
||||
cout << " credit_set <seed> <paying_account> <destination_account> <limit_amount> <currency> [<account_rate>]" << endl;
|
||||
cout << " ledger" << endl;
|
||||
cout << " peers" << endl;
|
||||
cout << " send <seed> <paying_account> <account_id> <amount> [<currency>] [<send_max>] [<send_currency>]" << endl;
|
||||
|
||||
Reference in New Issue
Block a user