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

This commit is contained in:
JoelKatz
2012-05-26 20:49:13 -07:00
21 changed files with 889 additions and 210 deletions

View File

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

View File

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

View File

@@ -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[];

View File

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

View File

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

View File

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

View File

@@ -65,6 +65,8 @@ public:
bool setAccountID(const std::string& strAccountID);
void setAccountID(const uint160& hash160In);
static NewcoinAddress createAccountID(const uint160& uiAccountID);
//
// Accounts Public
//

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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