diff --git a/src/Amount.cpp b/src/Amount.cpp index 637d4ef52d..28f3516cf3 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -299,7 +299,7 @@ void STAmount::add(Serializer& s) const } } -STAmount::STAmount(const char* name, int64 value) : SerializedType(name), mOffset(0), mIsNative(true) +STAmount::STAmount(SField::ref name, int64 value) : SerializedType(name), mOffset(0), mIsNative(true) { if (value >= 0) { @@ -325,13 +325,14 @@ void STAmount::setValue(const STAmount &a) uint64 STAmount::toUInt64() const { // makes them sort easily - if (mValue == 0) return 0x4000000000000000ull; + if (mValue == 0) + return 0x4000000000000000ull; if (mIsNegative) return mValue | (static_cast(mOffset + 97) << (64 - 10)); return mValue | (static_cast(mOffset + 256 + 97) << (64 - 10)); } -STAmount* STAmount::construct(SerializerIterator& sit, const char *name) +STAmount* STAmount::construct(SerializerIterator& sit, SField::ref name) { uint64 value = sit.get64(); @@ -351,8 +352,6 @@ STAmount* STAmount::construct(SerializerIterator& sit, const char *name) int offset = static_cast(value >> (64 - 10)); // 10 bits for the offset, sign and "not native" flag value &= ~(1023ull << (64-10)); - STAmount* sapResult; - if (value) { bool isNegative = (offset & 256) == 0; @@ -360,17 +359,12 @@ STAmount* STAmount::construct(SerializerIterator& sit, const char *name) if ((value < cMinValue) || (value > cMaxValue) || (offset < cMinOffset) || (offset > cMaxOffset)) throw std::runtime_error("invalid currency value"); - sapResult = new STAmount(name, uCurrencyID, uIssuerID, value, offset, isNegative); - } - else - { - if (offset != 512) - throw std::runtime_error("invalid currency value"); - - sapResult = new STAmount(name, uCurrencyID, uIssuerID); + return new STAmount(name, uCurrencyID, uIssuerID, value, offset, isNegative); } - return sapResult; + if (offset != 512) + throw std::runtime_error("invalid currency value"); + return new STAmount(name, uCurrencyID, uIssuerID); } int64 STAmount::getSNValue() const @@ -520,7 +514,7 @@ STAmount& STAmount::operator-=(const STAmount& a) STAmount STAmount::operator-(void) const { if (mValue == 0) return *this; - return STAmount(name, mCurrency, mIssuer, mValue, mOffset, mIsNative, !mIsNegative); + return STAmount(getFName(), mCurrency, mIssuer, mValue, mOffset, mIsNative, !mIsNegative); } STAmount& STAmount::operator=(uint64 v) @@ -573,12 +567,12 @@ bool STAmount::operator>=(uint64 v) const STAmount STAmount::operator+(uint64 v) const { - return STAmount(name, getSNValue() + static_cast(v)); + return STAmount(getFName(), getSNValue() + static_cast(v)); } STAmount STAmount::operator-(uint64 v) const { - return STAmount(name, getSNValue() - static_cast(v)); + return STAmount(getFName(), getSNValue() - static_cast(v)); } STAmount::operator double() const @@ -596,7 +590,7 @@ STAmount operator+(const STAmount& v1, const STAmount& v2) v1.throwComparable(v2); if (v1.mIsNative) - return STAmount(v1.name, v1.getSNValue() + v2.getSNValue()); + return STAmount(v1.getFName(), v1.getSNValue() + v2.getSNValue()); int ov1 = v1.mOffset, ov2 = v2.mOffset; @@ -618,9 +612,9 @@ STAmount operator+(const STAmount& v1, const STAmount& v2) int64 fv = vv1 + vv2; if (fv >= 0) - return STAmount(v1.name, v1.mCurrency, v1.mIssuer, fv, ov1, false); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, fv, ov1, false); else - return STAmount(v1.name, v1.mCurrency, v1.mIssuer, -fv, ov1, true); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, -fv, ov1, true); } STAmount operator-(const STAmount& v1, const STAmount& v2) @@ -629,7 +623,7 @@ STAmount operator-(const STAmount& v1, const STAmount& v2) v1.throwComparable(v2); if (v2.mIsNative) - return STAmount(v1.name, v1.getSNValue() - v2.getSNValue()); + return STAmount(v1.fName, v1.getSNValue() - v2.getSNValue()); int ov1 = v1.mOffset, ov2 = v2.mOffset; int64 vv1 = static_cast(v1.mValue), vv2 = static_cast(v2.mValue); @@ -650,9 +644,9 @@ STAmount operator-(const STAmount& v1, const STAmount& v2) int64 fv = vv1 - vv2; if (fv >= 0) - return STAmount(v1.name, v1.mCurrency, v1.mIssuer, fv, ov1, false); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, fv, ov1, false); else - return STAmount(v1.name, v1.mCurrency, v1.mIssuer, -fv, ov1, true); + return STAmount(v1.getFName(), v1.mCurrency, v1.mIssuer, -fv, ov1, true); } STAmount STAmount::divide(const STAmount& num, const STAmount& den, const uint160& uCurrencyID, const uint160& uIssuerID) @@ -704,7 +698,7 @@ STAmount STAmount::multiply(const STAmount& v1, const STAmount& v2, const uint16 return STAmount(uCurrencyID, uIssuerID); if (v1.mIsNative && v2.mIsNative) // FIXME: overflow - return STAmount(v1.name, v1.getSNValue() * v2.getSNValue()); + return STAmount(v1.getFName(), v1.getSNValue() * v2.getSNValue()); uint64 value1 = v1.mValue, value2 = v2.mValue; int offset1 = v1.mOffset, offset2 = v2.mOffset; @@ -883,19 +877,15 @@ uint64 STAmount::convertToDisplayAmount(const STAmount& internalAmount, uint64 t return muldiv(internalAmount.getNValue(), totalInit, totalNow); } -STAmount STAmount::convertToInternalAmount(uint64 displayAmount, uint64 totalNow, uint64 totalInit, - const char *name) +STAmount STAmount::convertToInternalAmount(uint64 displayAmount, uint64 totalNow, uint64 totalInit, SField::ref name) { // Convert a display/request currency amount to an internal amount return STAmount(name, muldiv(displayAmount, totalNow, totalInit)); } STAmount STAmount::deserialize(SerializerIterator& it) { - STAmount *s = construct(it); + std::auto_ptr s(dynamic_cast(construct(it, sfGeneric))); STAmount ret(*s); - - delete s; - return ret; } diff --git a/src/FieldNames.cpp b/src/FieldNames.cpp index a65ce1bc93..612d250c97 100644 --- a/src/FieldNames.cpp +++ b/src/FieldNames.cpp @@ -1,13 +1,97 @@ #include "FieldNames.h" -#define FIELD(name, type, index) { sf##name, #name, STI_##type, index }, +#include + +#include +#include +#include + + +// These must stay at the top of this file +std::map SField::codeToField; +boost::mutex SField::mapMutex; + +SField sfInvalid(-1), sfGeneric(0); +SField sfLedgerEntry(FIELD_CODE(STI_LEDGERENTRY, 1), STI_LEDGERENTRY, 1, "LedgerEntry"); +SField sfTransaction(FIELD_CODE(STI_TRANSACTION, 1), STI_TRANSACTION, 1, "Transaction"); +SField sfValidation(FIELD_CODE(STI_VALIDATION, 1), STI_VALIDATION, 1, "Validation"); + +#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name); #define TYPE(name, type, index) - -FieldName FieldNames[]= -{ #include "SerializeProto.h" -}; - #undef FIELD #undef TYPE + + +SField::ref SField::getField(int code) +{ + int type = code >> 16; + int field = code % 0xffff; + + if ((type <= 0) || (type >= 256) || (field <= 0) || (field >= 256)) + return sfInvalid; + + boost::mutex::scoped_lock sl(mapMutex); + + std::map::iterator it = codeToField.find(code); + if (it != codeToField.end()) + return *(it->second); + + switch (type) + { // types we are willing to dynamically extend + +#define FIELD(name, type, index) +#define TYPE(name, type, index) case STI_##type: +#include "SerializeProto.h" +#undef FIELD +#undef TYPE + + break; + default: + return sfInvalid; + } + + return *(new SField(code, static_cast(type), field, NULL)); +} + +int SField::compare(SField::ref f1, SField::ref f2) +{ // -1 = f1 comes before f2, 0 = illegal combination, 1 = f1 comes after f2 + if ((f1.fieldCode <= 0) || (f2.fieldCode <= 0)) + return 0; + + if (f1.fieldCode < f2.fieldCode) + return -1; + + if (f2.fieldCode < f1.fieldCode) + return 1; + + return 0; +} + +SField::ref SField::getField(int type, int value) +{ + return getField(FIELD_CODE(type, value)); +} + +std::string SField::getName() const +{ + if (!fieldName.empty()) + return fieldName; + if (fieldValue == 0) + return ""; + return boost::lexical_cast(static_cast(fieldType)) + "/" + + boost::lexical_cast(fieldValue); +} + +SField::ref SField::getField(const std::string& fieldName) +{ // OPTIMIZEME me with a map. CHECKME this is case sensitive + boost::mutex::scoped_lock sl(mapMutex); + typedef std::pair int_sfref_pair; + BOOST_FOREACH(const int_sfref_pair& fieldPair, codeToField) + { + if (fieldPair.second->fieldName == fieldName) + return *(fieldPair.second); + } + return sfInvalid; +} diff --git a/src/FieldNames.h b/src/FieldNames.h index af760127f6..ed51006499 100644 --- a/src/FieldNames.h +++ b/src/FieldNames.h @@ -1,16 +1,85 @@ #ifndef __FIELDNAMES__ #define __FIELDNAMES__ -#include "SerializedTypes.h" -#include "SerializedObject.h" +#include -struct FieldName +#include + +#define FIELD_CODE(type, index) ((static_cast(type) << 16) | index) + +enum SerializedTypeID { - SOE_Field field; - const char *fieldName; - SerializedTypeID fieldType; - int fieldValue; - int fieldID; + // special types + STI_UNKNOWN = -2, + STI_DONE = -1, + STI_NOTPRESENT = 0, + +#define TYPE(name, field, value) STI_##field = value, +#define FIELD(name, field, value) +#include "SerializeProto.h" +#undef TYPE +#undef FIELD + + // high level types + STI_TRANSACTION = 10001, + STI_LEDGERENTRY = 10002, + STI_VALIDATION = 10003, }; +enum SOE_Flags +{ + SOE_END = -1, // marks end of object + SOE_REQUIRED = 0, // required + SOE_OPTIONAL = 1, // optional +}; + +class SField +{ +public: + typedef const SField& ref; + typedef SField const * ptr; + +protected: + static std::map codeToField; + static boost::mutex mapMutex; + +public: + + const int fieldCode; // (type<<16)|index + const SerializedTypeID fieldType; // STI_* + const int fieldValue; // Code number for protocol + std::string fieldName; + + SField(int fc, SerializedTypeID tid, int fv, const char* fn) : + fieldCode(fc), fieldType(tid), fieldValue(fv), fieldName(fn) + { codeToField[fc] = this; } + + SField(int fc) : fieldCode(fc), fieldType(STI_UNKNOWN), fieldValue(0) { ; } + + static SField::ref getField(int fieldCode); + static SField::ref getField(int fieldType, int fieldValue); + static SField::ref getField(const std::string& fieldName); + static SField::ref getField(SerializedTypeID type, int value) { return getField(FIELD_CODE(type, value)); } + + std::string getName() const; + bool hasName() const { return !fieldName.empty(); } + + bool isGeneric() const { return fieldCode == 0; } + bool isInvalid() const { return fieldCode == -1; } + bool isKnown() const { return fieldType != STI_UNKNOWN; } + + bool operator==(const SField& f) const { return fieldCode == f.fieldCode; } + bool operator!=(const SField& f) const { return fieldCode != f.fieldCode; } + + static int compare(SField::ref f1, SField::ref f2); +}; + +extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation; + +#define FIELD(name, type, index) extern SField sf##name; +#define TYPE(name, type, index) +#include "SerializeProto.h" +#undef FIELD +#undef TYPE + #endif diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index 2b2af08a78..2dc6672f6f 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -977,21 +977,23 @@ void LedgerConsensus::applyTransaction(TransactionEngine& engine, const Serializ { #endif TER result = engine.applyTransaction(*txn, parms); - if (result > 0) + if (isTerRetry(result)) { Log(lsINFO) << " retry"; assert(!ledger->hasTransaction(txn->getTransactionID())); failedTransactions.push_back(txn); } - else if (result == 0) + else if (isTepSuccess(result)) // FIXME: Need to do partial success { Log(lsTRACE) << " success"; assert(ledger->hasTransaction(txn->getTransactionID())); } - else + else if (isTemMalformed(result) || isTefFailure(result)) { Log(lsINFO) << " hard fail"; } + else + assert(false); #ifndef TRUST_NETWORK } catch (...) diff --git a/src/LedgerEntrySet.cpp b/src/LedgerEntrySet.cpp index 8588f8f294..c64b90d972 100644 --- a/src/LedgerEntrySet.cpp +++ b/src/LedgerEntrySet.cpp @@ -876,7 +876,7 @@ uint32 LedgerEntrySet::rippleTransferRate(const uint160& uIssuerID) } // XXX Might not need this, might store in nodes on calc reverse. -uint32 LedgerEntrySet::rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID, const SOE_Field sfLow, const SOE_Field sfHigh) +uint32 LedgerEntrySet::rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID, SField::ref sfLow, SField::ref sfHigh) { uint32 uQuality = QUALITY_ONE; SLE::pointer sleRippleState; @@ -891,7 +891,7 @@ uint32 LedgerEntrySet::rippleQualityIn(const uint160& uToAccountID, const uint16 if (sleRippleState) { - SOE_Field sfField = uToAccountID < uFromAccountID ? sfLow: sfHigh; + SField::ref sfField = uToAccountID < uFromAccountID ? sfLow: sfHigh; uQuality = sleRippleState->getIFieldPresent(sfField) ? sleRippleState->getIFieldU32(sfField) diff --git a/src/LedgerEntrySet.h b/src/LedgerEntrySet.h index 150a5ae891..8a7c926c4e 100644 --- a/src/LedgerEntrySet.h +++ b/src/LedgerEntrySet.h @@ -104,7 +104,8 @@ public: uint32 rippleTransferRate(const uint160& uIssuerID); STAmount rippleOwed(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); STAmount rippleLimit(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID); - uint32 rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID, const SOE_Field sfLow=sfLowQualityIn, const SOE_Field sfHigh=sfHighQualityIn); + uint32 rippleQualityIn(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID, + SField::ref sfLow = sfLowQualityIn, SField::ref sfHigh = sfHighQualityIn); uint32 rippleQualityOut(const uint160& uToAccountID, const uint160& uFromAccountID, const uint160& uCurrencyID) { return rippleQualityIn(uToAccountID, uFromAccountID, uCurrencyID, sfLowQualityOut, sfHighQualityOut); } diff --git a/src/LedgerFormats.cpp b/src/LedgerFormats.cpp index fc70296bab..bc4ab86ed1 100644 --- a/src/LedgerFormats.cpp +++ b/src/LedgerFormats.cpp @@ -1,98 +1,103 @@ #include "LedgerFormats.h" -#define S_FIELD(x) sf##x, #x +#define LEF_BASE \ + { sfLedgerIndex, SOE_OPTIONAL }, \ + { sfLedgerEntryType, SOE_REQUIRED }, \ + { sfFlags, SOE_REQUIRED }, 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(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(AuthorizedKey), STI_ACCOUNT, 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(TransferRate), STI_UINT32, SOE_IFFLAG, 16 }, - { S_FIELD(Domain), STI_VL, SOE_IFFLAG, 32 }, - { S_FIELD(PublishHash), STI_HASH256, SOE_IFFLAG, 64 }, - { S_FIELD(PublishSize), STI_UINT32, SOE_IFFLAG, 128 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "AccountRoot", ltACCOUNT_ROOT, { LEF_BASE + { sfAccount, SOE_REQUIRED }, + { sfSequence, SOE_REQUIRED }, + { sfBalance, SOE_REQUIRED }, + { sfLastTxnID, SOE_REQUIRED }, + { sfLastTxnSeq, SOE_REQUIRED }, + { sfAuthorizedKey, SOE_OPTIONAL }, + { sfEmailHash, SOE_OPTIONAL }, + { sfWalletLocator, SOE_OPTIONAL }, + { sfMessageKey, SOE_OPTIONAL }, + { sfTransferRate, SOE_OPTIONAL }, + { sfDomain, SOE_OPTIONAL }, + { sfPublishHash, SOE_OPTIONAL }, + { sfPublishSize, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } }, - { "Contract", ltCONTRACT, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(Issuer), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Owner), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(BondAmount), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(CreateCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(FundCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(RemoveCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(ExpireCode), STI_VL, SOE_REQUIRED, 0 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "Contract", ltCONTRACT, { LEF_BASE + { sfLedgerEntryType,SOE_REQUIRED }, + { sfFlags, SOE_REQUIRED }, + { sfAccount, SOE_REQUIRED }, + { sfBalance, SOE_REQUIRED }, + { sfLastTxnID, SOE_REQUIRED }, + { sfLastTxnSeq, SOE_REQUIRED }, + { sfIssuer, SOE_REQUIRED }, + { sfOwner, SOE_REQUIRED }, + { sfExpiration, SOE_REQUIRED }, + { sfBondAmount, SOE_REQUIRED }, + { sfCreateCode, SOE_REQUIRED }, + { sfFundCode, SOE_REQUIRED }, + { sfRemoveCode, SOE_REQUIRED }, + { sfExpireCode, SOE_REQUIRED }, + { sfInvalid, SOE_END } } }, - { "DirectoryNode", ltDIR_NODE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Indexes), STI_VECTOR256, SOE_REQUIRED, 0 }, - { S_FIELD(IndexNext), STI_UINT64, SOE_IFFLAG, 1 }, - { S_FIELD(IndexPrevious), STI_UINT64, SOE_IFFLAG, 2 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "DirectoryNode", ltDIR_NODE, { LEF_BASE + { sfLedgerEntryType,SOE_REQUIRED }, + { sfFlags, SOE_REQUIRED }, + { sfIndexes, SOE_REQUIRED }, + { sfIndexNext, SOE_OPTIONAL }, + { sfIndexPrevious, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } }, - { "GeneratorMap", ltGENERATOR_MAP, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "GeneratorMap", ltGENERATOR_MAP, { LEF_BASE + { sfGenerator, SOE_REQUIRED }, + { sfInvalid, SOE_END } } }, - { "Nickname", ltNICKNAME, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Account), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "Nickname", ltNICKNAME, { LEF_BASE + { sfAccount, SOE_REQUIRED }, + { sfMinimumOffer, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } }, - { "Offer", ltOFFER, { - { 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(TakerPays), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(TakerGets), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(BookDirectory), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(BookNode), STI_UINT64, SOE_REQUIRED, 0 }, - { S_FIELD(OwnerNode), STI_UINT64, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(Expiration), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "Offer", ltOFFER, { LEF_BASE + { sfAccount, SOE_REQUIRED }, + { sfSequence, SOE_REQUIRED }, + { sfTakerPays, SOE_REQUIRED }, + { sfTakerGets, SOE_REQUIRED }, + { sfBookDirectory, SOE_REQUIRED }, + { sfBookNode, SOE_REQUIRED }, + { sfOwnerNode, SOE_REQUIRED }, + { sfLastTxnID, SOE_REQUIRED }, + { sfLastTxnSeq, SOE_REQUIRED }, + { sfExpiration, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } }, - { "RippleState", ltRIPPLE_STATE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Balance), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(LowLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(HighLimit), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnID), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(LastTxnSeq), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(LowQualityIn), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(LowQualityOut), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(HighQualityIn), STI_UINT32, SOE_IFFLAG, 4 }, - { S_FIELD(HighQualityOut), STI_UINT32, SOE_IFFLAG, 8 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } + { "RippleState", ltRIPPLE_STATE, { LEF_BASE + { sfBalance, SOE_REQUIRED }, + { sfLowLimit, SOE_REQUIRED }, + { sfHighLimit, SOE_REQUIRED }, + { sfLastTxnID, SOE_REQUIRED }, + { sfLastTxnSeq, SOE_REQUIRED }, + { sfLowQualityIn, SOE_OPTIONAL }, + { sfLowQualityOut, SOE_OPTIONAL }, + { sfHighQualityIn, SOE_OPTIONAL }, + { sfHighQualityOut, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } }, { NULL, ltINVALID } }; - LedgerEntryFormat* getLgrFormat(LedgerEntryType t) +{ + return getLgrFormat(static_cast(t)); +} + +LedgerEntryFormat* getLgrFormat(int t) { LedgerEntryFormat* f = LedgerFormats; while (f->t_name != NULL) { - if (f->t_type == t) return f; + if (f->t_type == t) + return f; ++f; } return NULL; diff --git a/src/LedgerFormats.h b/src/LedgerFormats.h index c1cdc505b6..7b4a95683e 100644 --- a/src/LedgerFormats.h +++ b/src/LedgerFormats.h @@ -41,12 +41,13 @@ enum LedgerSpecificFlags struct LedgerEntryFormat { - const char *t_name; - LedgerEntryType t_type; - SOElement elements[20]; + const char * t_name; + LedgerEntryType t_type; + SOElement elements[24]; }; extern LedgerEntryFormat LedgerFormats[]; extern LedgerEntryFormat* getLgrFormat(LedgerEntryType t); +extern LedgerEntryFormat* getLgrFormat(int t); #endif // vim:ts=4 diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 9988a03925..7985e2dbe6 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -83,17 +83,18 @@ uint32 NetworkOPs::getCurrentLedgerID() Transaction::pointer NetworkOPs::submitTransaction(const Transaction::pointer& tpTrans) { Serializer s; - tpTrans->getSTransaction()->add(s); - std::vector vucTransaction = s.getData(); - - SerializerIterator sit(s); - Transaction::pointer tpTransNew = Transaction::sharedTransaction(s.getData(), true); - assert(tpTransNew); - assert(tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction())); + + if(!tpTransNew->getSTransaction()->isEquivalent(*tpTrans->getSTransaction())) + { + Log(lsFATAL) << "Transaction reconstruction failure"; + Log(lsFATAL) << tpTransNew->getSTransaction()->getJson(0); + Log(lsFATAL) << tpTrans->getSTransaction()->getJson(0); + assert(false); + } (void) NetworkOPs::processTransaction(tpTransNew); diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index ffa8d0d439..ee3fb06204 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1777,17 +1777,17 @@ Json::Value RPCServer::doSend(const Json::Value& params) // Destination exists, ordinary send. STPathSet spsPaths; - /* uint160 srcCurrencyID; - bool ret_b; - ret_b = false; - STAmount::currencyFromString(srcCurrencyID, sSrcCurrency); + bool ret_b; + ret_b = false; - Pathfinder pf(naSrcAccountID, naDstAccountID, srcCurrencyID, saDstAmount); - - ret_b = pf.findPaths(5, 1, spsPaths); - // TODO: Nope; the above can't be right - */ + if (!saSrcAmountMax.isNative() || !saDstAmount.isNative()) + { + STAmount::currencyFromString(srcCurrencyID, sSrcCurrency); + Pathfinder pf(naSrcAccountID, naDstAccountID, srcCurrencyID, saDstAmount); + ret_b = pf.findPaths(5, 1, spsPaths); + } + trans = Transaction::sharedPayment( naAccountPublic, naAccountPrivate, naSrcAccountID, diff --git a/src/SerializeProto.h b/src/SerializeProto.h index d2336e8971..23a2260bb7 100644 --- a/src/SerializeProto.h +++ b/src/SerializeProto.h @@ -2,11 +2,11 @@ // appropriate #define statements. // types (common) - TYPE("Int32", UINT32, 1) - TYPE("Int64", UINT64, 2) - TYPE("Hash128", HASH128, 3) - TYPE("Hash256", HASH256, 4) - // 5 is reserved + TYPE("Int16", UINT16, 1) + TYPE("Int32", UINT32, 2) + TYPE("Int64", UINT64, 3) + TYPE("Hash128", HASH128, 4) + TYPE("Hash256", HASH256, 5) TYPE("Amount", AMOUNT, 6) TYPE("VariableLength", VL, 7) TYPE("Account", ACCOUNT, 8) @@ -16,28 +16,32 @@ // types (uncommon) TYPE("Int8", UINT8, 16) - TYPE("Int16", UINT16, 17) - TYPE("Hash160", HASH160, 18) - TYPE("PathSet", PATHSET, 19) - TYPE("Vector256", VECTOR256, 20) + TYPE("Hash160", HASH160, 17) + TYPE("PathSet", PATHSET, 18) + TYPE("Vector256", VECTOR256, 19) // 8-bit integers FIELD(CloseResolution, UINT8, 1) + // 16-bit integers + FIELD(LedgerEntryType, UINT16, 1) + FIELD(TransactionType, UINT16, 2) + // 32-bit integers (common) - FIELD(Flags, UINT32, 1) - FIELD(SourceTag, UINT32, 2) - FIELD(Sequence, UINT32, 3) - FIELD(LastTxnSeq, UINT32, 4) - FIELD(LedgerSequence, UINT32, 5) - FIELD(CloseTime, UINT32, 6) - FIELD(ParentCloseTime, UINT32, 7) - FIELD(SigningTime, UINT32, 8) - FIELD(Expiration, UINT32, 9) - FIELD(TransferRate, UINT32, 10) - FIELD(PublishSize, UINT32, 11) + FIELD(ObjectType, UINT32, 1) + FIELD(Flags, UINT32, 2) + FIELD(SourceTag, UINT32, 3) + FIELD(Sequence, UINT32, 4) + FIELD(LastTxnSeq, UINT32, 5) + FIELD(LedgerSequence, UINT32, 6) + FIELD(CloseTime, UINT32, 7) + FIELD(ParentCloseTime, UINT32, 8) + FIELD(SigningTime, UINT32, 9) + FIELD(Expiration, UINT32, 10) + FIELD(TransferRate, UINT32, 11) + FIELD(PublishSize, UINT32, 12) // 32-bit integers (uncommon) FIELD(HighQualityIn, UINT32, 16) @@ -59,7 +63,7 @@ FIELD(BaseFee, UINT64, 5) // 128-bit - FIELD(EmailHash, HASH128, 2) + FIELD(EmailHash, HASH128, 1) // 256-bit (common) FIELD(LedgerHash, HASH256, 1) @@ -67,8 +71,9 @@ FIELD(TransactionHash, HASH256, 3) FIELD(AccountHash, HASH256, 4) FIELD(LastTxnID, HASH256, 5) - FIELD(WalletLocator, HASH256, 6) - FIELD(PublishHash, HASH256, 7) + FIELD(LedgerIndex, HASH256, 6) + FIELD(WalletLocator, HASH256, 7) + FIELD(PublishHash, HASH256, 8) // 256-bit (uncommon) FIELD(BookDirectory, HASH256, 16) @@ -83,6 +88,7 @@ FIELD(TakerGets, AMOUNT, 5) FIELD(LowLimit, AMOUNT, 6) FIELD(HighLimit, AMOUNT, 7) + FIELD(Fee, AMOUNT, 8) FIELD(SendMax, AMOUNT, 9) // current amount (uncommon) @@ -92,14 +98,15 @@ // variable length FIELD(PublicKey, VL, 1) FIELD(MessageKey, VL, 2) - FIELD(SigningKey, VL, 3) - FIELD(Signature, VL, 4) + FIELD(SigningPubKey, VL, 3) + FIELD(TxnSignature, VL, 4) FIELD(Generator, VL, 5) - FIELD(Domain, VL, 6) - FIELD(FundCode, VL, 7) - FIELD(RemoveCode, VL, 8) - FIELD(ExpireCode, VL, 9) - FIELD(CreateCode, VL, 10) + FIELD(Signature, VL, 6) + FIELD(Domain, VL, 7) + FIELD(FundCode, VL, 8) + FIELD(RemoveCode, VL, 9) + FIELD(ExpireCode, VL, 10) + FIELD(CreateCode, VL, 11) // account FIELD(Account, ACCOUNT, 1) @@ -119,9 +126,9 @@ // inner object // OBJECT/1 is reserved for end of object - FIELD(MiddleTransaction, OBJECT, 2) - FIELD(InnerTransaction, OBJECT, 3) // array of objects // ARRAY/1 is reserved for end of array FIELD(SigningAccounts, ARRAY, 2) + FIELD(TxnSignatures, ARRAY, 3) + FIELD(Signatures, ARRAY, 4) diff --git a/src/SerializedLedger.cpp b/src/SerializedLedger.cpp index 08b807890e..4ba43bd1e3 100644 --- a/src/SerializedLedger.cpp +++ b/src/SerializedLedger.cpp @@ -6,35 +6,43 @@ #include "Log.h" SerializedLedgerEntry::SerializedLedgerEntry(SerializerIterator& sit, const uint256& index) - : SerializedType("LedgerEntry"), mIndex(index) + : STObject(sfLedgerEntry), mIndex(index) { - uint16 type = sit.get16(); + set(sit); + uint16 type = getValueFieldU16(sfLedgerEntryType); mFormat = getLgrFormat(static_cast(type)); - if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); + if (mFormat == NULL) + throw std::runtime_error("invalid ledger entry type"); mType = mFormat->t_type; - mVersion.setValue(type); - mObject = STObject(mFormat->elements, sit); + if (!setType(mFormat->elements)) + throw std::runtime_error("ledger entry not valid for type"); } SerializedLedgerEntry::SerializedLedgerEntry(const Serializer& s, const uint256& index) - : SerializedType("LedgerEntry"), mIndex(index) + : STObject(sfLedgerEntry), mIndex(index) { SerializerIterator sit(s); + set(sit); - uint16 type = sit.get16(); + uint16 type = getValueFieldU16(sfLedgerEntryType); mFormat = getLgrFormat(static_cast(type)); - if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); + if (mFormat == NULL) + throw std::runtime_error("invalid ledger entry type"); mType = mFormat->t_type; - mVersion.setValue(type); - mObject.set(mFormat->elements, sit); + if (!setType(mFormat->elements)) + { + Log(lsWARNING) << "Ledger entry not valid for type " << mFormat->t_name; + Log(lsWARNING) << getJson(0); + throw std::runtime_error("ledger entry not valid for type"); + } } -SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type) : SerializedType("LedgerEntry"), mType(type) +SerializedLedgerEntry::SerializedLedgerEntry(LedgerEntryType type) : STObject(sfLedgerEntry), mType(type) { mFormat = getLgrFormat(type); if (mFormat == NULL) throw std::runtime_error("invalid ledger entry type"); - mVersion.setValue(static_cast(mFormat->t_type)); - mObject.set(mFormat->elements); + set(mFormat->elements); + setValueFieldU16(sfLedgerEntryType, static_cast(mFormat->t_type)); } std::string SerializedLedgerEntry::getFullText() const @@ -44,76 +52,64 @@ std::string SerializedLedgerEntry::getFullText() const ret += "\" = { "; ret += mFormat->t_name; ret += ", "; - ret += mObject.getFullText(); + ret += STObject::getFullText(); ret += "}"; return ret; } std::string SerializedLedgerEntry::getText() const { - return str(boost::format("{ %s, %s, %s }") + return str(boost::format("{ %s, %s }") % mIndex.GetHex() - % mVersion.getText() - % mObject.getText()); + % STObject::getText()); } Json::Value SerializedLedgerEntry::getJson(int options) const { - Json::Value ret(mObject.getJson(options)); + Json::Value ret(STObject::getJson(options)); - ret["type"] = mFormat->t_name; ret["index"] = mIndex.GetHex(); - ret["version"] = std::string(1, mVersion); return ret; } -bool SerializedLedgerEntry::isEquivalent(const SerializedType& t) const -{ // locators are not compared - const SerializedLedgerEntry* v = dynamic_cast(&t); - if (!v) return false; - if (mType != v->mType) return false; - if (mObject != v->mObject) return false; - return true; -} - bool SerializedLedgerEntry::isThreadedType() { - return getIFieldIndex(sfLastTxnID) != -1; + return getFieldIndex(sfLastTxnID) != -1; } bool SerializedLedgerEntry::isThreaded() { - return getIFieldPresent(sfLastTxnID); + return isFieldPresent(sfLastTxnID); } uint256 SerializedLedgerEntry::getThreadedTransaction() { - return getIFieldH256(sfLastTxnID); + return getValueFieldH256(sfLastTxnID); } uint32 SerializedLedgerEntry::getThreadedLedger() { - return getIFieldU32(sfLastTxnSeq); + return getValueFieldU32(sfLastTxnSeq); } bool SerializedLedgerEntry::thread(const uint256& txID, uint32 ledgerSeq, uint256& prevTxID, uint32& prevLedgerID) { - uint256 oldPrevTxID = getIFieldH256(sfLastTxnID); + uint256 oldPrevTxID = getValueFieldH256(sfLastTxnID); Log(lsTRACE) << "Thread Tx:" << txID << " prev:" << oldPrevTxID; if (oldPrevTxID == txID) return false; prevTxID = oldPrevTxID; - prevLedgerID = getIFieldU32(sfLastTxnSeq); + prevLedgerID = getValueFieldU32(sfLastTxnSeq); assert(prevTxID != txID); - setIFieldH256(sfLastTxnID, txID); - setIFieldU32(sfLastTxnSeq, ledgerSeq); + setValueFieldH256(sfLastTxnID, txID); + setValueFieldU32(sfLastTxnSeq, ledgerSeq); return true; } bool SerializedLedgerEntry::hasOneOwner() { - return (mType != ltACCOUNT_ROOT) && (getIFieldIndex(sfAccount) != -1); + return (mType != ltACCOUNT_ROOT) && (getFieldIndex(sfAccount) != -1); } bool SerializedLedgerEntry::hasTwoOwners() @@ -123,7 +119,7 @@ bool SerializedLedgerEntry::hasTwoOwners() NewcoinAddress SerializedLedgerEntry::getOwner() { - return getIValueFieldAccount(sfAccount); + return getValueFieldAccount(sfAccount); } NewcoinAddress SerializedLedgerEntry::getFirstOwner() @@ -141,30 +137,24 @@ std::vector SerializedLedgerEntry::getOwners() std::vector owners; uint160 account; - for (int i = 0, fields = getIFieldCount(); i < fields; ++i) + for (int i = 0, fields = getCount(); i < fields; ++i) { - switch (getIFieldSType(i)) + SField::ref fc = getFieldSType(i); + if ((fc == sfAccount) || (fc == sfOwner)) { - case sfAccount: - { - const STAccount* entry = dynamic_cast(mObject.peekAtPIndex(i)); - if ((entry != NULL) && entry->getValueH160(account)) - owners.push_back(Ledger::getAccountRootIndex(account)); - } - break; - - case sfLowLimit: - case sfHighLimit: - { - const STAmount* entry = dynamic_cast(mObject.peekAtPIndex(i)); - if ((entry != NULL)) - owners.push_back(Ledger::getAccountRootIndex(entry->getIssuer())); - } - break; - - default: - nothing(); - break; + const STAccount* entry = dynamic_cast(peekAtPIndex(i)); + if ((entry != NULL) && entry->getValueH160(account)) + owners.push_back(Ledger::getAccountRootIndex(account)); + } + if ((fc == sfLowLimit) || (fc == sfHighLimit)) + { + const STAmount* entry = dynamic_cast(peekAtPIndex(i)); + if ((entry != NULL)) + { + uint160 issuer = entry->getIssuer(); + if (issuer.isNonZero()) + owners.push_back(Ledger::getAccountRootIndex(issuer)); + } } } diff --git a/src/SerializedLedger.h b/src/SerializedLedger.h index 1069887cc2..b7f35a34f4 100644 --- a/src/SerializedLedger.h +++ b/src/SerializedLedger.h @@ -5,7 +5,7 @@ #include "LedgerFormats.h" #include "NewcoinAddress.h" -class SerializedLedgerEntry : public SerializedType +class SerializedLedgerEntry : public STObject { public: typedef boost::shared_ptr pointer; @@ -14,8 +14,6 @@ public: protected: uint256 mIndex; LedgerEntryType mType; - STUInt16 mVersion; - STObject mObject; const LedgerEntryFormat* mFormat; SerializedLedgerEntry* duplicate() const { return new SerializedLedgerEntry(*this); } @@ -25,45 +23,18 @@ public: SerializedLedgerEntry(SerializerIterator& sit, const uint256& index); SerializedLedgerEntry(LedgerEntryType type); - int getLength() const { return mVersion.getLength() + mObject.getLength(); } SerializedTypeID getSType() const { return STI_LEDGERENTRY; } std::string getFullText() const; std::string getText() const; Json::Value getJson(int options) const; - 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; } + const uint256& getIndex() const { return mIndex; } + void setIndex(const uint256& i) { mIndex = i; } LedgerEntryType getType() const { return mType; } - uint16 getVersion() const { return mVersion.getValue(); } + uint16 getVersion() const { return getValueFieldU16(sfLedgerEntryType); } const LedgerEntryFormat* getFormat() { return mFormat; } - int getIFieldIndex(SOE_Field field) const { return mObject.getFieldIndex(field); } - int getIFieldCount() const { return mObject.getCount(); } - const SerializedType& peekIField(SOE_Field field) const { return mObject.peekAtField(field); } - SerializedType& getIField(SOE_Field field) { return mObject.getField(field); } - SOE_Field getIFieldSType(int index) { return mObject.getFieldSType(index); } - - std::string getIFieldString(SOE_Field field) const { return mObject.getFieldString(field); } - unsigned char getIFieldU8(SOE_Field field) const { return mObject.getValueFieldU8(field); } - uint16 getIFieldU16(SOE_Field field) const { return mObject.getValueFieldU16(field); } - uint32 getIFieldU32(SOE_Field field) const { return mObject.getValueFieldU32(field); } - uint64 getIFieldU64(SOE_Field field) const { return mObject.getValueFieldU64(field); } - uint128 getIFieldH128(SOE_Field field) const { return mObject.getValueFieldH128(field); } - uint160 getIFieldH160(SOE_Field field) const { return mObject.getValueFieldH160(field); } - uint256 getIFieldH256(SOE_Field field) const { return mObject.getValueFieldH256(field); } - std::vector getIFieldVL(SOE_Field field) const { return mObject.getValueFieldVL(field); } - std::vector 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); } - bool isThreadedType(); // is this a ledger entry that can be threaded bool isThreaded(); // is this ledger entry actually threaded bool hasOneOwner(); // This node has one other node that owns it (like nickname) @@ -76,28 +47,49 @@ public: bool thread(const uint256& txID, uint32 ledgerSeq, uint256& prevTxID, uint32& prevLedgerID); std::vector getOwners(); // nodes notified if this node is deleted - 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); } - void setIFieldU64(SOE_Field field, uint64 v) { return mObject.setValueFieldU64(field, v); } - void setIFieldH128(SOE_Field field, const uint128& v) { return mObject.setValueFieldH128(field, v); } - void setIFieldH160(SOE_Field field, const uint160& v) { return mObject.setValueFieldH160(field, v); } - void setIFieldH256(SOE_Field field, const uint256& v) { return mObject.setValueFieldH256(field, v); } - void setIFieldVL(SOE_Field field, const std::vector& v) - { return mObject.setValueFieldVL(field, v); } - void setIFieldTL(SOE_Field field, const std::vector& v) - { return mObject.setValueFieldTL(field, v); } - void setIFieldAccount(SOE_Field field, const uint160& account) - { return mObject.setValueFieldAccount(field, account); } - void setIFieldAccount(SOE_Field field, const NewcoinAddress& account) - { 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); } + // CAUTION: All these functions are now obsolete and will be removed after + // the new serialization code is merged. + int getIFieldIndex(SField::ref field) const { return getFieldIndex(field); } + int getIFieldCount() const { return getCount(); } + const SerializedType& peekIField(SField::ref field) const { return peekAtField(field); } + SerializedType& getIField(SField::ref field) { return getField(field); } + SField::ref getIFieldSType(int index) { return getFieldSType(index); } + std::string getIFieldString(SField::ref field) const { return getFieldString(field); } + unsigned char getIFieldU8(SField::ref field) const { return getValueFieldU8(field); } + uint16 getIFieldU16(SField::ref field) const { return getValueFieldU16(field); } + uint32 getIFieldU32(SField::ref field) const { return getValueFieldU32(field); } + uint64 getIFieldU64(SField::ref field) const { return getValueFieldU64(field); } + uint128 getIFieldH128(SField::ref field) const { return getValueFieldH128(field); } + uint160 getIFieldH160(SField::ref field) const { return getValueFieldH160(field); } + uint256 getIFieldH256(SField::ref field) const { return getValueFieldH256(field); } + std::vector getIFieldVL(SField::ref field) const { return getValueFieldVL(field); } + std::vector getIFieldTL(SField::ref field) const { return getValueFieldTL(field); } + NewcoinAddress getIValueFieldAccount(SField::ref field) const { return getValueFieldAccount(field); } + STAmount getIValueFieldAmount(SField::ref field) const { return getValueFieldAmount(field); } + STVector256 getIFieldV256(SField::ref field) { return getValueFieldV256(field); } + void setIFieldU8(SField::ref field, unsigned char v) { return setValueFieldU8(field, v); } + void setIFieldU16(SField::ref field, uint16 v) { return setValueFieldU16(field, v); } + void setIFieldU32(SField::ref field, uint32 v) { return setValueFieldU32(field, v); } + void setIFieldU64(SField::ref field, uint64 v) { return setValueFieldU64(field, v); } + void setIFieldH128(SField::ref field, const uint128& v) { return setValueFieldH128(field, v); } + void setIFieldH160(SField::ref field, const uint160& v) { return setValueFieldH160(field, v); } + void setIFieldH256(SField::ref field, const uint256& v) { return setValueFieldH256(field, v); } + void setIFieldVL(SField::ref field, const std::vector& v) + { return setValueFieldVL(field, v); } + void setIFieldTL(SField::ref field, const std::vector& v) + { return setValueFieldTL(field, v); } + void setIFieldAccount(SField::ref field, const uint160& account) + { return setValueFieldAccount(field, account); } + void setIFieldAccount(SField::ref field, const NewcoinAddress& account) + { return setValueFieldAccount(field, account); } + void setIFieldAmount(SField::ref field, const STAmount& amount) + { return setValueFieldAmount(field, amount); } + void setIFieldV256(SField::ref field, const STVector256& v) { return setValueFieldV256(field, v); } + bool getIFieldPresent(SField::ref field) const { return isFieldPresent(field); } + void makeIFieldPresent(SField::ref field) { makeFieldPresent(field); } + void makeIFieldAbsent(SField::ref field) { return makeFieldAbsent(field); } + // CAUTION: All the above functions are obsolete - bool getIFieldPresent(SOE_Field field) const { return mObject.isFieldPresent(field); } - void makeIFieldPresent(SOE_Field field) { mObject.makeFieldPresent(field); } - void makeIFieldAbsent(SOE_Field field) { return mObject.makeFieldAbsent(field); } }; typedef SerializedLedgerEntry SLE; diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index eaf7ec4006..0bfab6c928 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -3,13 +3,16 @@ #include #include +#include #include "../json/writer.h" #include "Log.h" -std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, const char *name) +std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, SField::ref name) { + assert((id == STI_NOTPRESENT) || (id == name.fieldType)); + switch(id) { case STI_NOTPRESENT: @@ -48,13 +51,19 @@ std::auto_ptr STObject::makeDefaultObject(SerializedTypeID id, c case STI_PATHSET: return std::auto_ptr(new STPathSet(name)); + case STI_OBJECT: + return std::auto_ptr(new STObject(name)); + + case STI_ARRAY: + return std::auto_ptr(new STArray(name)); + default: throw std::runtime_error("Unknown object type"); } } -std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID id, const char *name, - SerializerIterator& sit) +std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID id, SField::ref name, + SerializerIterator& sit, int depth) { switch(id) { @@ -94,89 +103,128 @@ std::auto_ptr STObject::makeDeserializedObject(SerializedTypeID case STI_PATHSET: return STPathSet::deserialize(sit, name); + case STI_ARRAY: + return STArray::deserialize(sit, name); + + case STI_OBJECT: + return STObject::deserialize(sit, name); + default: throw std::runtime_error("Unknown object type"); } } -void STObject::set(const SOElement* elem) +void STObject::set(SOElement::ptr elem) { mData.empty(); mType.empty(); - mFlagIdx = -1; - while (elem->e_id != STI_DONE) + while (elem->flags != SOE_END) { - if (elem->e_type == SOE_FLAGS) mFlagIdx = mType.size(); mType.push_back(elem); - if (elem->e_type == SOE_IFFLAG) - giveObject(makeDefaultObject(STI_NOTPRESENT, elem->e_name)); + if (elem->flags == SOE_OPTIONAL) + giveObject(makeNonPresentObject(elem->e_field)); else - giveObject(makeDefaultObject(elem->e_id, elem->e_name)); + giveObject(makeDefaultObject(elem->e_field)); ++elem; } } -STObject::STObject(const SOElement* elem, const char *name) : SerializedType(name) +bool STObject::setType(SOElement::ptrList t) { - set(elem); -} + boost::ptr_vector newData; + bool valid = true; -void STObject::set(const SOElement* elem, SerializerIterator& sit) -{ - mData.empty(); mType.empty(); - mFlagIdx = -1; - - int flags = -1; - while (elem->e_id != STI_DONE) + while (t->flags != SOE_END) { - mType.push_back(elem); - bool done = false; - if (elem->e_type == SOE_IFFLAG) - { - assert(flags >= 0); - if ((flags&elem->e_flags) == 0) + bool match = false; + for (boost::ptr_vector::iterator it = mData.begin(); it != mData.end(); ++it) + if (it->getFName() == t->e_field) { - done = true; - giveObject(makeDefaultObject(STI_NOTPRESENT, elem->e_name)); + match = true; + newData.push_back(mData.release(it).release()); + break; } - } - else if (elem->e_type == SOE_IFNFLAG) + + if (!match) { - assert(flags >= 0); - if ((flags&elem->e_flags) != 0) + if (t->flags != SOE_OPTIONAL) { - done = true; - giveObject(makeDefaultObject(elem->e_id, elem->e_name)); + Log(lsTRACE) << "setType !valid missing"; + valid = false; } + newData.push_back(makeNonPresentObject(t->e_field)); } - else if (elem->e_type == SOE_FLAGS) - { - assert(elem->e_id == STI_UINT32); - flags = sit.get32(); - mFlagIdx = giveObject(new STUInt32(elem->e_name, flags)); - done = true; - } - if (!done) - giveObject(makeDeserializedObject(elem->e_id, elem->e_name, sit)); - elem++; + + mType.push_back(t++); } + if (mData.size() != 0) + { + Log(lsTRACE) << "setType !valid leftover"; + valid = false; + } + mData.swap(newData); + return valid; } -STObject::STObject(const SOElement* elem, SerializerIterator& sit, const char *name) - : SerializedType(name), mFlagIdx(-1) +bool STObject::isValidForType() { - set(elem, sit); + boost::ptr_vector::iterator it = mData.begin(); + BOOST_FOREACH(SOElement::ptr elem, mType) + { + if (it == mData.end()) + return false; + if (elem->e_field != it->getFName()) + return false; + ++it; + } + + return true; +} + +bool STObject::isFieldAllowed(SField::ref field) +{ + BOOST_FOREACH(SOElement::ptr elem, mType) + { // are any required elemnents missing + if (elem->e_field == field) + return true; + } + return false; +} + +bool STObject::set(SerializerIterator& sit, int depth) +{ // return true = terminated with end-of-object + mData.empty(); + while (!sit.empty()) + { + int type, field; + sit.getFieldID(type, field); + if ((type == STI_OBJECT) && (field == 1)) // end of object indicator + return true; + SField::ref fn = SField::getField(type, field); + if (fn.isInvalid()) + throw std::runtime_error("Unknown field"); + giveObject(makeDeserializedObject(fn.fieldType, fn, sit, depth + 1)); + } + return false; +} + +std::auto_ptr STObject::deserialize(SerializerIterator& sit, SField::ref name) +{ + STObject *o; + std::auto_ptr object(o = new STObject(name)); + o->set(sit, 1); + return object; } std::string STObject::getFullText() const { std::string ret; bool first = true; - if (name != NULL) + if (fName->hasName()) { - ret = name; + ret = fName->getName(); ret += " = {"; } else ret = "{"; @@ -193,18 +241,33 @@ std::string STObject::getFullText() const return ret; } -int STObject::getLength() const +void STObject::add(Serializer& s, bool withSigningFields) const { - int ret = 0; - BOOST_FOREACH(const SerializedType& it, mData) - ret += it.getLength(); - return ret; -} + std::map fields; -void STObject::add(Serializer& s) const -{ BOOST_FOREACH(const SerializedType& it, mData) - it.add(s); + { // pick out the fields and sort them + if (it.getSType() != STI_NOTPRESENT) + { + SField::ref fName = it.getFName(); + if (withSigningFields || ((fName != sfTxnSignature) && (fName != sfTxnSignatures))) + fields.insert(std::make_pair(it.getFName().fieldCode, &it)); + } + } + + + typedef std::pair field_iterator; + BOOST_FOREACH(field_iterator& it, fields) + { // insert them in sorted order + const SerializedType* field = it.second; + + field->addFieldID(s); + field->add(s); + if (dynamic_cast(field) != NULL) + s.addFieldID(STI_ARRAY, 1); + else if (dynamic_cast(field) != NULL) + s.addFieldID(STI_OBJECT, 1); + } } std::string STObject::getText() const @@ -227,7 +290,8 @@ std::string STObject::getText() const bool STObject::isEquivalent(const SerializedType& t) const { const STObject* v = dynamic_cast(&t); - if (!v) return false; + if (!v) + return false; boost::ptr_vector::const_iterator it1 = mData.begin(), end1 = mData.end(); boost::ptr_vector::const_iterator it2 = v->mData.begin(), end2 = v->mData.end(); while ((it1 != end1) && (it2 != end2)) @@ -240,15 +304,35 @@ bool STObject::isEquivalent(const SerializedType& t) const return (it1 == end1) && (it2 == end2); } -int STObject::getFieldIndex(SOE_Field field) const +uint256 STObject::getHash(uint32 prefix) const +{ + Serializer s; + s.add32(prefix); + add(s, true); + return s.getSHA512Half(); +} + +uint256 STObject::getSigningHash(uint32 prefix) const +{ + Serializer s; + s.add32(prefix); + add(s, false); + return s.getSHA512Half(); +} + +int STObject::getFieldIndex(SField::ref field) const { int i = 0; - for (std::vector::const_iterator it = mType.begin(), end = mType.end(); it != end; ++it, ++i) - if ((*it)->e_field == field) return i; + BOOST_FOREACH(const SerializedType& elem, mData) + { + if (elem.getFName() == field) + return i; + ++i; + } return -1; } -const SerializedType& STObject::peekAtField(SOE_Field field) const +const SerializedType& STObject::peekAtField(SField::ref field) const { int index = getFieldIndex(field); if (index == -1) @@ -256,7 +340,7 @@ const SerializedType& STObject::peekAtField(SOE_Field field) const return peekAtIndex(index); } -SerializedType& STObject::getField(SOE_Field field) +SerializedType& STObject::getField(SField::ref field) { int index = getFieldIndex(field); if (index == -1) @@ -264,12 +348,12 @@ SerializedType& STObject::getField(SOE_Field field) return getIndex(index); } -SOE_Field STObject::getFieldSType(int index) const +SField::ref STObject::getFieldSType(int index) const { - return mType[index]->e_field; + return mData[index].getFName(); } -const SerializedType* STObject::peekAtPField(SOE_Field field) const +const SerializedType* STObject::peekAtPField(SField::ref field) const { int index = getFieldIndex(field); if (index == -1) @@ -277,7 +361,7 @@ const SerializedType* STObject::peekAtPField(SOE_Field field) const return peekAtPIndex(index); } -SerializedType* STObject::getPField(SOE_Field field) +SerializedType* STObject::getPField(SField::ref field) { int index = getFieldIndex(field); if (index == -1) @@ -285,7 +369,7 @@ SerializedType* STObject::getPField(SOE_Field field) return getPIndex(index); } -bool STObject::isFieldPresent(SOE_Field field) const +bool STObject::isFieldPresent(SField::ref field) const { int index = getFieldIndex(field); if (index == -1) @@ -295,76 +379,78 @@ bool STObject::isFieldPresent(SOE_Field field) const bool STObject::setFlag(uint32 f) { - if (mFlagIdx < 0) return false; - STUInt32* t = dynamic_cast(getPIndex(mFlagIdx)); - assert(t); + STUInt32* t = dynamic_cast(getPField(sfFlags)); + if (!t) + return false; t->setValue(t->getValue() | f); return true; } bool STObject::clearFlag(uint32 f) { - if (mFlagIdx < 0) return false; - STUInt32* t = dynamic_cast(getPIndex(mFlagIdx)); - assert(t); + STUInt32* t = dynamic_cast(getPField(sfFlags)); + if (!t) + return false; t->setValue(t->getValue() & ~f); return true; } uint32 STObject::getFlags(void) const { - if (mFlagIdx < 0) return 0; - const STUInt32* t = dynamic_cast(peekAtPIndex(mFlagIdx)); - assert(t); + const STUInt32* t = dynamic_cast(peekAtPField(sfFlags)); + if (!t) + return 0; return t->getValue(); } -SerializedType* STObject::makeFieldPresent(SOE_Field field) +SerializedType* STObject::makeFieldPresent(SField::ref field) { int index = getFieldIndex(field); if (index == -1) throw std::runtime_error("Field not found"); - if ((mType[index]->e_type != SOE_IFFLAG) && (mType[index]->e_type != SOE_IFNFLAG)) - throw std::runtime_error("field is not optional"); SerializedType* f = getPIndex(index); - if (f->getSType() != STI_NOTPRESENT) return f; - mData.replace(index, makeDefaultObject(mType[index]->e_id, mType[index]->e_name)); - f = getPIndex(index); - - if (mType[index]->e_type == SOE_IFFLAG) - setFlag(mType[index]->e_flags); - else if (mType[index]->e_type == SOE_IFNFLAG) - clearFlag(mType[index]->e_flags); - - return f; + if (f->getSType() != STI_NOTPRESENT) + return f; + mData.replace(index, makeDefaultObject(f->getFName())); + return getPIndex(index); } -void STObject::makeFieldAbsent(SOE_Field field) +void STObject::makeFieldAbsent(SField::ref field) { int index = getFieldIndex(field); if (index == -1) throw std::runtime_error("Field not found"); - if ((mType[index]->e_type != SOE_IFFLAG) && (mType[index]->e_type != SOE_IFNFLAG)) - throw std::runtime_error("field is not optional"); - if (peekAtIndex(index).getSType() == STI_NOTPRESENT) return; - mData.replace(index, new SerializedType(mType[index]->e_name)); + const SerializedType& f = peekAtIndex(index); + if (f.getSType() == STI_NOTPRESENT) + return; - if (mType[index]->e_type == SOE_IFFLAG) - clearFlag(mType[index]->e_flags); - else if (mType[index]->e_type == SOE_IFNFLAG) - setFlag(mType[index]->e_flags); + mData.replace(index, makeDefaultObject(f.getFName())); } -std::string STObject::getFieldString(SOE_Field field) const +bool STObject::delField(SField::ref field) +{ + int index = getFieldIndex(field); + if (index == -1) + return false; + delField(index); + return true; +} + +void STObject::delField(int index) +{ + mData.erase(mData.begin() + index); +} + +std::string STObject::getFieldString(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); return rf->getText(); } -unsigned char STObject::getValueFieldU8(SOE_Field field) const +unsigned char STObject::getValueFieldU8(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -375,7 +461,7 @@ unsigned char STObject::getValueFieldU8(SOE_Field field) const return cf->getValue(); } -uint16 STObject::getValueFieldU16(SOE_Field field) const +uint16 STObject::getValueFieldU16(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -386,7 +472,7 @@ uint16 STObject::getValueFieldU16(SOE_Field field) const return cf->getValue(); } -uint32 STObject::getValueFieldU32(SOE_Field field) const +uint32 STObject::getValueFieldU32(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -397,7 +483,7 @@ uint32 STObject::getValueFieldU32(SOE_Field field) const return cf->getValue(); } -uint64 STObject::getValueFieldU64(SOE_Field field) const +uint64 STObject::getValueFieldU64(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -408,7 +494,7 @@ uint64 STObject::getValueFieldU64(SOE_Field field) const return cf->getValue(); } -uint128 STObject::getValueFieldH128(SOE_Field field) const +uint128 STObject::getValueFieldH128(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -419,7 +505,7 @@ uint128 STObject::getValueFieldH128(SOE_Field field) const return cf->getValue(); } -uint160 STObject::getValueFieldH160(SOE_Field field) const +uint160 STObject::getValueFieldH160(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -430,7 +516,7 @@ uint160 STObject::getValueFieldH160(SOE_Field field) const return cf->getValue(); } -uint256 STObject::getValueFieldH256(SOE_Field field) const +uint256 STObject::getValueFieldH256(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -441,7 +527,7 @@ uint256 STObject::getValueFieldH256(SOE_Field field) const return cf->getValue(); } -NewcoinAddress STObject::getValueFieldAccount(SOE_Field field) const +NewcoinAddress STObject::getValueFieldAccount(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) @@ -459,7 +545,7 @@ NewcoinAddress STObject::getValueFieldAccount(SOE_Field field) const return cf->getValueNCA(); } -std::vector STObject::getValueFieldVL(SOE_Field field) const +std::vector STObject::getValueFieldVL(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -470,7 +556,7 @@ std::vector STObject::getValueFieldVL(SOE_Field field) const return cf->getValue(); } -STAmount STObject::getValueFieldAmount(SOE_Field field) const +STAmount STObject::getValueFieldAmount(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -481,7 +567,7 @@ STAmount STObject::getValueFieldAmount(SOE_Field field) const return *cf; } -STPathSet STObject::getValueFieldPathSet(SOE_Field field) const +STPathSet STObject::getValueFieldPathSet(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -492,7 +578,7 @@ STPathSet STObject::getValueFieldPathSet(SOE_Field field) const return *cf; } -STVector256 STObject::getValueFieldV256(SOE_Field field) const +STVector256 STObject::getValueFieldV256(SField::ref field) const { const SerializedType* rf = peekAtPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -503,7 +589,7 @@ STVector256 STObject::getValueFieldV256(SOE_Field field) const return *cf; } -void STObject::setValueFieldU8(SOE_Field field, unsigned char v) +void STObject::setValueFieldU8(SField::ref field, unsigned char v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -513,7 +599,7 @@ void STObject::setValueFieldU8(SOE_Field field, unsigned char v) cf->setValue(v); } -void STObject::setValueFieldU16(SOE_Field field, uint16 v) +void STObject::setValueFieldU16(SField::ref field, uint16 v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -523,7 +609,7 @@ void STObject::setValueFieldU16(SOE_Field field, uint16 v) cf->setValue(v); } -void STObject::setValueFieldU32(SOE_Field field, uint32 v) +void STObject::setValueFieldU32(SField::ref field, uint32 v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -533,7 +619,7 @@ void STObject::setValueFieldU32(SOE_Field field, uint32 v) cf->setValue(v); } -void STObject::setValueFieldU64(SOE_Field field, uint64 v) +void STObject::setValueFieldU64(SField::ref field, uint64 v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -543,7 +629,7 @@ void STObject::setValueFieldU64(SOE_Field field, uint64 v) cf->setValue(v); } -void STObject::setValueFieldH128(SOE_Field field, const uint128& v) +void STObject::setValueFieldH128(SField::ref field, const uint128& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -553,7 +639,7 @@ void STObject::setValueFieldH128(SOE_Field field, const uint128& v) cf->setValue(v); } -void STObject::setValueFieldH160(SOE_Field field, const uint160& v) +void STObject::setValueFieldH160(SField::ref field, const uint160& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -563,7 +649,7 @@ void STObject::setValueFieldH160(SOE_Field field, const uint160& v) cf->setValue(v); } -void STObject::setValueFieldH256(SOE_Field field, const uint256& v) +void STObject::setValueFieldH256(SField::ref field, const uint256& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -573,7 +659,7 @@ void STObject::setValueFieldH256(SOE_Field field, const uint256& v) cf->setValue(v); } -void STObject::setValueFieldV256(SOE_Field field, const STVector256& v) +void STObject::setValueFieldV256(SField::ref field, const STVector256& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -583,7 +669,7 @@ void STObject::setValueFieldV256(SOE_Field field, const STVector256& v) cf->setValue(v); } -void STObject::setValueFieldAccount(SOE_Field field, const uint160& v) +void STObject::setValueFieldAccount(SField::ref field, const uint160& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -593,7 +679,7 @@ void STObject::setValueFieldAccount(SOE_Field field, const uint160& v) cf->setValueH160(v); } -void STObject::setValueFieldVL(SOE_Field field, const std::vector& v) +void STObject::setValueFieldVL(SField::ref field, const std::vector& v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -603,7 +689,7 @@ void STObject::setValueFieldVL(SOE_Field field, const std::vector cf->setValue(v); } -void STObject::setValueFieldAmount(SOE_Field field, const STAmount &v) +void STObject::setValueFieldAmount(SField::ref field, const STAmount &v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -613,7 +699,7 @@ void STObject::setValueFieldAmount(SOE_Field field, const STAmount &v) (*cf) = v; } -void STObject::setValueFieldPathSet(SOE_Field field, const STPathSet &v) +void STObject::setValueFieldPathSet(SField::ref field, const STPathSet &v) { SerializedType* rf = getPField(field); if (!rf) throw std::runtime_error("Field not found"); @@ -631,9 +717,10 @@ Json::Value STObject::getJson(int options) const { if (it.getSType() != STI_NOTPRESENT) { - if (it.getName() == NULL) + if (!it.getFName().hasName()) ret[boost::lexical_cast(index)] = it.getJson(options); - else ret[it.getName()] = it.getJson(options); + else + ret[it.getName()] = it.getJson(options); } } return ret; @@ -649,6 +736,185 @@ Json::Value STVector256::getJson(int options) const return ret; } +std::string STArray::getFullText() const +{ + return "WRITEME"; +} + +std::string STArray::getText() const +{ + return "WRITEME"; +} + +Json::Value STArray::getJson(int) const +{ + return Json::Value("WRITEME"); +} + +void STArray::add(Serializer& s) const +{ + BOOST_FOREACH(const STObject& object, value) + { + object.addFieldID(s); + object.add(s); + s.addFieldID(STI_OBJECT, 1); + } +} + +bool STArray::isEquivalent(const SerializedType& t) const +{ + const STArray* v = dynamic_cast(&t); + if (!v) + return false; + return value == v->value; +} + +STArray* STArray::construct(SerializerIterator& sit, SField::ref field) +{ + vector value; + + while (!sit.empty()) + { + int type, field; + sit.getFieldID(type, field); + if ((type == STI_ARRAY) && (field == 1)) + break; + + SField::ref fn = SField::getField(type, field); + if (fn.isInvalid()) + throw std::runtime_error("Unknown field"); + + value.push_back(STObject(fn)); + value.rbegin()->set(sit, 1); + } + + return new STArray(field, value); +} + +std::auto_ptr STObject::parseJson(const Json::Value& object, SField::ref name, int depth) +{ + if (!object.isObject()) + throw std::runtime_error("Value is not an object"); + + boost::ptr_vector data; + Json::Value::Members members(object.getMemberNames()); + for (Json::Value::Members::iterator it = members.begin(), end = members.end(); it != end; ++it) + { + const std::string& name = *it; + const Json::Value& value = object[name]; + + SField::ref field = SField::getField(name); + if (field == sfInvalid) + throw std::runtime_error("Unknown field: " + name); + + switch (field.fieldType) + { + case STI_UINT8: + if (value.isString()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt8(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT16: + if (value.isString()) + { + std::string strValue = value.asString(); + if (!strValue.empty() && (strValue[0]<'0' || strValue[0]>'9')) + { + if (field == sfTransactionType) + { + // WRITEME + } + else if (field == sfLedgerEntryType) + { + // WRITEME + } + else + throw std::runtime_error("Invalid field data"); + } + data.push_back(new STUInt16(field, boost::lexical_cast(strValue))); + } + else if (value.isInt()) + data.push_back(new STUInt16(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt16(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT32: + if (value.isString()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt32(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + case STI_UINT64: + if (value.isString()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asString()))); + else if (value.isInt()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asInt()))); + else if (value.isUInt()) + data.push_back(new STUInt64(field, boost::lexical_cast(value.asUInt()))); + else + throw std::runtime_error("Incorrect type"); + break; + + + case STI_HASH128: + // WRITEME + + case STI_HASH160: + // WRITEME + + case STI_HASH256: + // WRITEME + + case STI_VL: + // WRITEME + + case STI_AMOUNT: + // WRITEME + + case STI_VECTOR256: + // WRITEME + + case STI_PATHSET: + // WRITEME + + case STI_OBJECT: + case STI_ACCOUNT: + case STI_TRANSACTION: + case STI_LEDGERENTRY: + case STI_VALIDATION: + if (!value.isObject()) + throw std::runtime_error("Inner value is not an object"); + if (depth > 64) + throw std::runtime_error("Json nest depth exceeded"); + data.push_back(parseJson(value, field, depth + 1)); + break; + + case STI_ARRAY: + // WRITEME + + default: + throw std::runtime_error("Invalid field type"); + } + } + return std::auto_ptr(new STObject(name, data)); +} + +#if 0 + static SOElement testSOElements[2][16] = { // field, name, id, type, flags { @@ -708,4 +974,6 @@ void STObject::unitTest() } +#endif + // vim:ts=4 diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 3ff352a793..58a926d983 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -9,62 +9,56 @@ #include "SerializedTypes.h" -enum SOE_Type -{ - SOE_NEVER = -1, // never occurs (marks end of object) - SOE_REQUIRED = 0, // required - SOE_FLAGS = 1, // flags field - SOE_IFFLAG = 2, // present if flag set - SOE_IFNFLAG = 3 // present if flag not set -}; +// Serializable object/array types -enum SOE_Field -{ - sfInvalid = -1, - sfGeneric = 0, - -#define FIELD(name, type, index) sf##name, -#define TYPE(name, type, index) -#include "SerializeProto.h" -#undef FIELD -#undef TYPE - - // test fields - sfTest1, sfTest2, sfTest3, sfTest4 -}; - -struct SOElement +class SOElement { // An element in the description of a serialized object - SOE_Field e_field; - const char *e_name; - SerializedTypeID e_id; - SOE_Type e_type; - int e_flags; +public: + typedef SOElement const * ptr; // used to point to one element + typedef SOElement const * ptrList; // used to point to a terminated list of elements + + SField::ref e_field; + const SOE_Flags flags; }; class STObject : public SerializedType { protected: - int mFlagIdx; // the offset to the flags object, -1 if none boost::ptr_vector mData; - std::vector mType; + std::vector mType; STObject* duplicate() const { return new STObject(*this); } + STObject(SField::ref name, boost::ptr_vector& data) : SerializedType(name) { mData.swap(data); } public: - STObject(const char *n = NULL) : SerializedType(n), mFlagIdx(-1) { ; } - STObject(const SOElement *t, const char *n = NULL); - STObject(const SOElement *t, SerializerIterator& u, const char *n = NULL); + STObject() { ; } + + STObject(SField::ref name) : SerializedType(name) { ; } + + STObject(SOElement::ptrList type, SField::ref name) : SerializedType(name) + { set(type); } + + STObject(SOElement::ptrList type, SerializerIterator& sit, SField::ref name) : SerializedType(name) + { set(sit); setType(type); } + + static std::auto_ptr parseJson(const Json::Value& value, SField::ref name, int depth = 0); + virtual ~STObject() { ; } - void set(const SOElement* t); - void set(const SOElement* t, SerializerIterator& u); + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name); + + bool setType(SOElement::ptrList); + bool isValidForType(); + bool isFieldAllowed(SField::ref); + + void set(SOElement::ptrList); + bool set(SerializerIterator& u, int depth = 0); - int getLength() const; virtual SerializedTypeID getSType() const { return STI_OBJECT; } virtual bool isEquivalent(const SerializedType& t) const; - void add(Serializer& s) const; + virtual void add(Serializer& s) const { add(s, true); } // just inner elements + void add(Serializer& s, bool withSignature) const; Serializer getSerializer() const { Serializer s; add(s); return s; } std::string getFullText() const; std::string getText() const; @@ -82,64 +76,132 @@ public: bool clearFlag(uint32); uint32 getFlags() const; + uint256 getHash(uint32 prefix) const; + uint256 getSigningHash(uint32 prefix) const; + const SerializedType& peekAtIndex(int offset) const { return mData[offset]; } SerializedType& getIndex(int offset) { return mData[offset]; } const SerializedType* peekAtPIndex(int offset) const { return &(mData[offset]); } SerializedType* getPIndex(int offset) { return &(mData[offset]); } - int getFieldIndex(SOE_Field field) const; - SOE_Field getFieldSType(int index) const; + int getFieldIndex(SField::ref field) const; + SField::ref getFieldSType(int index) const; - const SerializedType& peekAtField(SOE_Field field) const; - SerializedType& getField(SOE_Field field); - const SerializedType* peekAtPField(SOE_Field field) const; - SerializedType* getPField(SOE_Field field); - const SOElement* getFieldType(SOE_Field field) const; + const SerializedType& peekAtField(SField::ref field) const; + SerializedType& getField(SField::ref field); + const SerializedType* peekAtPField(SField::ref field) const; + SerializedType* getPField(SField::ref field); // these throw if the field type doesn't match, or return default values if the // field is optional but not present - std::string getFieldString(SOE_Field field) const; - unsigned char getValueFieldU8(SOE_Field field) const; - uint16 getValueFieldU16(SOE_Field field) const; - uint32 getValueFieldU32(SOE_Field field) const; - uint64 getValueFieldU64(SOE_Field field) const; - uint128 getValueFieldH128(SOE_Field field) const; - uint160 getValueFieldH160(SOE_Field field) const; - uint256 getValueFieldH256(SOE_Field field) const; - NewcoinAddress getValueFieldAccount(SOE_Field field) const; - std::vector getValueFieldVL(SOE_Field field) const; - std::vector getValueFieldTL(SOE_Field field) const; - STAmount getValueFieldAmount(SOE_Field field) const; - STPathSet getValueFieldPathSet(SOE_Field field) const; - STVector256 getValueFieldV256(SOE_Field field) const; + std::string getFieldString(SField::ref field) const; + unsigned char getValueFieldU8(SField::ref field) const; + uint16 getValueFieldU16(SField::ref field) const; + uint32 getValueFieldU32(SField::ref field) const; + uint64 getValueFieldU64(SField::ref field) const; + uint128 getValueFieldH128(SField::ref field) const; + uint160 getValueFieldH160(SField::ref field) const; + uint256 getValueFieldH256(SField::ref field) const; + NewcoinAddress getValueFieldAccount(SField::ref field) const; + std::vector getValueFieldVL(SField::ref field) const; + std::vector getValueFieldTL(SField::ref field) const; + STAmount getValueFieldAmount(SField::ref field) const; + STPathSet getValueFieldPathSet(SField::ref field) const; + STVector256 getValueFieldV256(SField::ref field) const; - void setValueFieldU8(SOE_Field field, unsigned char); - void setValueFieldU16(SOE_Field field, uint16); - void setValueFieldU32(SOE_Field field, uint32); - void setValueFieldU64(SOE_Field field, uint64); - void setValueFieldH128(SOE_Field field, const uint128&); - void setValueFieldH160(SOE_Field field, const uint160&); - void setValueFieldH256(SOE_Field field, const uint256&); - void setValueFieldVL(SOE_Field field, const std::vector&); - void setValueFieldTL(SOE_Field field, const std::vector&); - void setValueFieldAccount(SOE_Field field, const uint160&); - void setValueFieldAccount(SOE_Field field, const NewcoinAddress& addr) + void setValueFieldU8(SField::ref field, unsigned char); + void setValueFieldU16(SField::ref field, uint16); + void setValueFieldU32(SField::ref field, uint32); + void setValueFieldU64(SField::ref field, uint64); + void setValueFieldH128(SField::ref field, const uint128&); + void setValueFieldH160(SField::ref field, const uint160&); + void setValueFieldH256(SField::ref field, const uint256&); + void setValueFieldVL(SField::ref field, const std::vector&); + void setValueFieldTL(SField::ref field, const std::vector&); + void setValueFieldAccount(SField::ref field, const uint160&); + void setValueFieldAccount(SField::ref field, const NewcoinAddress& addr) { 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); + void setValueFieldAmount(SField::ref field, const STAmount&); + void setValueFieldPathSet(SField::ref field, const STPathSet&); + void setValueFieldV256(SField::ref field, const STVector256& v); - bool isFieldPresent(SOE_Field field) const; - SerializedType* makeFieldPresent(SOE_Field field); - void makeFieldAbsent(SOE_Field field); + bool isFieldPresent(SField::ref field) const; + SerializedType* makeFieldPresent(SField::ref field); + void makeFieldAbsent(SField::ref field); + bool delField(SField::ref field); + void delField(int index); - static std::auto_ptr makeDefaultObject(SerializedTypeID id, const char *name); - static std::auto_ptr makeDeserializedObject(SerializedTypeID id, const char *name, - SerializerIterator&); + static std::auto_ptr makeDefaultObject(SerializedTypeID id, SField::ref name); + static std::auto_ptr makeDeserializedObject(SerializedTypeID id, SField::ref name, + SerializerIterator&, int depth); + + static std::auto_ptr makeNonPresentObject(SField::ref name) + { return makeDefaultObject(STI_NOTPRESENT, name); } + static std::auto_ptr makeDefaultObject(SField::ref name) + { return makeDefaultObject(name.fieldType, name); } static void unitTest(); }; +class STArray : public SerializedType +{ +public: + typedef std::vector vector; + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::const_reverse_iterator const_reverse_iterator; + typedef std::vector::size_type size_type; + +protected: + + vector value; + + STArray* duplicate() const { return new STArray(*this); } + static STArray* construct(SerializerIterator&, SField::ref); + +public: + + STArray() { ; } + STArray(SField::ref f) : SerializedType(f) { ; } + STArray(SField::ref f, const vector& v) : SerializedType(f), value(v) { ; } + STArray(vector& v) : value(v) { ; } + + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) + { return std::auto_ptr(construct(sit, name)); } + + const vector& getValue() const { return value; } + vector& getValue() { return value; } + + // vector-like functions + void push_back(const STObject& object) { value.push_back(object); } + STObject& operator[](int j) { return value[j]; } + const STObject& operator[](int j) const { return value[j]; } + iterator begin() { return value.begin(); } + const_iterator begin() const { return value.begin(); } + iterator end() { return value.end(); } + const_iterator end() const { return value.end(); } + size_type size() const { return value.size(); } + reverse_iterator rbegin() { return value.rbegin(); } + const_reverse_iterator rbegin() const { return value.rbegin(); } + reverse_iterator rend() { return value.rend(); } + const_reverse_iterator rend() const { return value.rend(); } + iterator erase(iterator pos) { return value.erase(pos); } + void pop_back() { value.pop_back(); } + bool empty() const { return value.empty(); } + void clear() { value.clear(); } + + virtual std::string getFullText() const; + virtual std::string getText() const; + virtual Json::Value getJson(int) const; + virtual void add(Serializer& s) const; + + bool operator==(const STArray &s) { return value == s.value; } + bool operator!=(const STArray &s) { return value != s.value; } + + virtual SerializedTypeID getSType() const { return STI_ARRAY; } + virtual bool isEquivalent(const SerializedType& t) const; +}; #endif // vim:ts=4 diff --git a/src/SerializedTransaction.cpp b/src/SerializedTransaction.cpp index 0ee218028c..aca26946ca 100644 --- a/src/SerializedTransaction.cpp +++ b/src/SerializedTransaction.cpp @@ -7,21 +7,16 @@ #include "Log.h" #include "HashPrefixes.h" -SerializedTransaction::SerializedTransaction(TransactionType type) : mType(type) +SerializedTransaction::SerializedTransaction(TransactionType type) : STObject(sfTransaction), mType(type) { mFormat = getTxnFormat(type); - if (mFormat == NULL) throw std::runtime_error("invalid transaction type"); - - mMiddleTxn.giveObject(new STVariableLength("SigningPubKey")); - mMiddleTxn.giveObject(new STAccount("SourceAccount")); - mMiddleTxn.giveObject(new STUInt32("Sequence")); - mMiddleTxn.giveObject(new STUInt16("Type", static_cast(type))); - mMiddleTxn.giveObject(new STAmount("Fee")); - - mInnerTxn = STObject(mFormat->elements, "InnerTransaction"); + if (mFormat == NULL) + throw std::runtime_error("invalid transaction type"); + set(mFormat->elements); + setValueFieldU16(sfTransactionType, mFormat->t_type); } -SerializedTransaction::SerializedTransaction(SerializerIterator& sit) +SerializedTransaction::SerializedTransaction(SerializerIterator& sit) : STObject(sfTransaction) { int length = sit.getBytesLeft(); if ((length < TransactionMinLen) || (length > TransactionMaxLen)) @@ -30,32 +25,17 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit) throw std::runtime_error("Transaction length invalid"); } - mSignature.setValue(sit.getVL()); + set(sit); + mType = static_cast(getValueFieldU16(sfTransactionType)); - mMiddleTxn.giveObject(new STVariableLength("SigningPubKey", sit.getVL())); - - STAccount sa("SourceAccount", sit.getVL()); - mSourceAccount = sa.getValueNCA(); - mMiddleTxn.giveObject(new STAccount(sa)); - - mMiddleTxn.giveObject(new STUInt32("Sequence", sit.get32())); - - mType = static_cast(sit.get16()); - mMiddleTxn.giveObject(new STUInt16("Type", static_cast(mType))); mFormat = getTxnFormat(mType); if (!mFormat) + throw std::runtime_error("invalid transaction type"); + if (!setType(mFormat->elements)) { - Log(lsERROR) << "Transaction has invalid type"; - throw std::runtime_error("Transaction has invalid type"); + assert(false); + throw std::runtime_error("transaction not valid"); } - mMiddleTxn.giveObject(STAmount::deserialize(sit, "Fee")); - - mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction"); -} - -int SerializedTransaction::getLength() const -{ - return mSignature.getLength() + mMiddleTxn.getLength() + mInnerTxn.getLength(); } std::string SerializedTransaction::getFullText() const @@ -63,29 +43,21 @@ std::string SerializedTransaction::getFullText() const std::string ret = "\""; ret += getTransactionID().GetHex(); ret += "\" = {"; - ret += mSignature.getFullText(); - ret += mMiddleTxn.getFullText(); - ret += mInnerTxn.getFullText(); + ret += STObject::getFullText(); ret += "}"; return ret; } std::string SerializedTransaction::getText() const { - std::string ret = "{"; - ret += mSignature.getText(); - ret += mMiddleTxn.getText(); - ret += mInnerTxn.getText(); - ret += "}"; - return ret; + return STObject::getText(); } std::vector SerializedTransaction::getAffectedAccounts() const { std::vector accounts; - accounts.push_back(mSourceAccount); - BOOST_FOREACH(const SerializedType& it, mInnerTxn.peekData()) + BOOST_FOREACH(const SerializedType& it, peekData()) { const STAccount* sa = dynamic_cast(&it); if (sa != NULL) @@ -108,197 +80,70 @@ std::vector SerializedTransaction::getAffectedAccounts() const return accounts; } -void SerializedTransaction::add(Serializer& s) const -{ - mSignature.add(s); - mMiddleTxn.add(s); - mInnerTxn.add(s); -} - -bool SerializedTransaction::isEquivalent(const SerializedType& t) const -{ // Signatures are not compared - const SerializedTransaction* v = dynamic_cast(&t); - if (!v) return false; - if (mType != v->mType) return false; - if (mMiddleTxn != v->mMiddleTxn) return false; - if (mInnerTxn != v->mInnerTxn) return false; - return true; -} - uint256 SerializedTransaction::getSigningHash() const { - Serializer s; - s.add32(sHP_TransactionSign); - mMiddleTxn.add(s); - mInnerTxn.add(s); - return s.getSHA512Half(); + return STObject::getSigningHash(sHP_TransactionSign); } uint256 SerializedTransaction::getTransactionID() const { // perhaps we should cache this - Serializer s; - s.add32(sHP_TransactionID); - mSignature.add(s); - mMiddleTxn.add(s); - mInnerTxn.add(s); - return s.getSHA512Half(); + return getHash(sHP_TransactionID); } std::vector SerializedTransaction::getSignature() const { - return mSignature.getValue(); + try + { + return getValueFieldVL(sfTxnSignature); + } + catch (...) + { + return std::vector(); + } } -const std::vector& SerializedTransaction::peekSignature() const +void SerializedTransaction::sign(const NewcoinAddress& naAccountPrivate) { - return mSignature.peekValue(); -} - -bool SerializedTransaction::sign(const NewcoinAddress& naAccountPrivate) -{ - return naAccountPrivate.accountPrivateSign(getSigningHash(), mSignature.peekValue()); + std::vector signature; + naAccountPrivate.accountPrivateSign(getSigningHash(), signature); + setValueFieldVL(sfTxnSignature, signature); } bool SerializedTransaction::checkSign(const NewcoinAddress& naAccountPublic) const { - return naAccountPublic.accountPublicVerify(getSigningHash(), mSignature.getValue()); + try + { + return naAccountPublic.accountPublicVerify(getSigningHash(), getValueFieldVL(sfTxnSignature)); + } + catch (...) + { + return false; + } } -void SerializedTransaction::setSignature(const std::vector& sig) +void SerializedTransaction::setSigningPubKey(const NewcoinAddress& naSignPubKey) { - mSignature.setValue(sig); + setValueFieldVL(sfSigningPubKey, naSignPubKey.getAccountPublic()); } -STAmount SerializedTransaction::getTransactionFee() const +void SerializedTransaction::setSourceAccount(const NewcoinAddress& naSource) { - const STAmount* v = dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionIFee)); - if (!v) throw std::runtime_error("corrupt transaction"); - return *v; + setValueFieldAccount(sfAccount, naSource); } -void SerializedTransaction::setTransactionFee(const STAmount& fee) -{ - STAmount* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionIFee)); - if (!v) throw std::runtime_error("corrupt transaction"); - v->setValue(fee); -} - -uint32 SerializedTransaction::getSequence() const -{ - const STUInt32* v = dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISequence)); - if (!v) throw std::runtime_error("corrupt transaction"); - return v->getValue(); -} - -void SerializedTransaction::setSequence(uint32 seq) -{ - STUInt32* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISequence)); - if (!v) throw std::runtime_error("corrupt transaction"); - v->setValue(seq); -} - -std::vector SerializedTransaction::getSigningPubKey() const -{ - const STVariableLength* v = - dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningPubKey)); - if (!v) throw std::runtime_error("corrupt transaction"); - return v->getValue(); -} - -const std::vector& SerializedTransaction::peekSigningPubKey() const -{ - const STVariableLength* v= - dynamic_cast(mMiddleTxn.peekAtPIndex(TransactionISigningPubKey)); - if (!v) throw std::runtime_error("corrupt transaction"); - return v->peekValue(); -} - -std::vector& SerializedTransaction::peekSigningPubKey() -{ - STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningPubKey)); - if (!v) throw std::runtime_error("corrupt transaction"); - return v->peekValue(); -} - -const NewcoinAddress& SerializedTransaction::setSigningPubKey(const NewcoinAddress& naSignPubKey) -{ - mSignPubKey = naSignPubKey; - - STVariableLength* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISigningPubKey)); - if (!v) throw std::runtime_error("corrupt transaction"); - v->setValue(mSignPubKey.getAccountPublic()); - - return mSignPubKey; -} - -const NewcoinAddress& SerializedTransaction::setSourceAccount(const NewcoinAddress& naSource) -{ - mSourceAccount = naSource; - - STAccount* v = dynamic_cast(mMiddleTxn.getPIndex(TransactionISourceID)); - if (!v) throw std::runtime_error("corrupt transaction"); - v->setValueNCA(mSourceAccount); - return mSourceAccount; -} - -uint160 SerializedTransaction::getITFieldAccount(SOE_Field field) const +uint160 SerializedTransaction::getITFieldAccount(SField::ref field) const { uint160 r; - const SerializedType* st = mInnerTxn.peekAtPField(field); - if (!st) return r; - - const STAccount* ac = dynamic_cast(st); - if (!ac) return r; - ac->getValueH160(r); + const STAccount* ac = dynamic_cast(peekAtPField(field)); + if (ac) + ac->getValueH160(r); return r; } -int SerializedTransaction::getITFieldIndex(SOE_Field field) const -{ - return mInnerTxn.getFieldIndex(field); -} - -int SerializedTransaction::getITFieldCount() const -{ - return mInnerTxn.getCount(); -} - -bool SerializedTransaction::getITFieldPresent(SOE_Field field) const -{ - return mInnerTxn.isFieldPresent(field); -} - -const SerializedType& SerializedTransaction::peekITField(SOE_Field field) const -{ - return mInnerTxn.peekAtField(field); -} - -SerializedType& SerializedTransaction::getITField(SOE_Field field) -{ - return mInnerTxn.getField(field); -} - -void SerializedTransaction::makeITFieldPresent(SOE_Field field) -{ - mInnerTxn.makeFieldPresent(field); -} - -void SerializedTransaction::makeITFieldAbsent(SOE_Field field) -{ - return mInnerTxn.makeFieldAbsent(field); -} - Json::Value SerializedTransaction::getJson(int options) const { - Json::Value ret = Json::objectValue; + Json::Value ret = STObject::getJson(0); ret["id"] = getTransactionID().GetHex(); - ret["signature"] = mSignature.getText(); - - Json::Value middle = mMiddleTxn.getJson(options); - middle["type"] = mFormat->t_name; - ret["middle"] = middle; - - ret["inner"] = mInnerTxn.getJson(options); return ret; } diff --git a/src/SerializedTransaction.h b/src/SerializedTransaction.h index ee4ffb3ea4..295d0eb3cb 100644 --- a/src/SerializedTransaction.h +++ b/src/SerializedTransaction.h @@ -17,17 +17,13 @@ #define TXN_SQL_INCLUDED 'I' #define TXN_SQL_UNKNOWN 'U' -class SerializedTransaction : public SerializedType +class SerializedTransaction : public STObject { public: typedef boost::shared_ptr pointer; protected: - NewcoinAddress mSignPubKey; - NewcoinAddress mSourceAccount; TransactionType mType; - STVariableLength mSignature; - STObject mMiddleTxn, mInnerTxn; const TransactionFormat* mFormat; SerializedTransaction* duplicate() const { return new SerializedTransaction(*this); } @@ -37,84 +33,72 @@ public: SerializedTransaction(TransactionType type); // STObject functions - int getLength() const; SerializedTypeID getSType() const { return STI_TRANSACTION; } std::string getFullText() const; std::string getText() const; - void add(Serializer& s) const; - virtual bool isEquivalent(const SerializedType& t) const; // outer transaction functions / signature functions std::vector getSignature() const; - const std::vector& peekSignature() const; - void setSignature(const std::vector& s); + void setSignature(const std::vector& s) { setValueFieldVL(sfTxnSignature, s); } uint256 getSigningHash() const; - TransactionType getTxnType() const { return mType; } - STAmount getTransactionFee() const; - void setTransactionFee(const STAmount& fee); + TransactionType getTxnType() const { return mType; } + STAmount getTransactionFee() const { return getValueFieldAmount(sfFee); } + void setTransactionFee(const STAmount& fee) { setValueFieldAmount(sfFee, fee); } - const NewcoinAddress& getSourceAccount() const { return mSourceAccount; } - std::vector getSigningPubKey() const; - const std::vector& peekSigningPubKey() const; - std::vector& peekSigningPubKey(); - const NewcoinAddress& setSigningPubKey(const NewcoinAddress& naSignPubKey); - const NewcoinAddress& setSourceAccount(const NewcoinAddress& naSource); + NewcoinAddress getSourceAccount() const { return getValueFieldAccount(sfAccount); } + std::vector getSigningPubKey() const { return getValueFieldVL(sfSigningPubKey); } + void setSigningPubKey(const NewcoinAddress& naSignPubKey); + void setSourceAccount(const NewcoinAddress& naSource); std::string getTransactionType() const { return mFormat->t_name; } - // inner transaction functions - uint32 getFlags() const { return mInnerTxn.getFlags(); } - void setFlag(uint32 v) { mInnerTxn.setFlag(v); } - void clearFlag(uint32 v) { mInnerTxn.clearFlag(v); } + uint32 getSequence() const { return getValueFieldU32(sfSequence); } + void setSequence(uint32 seq) { return setValueFieldU32(sfSequence, seq); } - uint32 getSequence() const; - void setSequence(uint32); + // inner transaction field functions (OBSOLETE - use STObject functions) + int getITFieldIndex(SField::ref field) const { return getFieldIndex(field); } + const SerializedType& peekITField(SField::ref field) const { return peekAtField(field); } + SerializedType& getITField(SField::ref field) { return getField(field); } - // inner transaction field functions - int getITFieldIndex(SOE_Field field) const; - int getITFieldCount() const; - const SerializedType& peekITField(SOE_Field field) const; - SerializedType& getITField(SOE_Field field); + // inner transaction field value functions (OBSOLETE - use STObject functions) + std::string getITFieldString(SField::ref field) const { return getFieldString(field); } + unsigned char getITFieldU8(SField::ref field) const { return getValueFieldU8(field); } + uint16 getITFieldU16(SField::ref field) const { return getValueFieldU16(field); } + uint32 getITFieldU32(SField::ref field) const { return getValueFieldU32(field); } + uint64 getITFieldU64(SField::ref field) const { return getValueFieldU64(field); } + uint128 getITFieldH128(SField::ref field) const { return getValueFieldH128(field); } + uint160 getITFieldH160(SField::ref field) const { return getValueFieldH160(field); } + uint160 getITFieldAccount(SField::ref field) const; + uint256 getITFieldH256(SField::ref field) const { return getValueFieldH256(field); } + std::vector getITFieldVL(SField::ref field) const { return getValueFieldVL(field); } + std::vector getITFieldTL(SField::ref field) const { return getValueFieldTL(field); } + STAmount getITFieldAmount(SField::ref field) const { return getValueFieldAmount(field); } + STPathSet getITFieldPathSet(SField::ref field) const { return getValueFieldPathSet(field); } - // inner transaction field value functions - std::string getITFieldString(SOE_Field field) const { return mInnerTxn.getFieldString(field); } - unsigned char getITFieldU8(SOE_Field field) const { return mInnerTxn.getValueFieldU8(field); } - uint16 getITFieldU16(SOE_Field field) const { return mInnerTxn.getValueFieldU16(field); } - uint32 getITFieldU32(SOE_Field field) const { return mInnerTxn.getValueFieldU32(field); } - uint64 getITFieldU64(SOE_Field field) const { return mInnerTxn.getValueFieldU64(field); } - uint128 getITFieldH128(SOE_Field field) const { return mInnerTxn.getValueFieldH128(field); } - uint160 getITFieldH160(SOE_Field field) const { return mInnerTxn.getValueFieldH160(field); } - uint160 getITFieldAccount(SOE_Field field) const; - uint256 getITFieldH256(SOE_Field field) const { return mInnerTxn.getValueFieldH256(field); } - std::vector getITFieldVL(SOE_Field field) const { return mInnerTxn.getValueFieldVL(field); } - std::vector getITFieldTL(SOE_Field field) const { return mInnerTxn.getValueFieldTL(field); } - STAmount getITFieldAmount(SOE_Field field) const { return mInnerTxn.getValueFieldAmount(field); } - STPathSet getITFieldPathSet(SOE_Field field) const { return mInnerTxn.getValueFieldPathSet(field); } + void setITFieldU8(SField::ref field, unsigned char v) { return setValueFieldU8(field, v); } + void setITFieldU16(SField::ref field, uint16 v) { return setValueFieldU16(field, v); } + void setITFieldU32(SField::ref field, uint32 v) { return setValueFieldU32(field, v); } + void setITFieldU64(SField::ref field, uint32 v) { return setValueFieldU64(field, v); } + void setITFieldH128(SField::ref field, const uint128& v) { return setValueFieldH128(field, v); } + void setITFieldH160(SField::ref field, const uint160& v) { return setValueFieldH160(field, v); } + void setITFieldH256(SField::ref field, const uint256& v) { return setValueFieldH256(field, v); } + void setITFieldVL(SField::ref field, const std::vector& v) + { return setValueFieldVL(field, v); } + void setITFieldTL(SField::ref field, const std::vector& v) + { return setValueFieldTL(field, v); } + void setITFieldAccount(SField::ref field, const uint160& v) + { return setValueFieldAccount(field, v); } + void setITFieldAccount(SField::ref field, const NewcoinAddress& v) + { return setValueFieldAccount(field, v); } + void setITFieldAmount(SField::ref field, const STAmount& v) + { return setValueFieldAmount(field, v); } + void setITFieldPathSet(SField::ref field, const STPathSet& v) + { return setValueFieldPathSet(field, v); } - void setITFieldU8(SOE_Field field, unsigned char v) { return mInnerTxn.setValueFieldU8(field, v); } - void setITFieldU16(SOE_Field field, uint16 v) { return mInnerTxn.setValueFieldU16(field, v); } - void setITFieldU32(SOE_Field field, uint32 v) { return mInnerTxn.setValueFieldU32(field, v); } - void setITFieldU64(SOE_Field field, uint32 v) { return mInnerTxn.setValueFieldU64(field, v); } - void setITFieldH128(SOE_Field field, const uint128& v) { return mInnerTxn.setValueFieldH128(field, v); } - void setITFieldH160(SOE_Field field, const uint160& v) { return mInnerTxn.setValueFieldH160(field, v); } - void setITFieldH256(SOE_Field field, const uint256& v) { return mInnerTxn.setValueFieldH256(field, v); } - void setITFieldVL(SOE_Field field, const std::vector& v) - { return mInnerTxn.setValueFieldVL(field, v); } - void setITFieldTL(SOE_Field field, const std::vector& v) - { return mInnerTxn.setValueFieldTL(field, v); } - void setITFieldAccount(SOE_Field field, const uint160& v) - { return mInnerTxn.setValueFieldAccount(field, v); } - void setITFieldAccount(SOE_Field field, const NewcoinAddress& v) - { return mInnerTxn.setValueFieldAccount(field, v); } - void setITFieldAmount(SOE_Field field, const STAmount& v) - { return mInnerTxn.setValueFieldAmount(field, v); } - void setITFieldPathSet(SOE_Field field, const STPathSet& v) - { return mInnerTxn.setValueFieldPathSet(field, v); } - - // optional field functions - bool getITFieldPresent(SOE_Field field) const; - void makeITFieldPresent(SOE_Field field); - void makeITFieldAbsent(SOE_Field field); + // optional field functions (OBSOLETE - use STObject functions) + bool getITFieldPresent(SField::ref field) const { return isFieldPresent(field); } + void makeITFieldPresent(SField::ref field) { makeFieldPresent(field); } + void makeITFieldAbsent(SField::ref field) { makeFieldAbsent(field); } std::vector getAffectedAccounts() const; @@ -122,7 +106,7 @@ public: virtual Json::Value getJson(int options) const; - bool sign(const NewcoinAddress& naAccountPrivate); + void sign(const NewcoinAddress& naAccountPrivate); bool checkSign(const NewcoinAddress& naAccountPublic) const; // SQL Functions diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index dde47265c0..4cee5f5c9b 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -5,6 +5,8 @@ #include "SerializedTypes.h" #include "SerializedObject.h" #include "TransactionFormats.h" +#include "LedgerFormats.h" +#include "FieldNames.h" #include "Log.h" #include "NewcoinAddress.h" #include "utils.h" @@ -17,9 +19,9 @@ std::string SerializedType::getFullText() const std::string ret; if (getSType() != STI_NOTPRESENT) { - if(name != NULL) + if(fName->hasName()) { - ret = name; + ret = fName->fieldName; ret += " = "; } ret += getText(); @@ -27,7 +29,7 @@ std::string SerializedType::getFullText() const return ret; } -STUInt8* STUInt8::construct(SerializerIterator& u, const char *name) +STUInt8* STUInt8::construct(SerializerIterator& u, SField::ref name) { return new STUInt8(name, u.get8()); } @@ -43,13 +45,25 @@ bool STUInt8::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STUInt16* STUInt16::construct(SerializerIterator& u, const char *name) +STUInt16* STUInt16::construct(SerializerIterator& u, SField::ref name) { return new STUInt16(name, u.get16()); } std::string STUInt16::getText() const { + if (getFName() == sfLedgerEntryType) + { + LedgerEntryFormat *f = getLgrFormat(value); + if (f != NULL) + return f->t_name; + } + if (getFName() == sfTransactionType) + { + TransactionFormat *f = getTxnFormat(value); + if (f != NULL) + return f->t_name; + } return boost::lexical_cast(value); } @@ -59,7 +73,7 @@ bool STUInt16::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STUInt32* STUInt32::construct(SerializerIterator& u, const char *name) +STUInt32* STUInt32::construct(SerializerIterator& u, SField::ref name) { return new STUInt32(name, u.get32()); } @@ -75,7 +89,7 @@ bool STUInt32::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STUInt64* STUInt64::construct(SerializerIterator& u, const char *name) +STUInt64* STUInt64::construct(SerializerIterator& u, SField::ref name) { return new STUInt64(name, u.get64()); } @@ -91,7 +105,7 @@ bool STUInt64::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STHash128* STHash128::construct(SerializerIterator& u, const char *name) +STHash128* STHash128::construct(SerializerIterator& u, SField::ref name) { return new STHash128(name, u.get128()); } @@ -107,7 +121,7 @@ bool STHash128::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STHash160* STHash160::construct(SerializerIterator& u, const char *name) +STHash160* STHash160::construct(SerializerIterator& u, SField::ref name) { return new STHash160(name, u.get160()); } @@ -123,7 +137,7 @@ bool STHash160::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STHash256* STHash256::construct(SerializerIterator& u, const char *name) +STHash256* STHash256::construct(SerializerIterator& u, SField::ref name) { return new STHash256(name, u.get256()); } @@ -139,7 +153,7 @@ bool STHash256::isEquivalent(const SerializedType& t) const return v && (value == v->value); } -STVariableLength::STVariableLength(SerializerIterator& st, const char *name) : SerializedType(name) +STVariableLength::STVariableLength(SerializerIterator& st, SField::ref name) : SerializedType(name) { value = st.getVL(); } @@ -149,16 +163,11 @@ std::string STVariableLength::getText() const return strHex(value); } -STVariableLength* STVariableLength::construct(SerializerIterator& u, const char *name) +STVariableLength* STVariableLength::construct(SerializerIterator& u, SField::ref name) { return new STVariableLength(name, u.getVL()); } -int STVariableLength::getLength() const -{ - return Serializer::encodeLengthLength(value.size()) + value.size(); -} - bool STVariableLength::isEquivalent(const SerializedType& t) const { const STVariableLength* v = dynamic_cast(&t); @@ -176,7 +185,7 @@ std::string STAccount::getText() const return a.humanAccountID(); } -STAccount* STAccount::construct(SerializerIterator& u, const char *name) +STAccount* STAccount::construct(SerializerIterator& u, SField::ref name) { return new STAccount(name, u.getVL()); } @@ -186,7 +195,7 @@ STAccount* STAccount::construct(SerializerIterator& u, const char *name) // // Return a new object from a SerializerIterator. -STVector256* STVector256::construct(SerializerIterator& u, const char *name) +STVector256* STVector256::construct(SerializerIterator& u, SField::ref name) { std::vector data = u.getVL(); std::vector value; @@ -255,7 +264,7 @@ void STAccount::setValueNCA(const NewcoinAddress& nca) setValueH160(nca.getAccountID()); } -STPathSet* STPathSet::construct(SerializerIterator& s, const char *name) +STPathSet* STPathSet::construct(SerializerIterator& s, SField::ref name) { std::vector paths; std::vector path; @@ -342,18 +351,6 @@ int STPath::getSerializeSize() const return iBytes; } -int STPathSet::getLength() const -{ - int iBytes = 0; - - BOOST_FOREACH(const STPath& spPath, value) - { - iBytes += spPath.getSerializeSize(); - } - - return iBytes ? iBytes : 1; -} - Json::Value STPath::getJson(int) const { Json::Value ret(Json::arrayValue); diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index 28a3063677..de1fb75eb6 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -8,28 +8,13 @@ #include "uint256.h" #include "Serializer.h" +#include "FieldNames.h" -enum SerializedTypeID -{ - // special types - STI_DONE = -1, - STI_NOTPRESENT = 0, - -#define TYPE(name, field, value) STI_##field = value, -#define FIELD(name, field, value) -#include "SerializeProto.h" -#undef TYPE -#undef FIELD - - // high level types - STI_TRANSACTION = 100001, - STI_LEDGERENTRY = 100002 -}; enum PathFlags { PF_END = 0x00, // End of current path & path list. - PF_BOUNDRY = 0xFF, // End of current path & new path follows. + PF_BOUNDARY = 0xFF, // End of current path & new path follows. PF_ACCOUNT = 0x01, PF_OFFER = 0x02, @@ -48,24 +33,25 @@ enum PathFlags class SerializedType { protected: - const char* name; + SField::ptr fName; - virtual SerializedType* duplicate() const { return new SerializedType(name); } + virtual SerializedType* duplicate() const { return new SerializedType(*fName); } + SerializedType(SField::ptr n) : fName(n) { assert(fName); } public: - SerializedType() : name(NULL) { ; } - SerializedType(const char* n) : name(n) { ; } - SerializedType(const SerializedType& n) : name(n.name) { ; } + SerializedType() : fName(&sfGeneric) { ; } + SerializedType(SField::ref n) : fName(&n) { assert(fName); } + SerializedType(const SerializedType& n) : fName(n.fName) { ; } virtual ~SerializedType() { ; } - static std::auto_ptr deserialize(const char* name) + static std::auto_ptr deserialize(SField::ref name) { return std::auto_ptr(new SerializedType(name)); } - void setName(const char* n) { name=n; } - const char *getName() const { return name; } + void setFName(SField::ref n) { fName = &n; assert(fName); } + SField::ref getFName() const { return *fName; } + std::string getName() const { return fName->fieldName; } - virtual int getLength() const { return 0; } virtual SerializedTypeID getSType() const { return STI_NOTPRESENT; } std::auto_ptr clone() const { return std::auto_ptr(duplicate()); } @@ -75,13 +61,15 @@ public: virtual Json::Value getJson(int) const { return getText(); } - virtual void add(Serializer& s) const { return; } + virtual void add(Serializer& s) const { ; } virtual bool isEquivalent(const SerializedType& t) const { assert(getSType() == STI_NOTPRESENT); return t.getSType() == STI_NOTPRESENT; } + void addFieldID(Serializer& s) const { s.addFieldID(fName->fieldType, fName->fieldValue); } + SerializedType& operator=(const SerializedType& t) - { name = (name == NULL) ? t.name : name; return *this; } + { if (!fName->fieldCode) fName = t.fName; return *this; } bool operator==(const SerializedType& t) const { return (getSType() == t.getSType()) && isEquivalent(t); } bool operator!=(const SerializedType& t) const @@ -97,23 +85,22 @@ class STUInt8 : public SerializedType protected: unsigned char value; - STUInt8* duplicate() const { return new STUInt8(name, value); } - static STUInt8* construct(SerializerIterator&, const char* name = NULL); + STUInt8* duplicate() const { return new STUInt8(*this); } + static STUInt8* construct(SerializerIterator&, SField::ref f); public: - STUInt8(unsigned char v=0) : value(v) { ; } - STUInt8(const char* n, unsigned char v=0) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + STUInt8(unsigned char v = 0) : value(v) { ; } + STUInt8(SField::ref n, unsigned char v = 0) : SerializedType(n), value(v) { ; } + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 1; } SerializedTypeID getSType() const { return STI_UINT8; } std::string getText() const; void add(Serializer& s) const { s.add8(value); } unsigned char getValue() const { return value; } - void setValue(unsigned char v) { value=v; } + void setValue(unsigned char v) { value = v; } operator unsigned char() const { return value; } virtual bool isEquivalent(const SerializedType& t) const; @@ -124,17 +111,16 @@ class STUInt16 : public SerializedType protected: uint16 value; - STUInt16* duplicate() const { return new STUInt16(name, value); } - static STUInt16* construct(SerializerIterator&, const char* name = NULL); + STUInt16* duplicate() const { return new STUInt16(*this); } + static STUInt16* construct(SerializerIterator&, SField::ref name); public: - STUInt16(uint16 v=0) : value(v) { ; } - STUInt16(const char* n, uint16 v=0) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + STUInt16(uint16 v = 0) : value(v) { ; } + STUInt16(SField::ref n, uint16 v = 0) : SerializedType(n), value(v) { ; } + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 2; } SerializedTypeID getSType() const { return STI_UINT16; } std::string getText() const; void add(Serializer& s) const { s.add16(value); } @@ -151,17 +137,16 @@ class STUInt32 : public SerializedType protected: uint32 value; - STUInt32* duplicate() const { return new STUInt32(name, value); } - static STUInt32* construct(SerializerIterator&, const char* name = NULL); + STUInt32* duplicate() const { return new STUInt32(*this); } + static STUInt32* construct(SerializerIterator&, SField::ref name); public: - STUInt32(uint32 v=0) : value(v) { ; } - STUInt32(const char* n, uint32 v=0) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + STUInt32(uint32 v = 0) : value(v) { ; } + STUInt32(SField::ref n, uint32 v = 0) : SerializedType(n), value(v) { ; } + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 4; } SerializedTypeID getSType() const { return STI_UINT32; } std::string getText() const; void add(Serializer& s) const { s.add32(value); } @@ -178,17 +163,16 @@ class STUInt64 : public SerializedType protected: uint64 value; - STUInt64* duplicate() const { return new STUInt64(name, value); } - static STUInt64* construct(SerializerIterator&, const char* name = NULL); + STUInt64* duplicate() const { return new STUInt64(*this); } + static STUInt64* construct(SerializerIterator&, SField::ref name); public: - STUInt64(uint64 v=0) : value(v) { ; } - STUInt64(const char* n, uint64 v=0) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + STUInt64(uint64 v = 0) : value(v) { ; } + STUInt64(SField::ref n, uint64 v = 0) : SerializedType(n), value(v) { ; } + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 8; } SerializedTypeID getSType() const { return STI_UINT64; } std::string getText() const; void add(Serializer& s) const { s.add64(value); } @@ -224,7 +208,7 @@ protected: void canonicalize(); STAmount* duplicate() const { return new STAmount(*this); } - static STAmount* construct(SerializerIterator&, const char* name = NULL); + static STAmount* construct(SerializerIterator&, SField::ref name); static const int cMinOffset = -96, cMaxOffset = 80; static const uint64 cMinValue = 1000000000000000ull, cMaxValue = 9999999999999999ull; @@ -234,13 +218,15 @@ protected: STAmount(bool isNeg, uint64 value) : mValue(value), mOffset(0), mIsNative(true), mIsNegative(isNeg) { ; } - STAmount(const char *name, uint64 value, bool isNegative) + STAmount(SField::ref name, uint64 value, bool isNegative) : SerializedType(name), mValue(value), mOffset(0), mIsNative(true), mIsNegative(isNegative) { ; } - STAmount(const char *n, const uint160& cur, const uint160& iss, uint64 val, int off, bool isNat, bool isNeg) - : SerializedType(n), mCurrency(cur), mIssuer(iss), mValue(val), mOffset(off), + STAmount(SField::ref name, const uint160& cur, const uint160& iss, uint64 val, int off, bool isNat, bool isNeg) + : SerializedType(name), mCurrency(cur), mIssuer(iss), mValue(val), mOffset(off), mIsNative(isNat), mIsNegative(isNeg) { ; } + STAmount(SField::ref name, const Json::Value& value); + uint64 toUInt64() const; static uint64 muldiv(uint64, uint64, uint64); @@ -248,38 +234,33 @@ public: static uint64 uRateOne; STAmount(uint64 v = 0, bool isNeg = false) : mValue(v), mOffset(0), mIsNative(true), mIsNegative(isNeg) - { if (v==0) mIsNegative = false; } + { if (v == 0) mIsNegative = false; } - STAmount(const char* n, uint64 v = 0) + STAmount(SField::ref n, uint64 v = 0) : SerializedType(n), mValue(v), mOffset(0), mIsNative(true), mIsNegative(false) { ; } - STAmount(const uint160& uCurrencyID, const uint160& uIssuerID, uint64 uV=0, int iOff=0, bool bNegative=false) + STAmount(const uint160& uCurrencyID, const uint160& uIssuerID, uint64 uV = 0, int iOff = 0, bool bNegative = false) : mCurrency(uCurrencyID), mIssuer(uIssuerID), mValue(uV), mOffset(iOff), mIsNegative(bNegative) { canonicalize(); } // YYY This should probably require issuer too. - STAmount(const char* n, const uint160& currency, const uint160& issuer, + STAmount(SField::ref n, const uint160& currency, const uint160& issuer, uint64 v = 0, int off = 0, bool isNeg = false) : SerializedType(n), mCurrency(currency), mIssuer(issuer), mValue(v), mOffset(off), mIsNegative(isNeg) { canonicalize(); } - STAmount(const char* n, int64 v); + STAmount(SField::ref n, int64 v); - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } static STAmount saFromRate(uint64 uRate = 0) - { - return STAmount(CURRENCY_ONE, ACCOUNT_ONE, uRate, -9, false); - } + { return STAmount(CURRENCY_ONE, ACCOUNT_ONE, uRate, -9, false); } - static STAmount saFromSigned(const uint160& uCurrencyID, const uint160& uIssuerID, int64 iV=0, int iOff=0) - { - return STAmount(uCurrencyID, uIssuerID, iV < 0 ? -iV : iV, iOff, iV < 0); - } + static STAmount saFromSigned(const uint160& uCurrencyID, const uint160& uIssuerID, int64 iV = 0, int iOff = 0) + { return STAmount(uCurrencyID, uIssuerID, iV < 0 ? -iV : iV, iOff, iV < 0); } - int getLength() const { return mIsNative ? 8 : 28; } SerializedTypeID getSType() const { return STI_AMOUNT; } std::string getText() const; std::string getRaw() const; @@ -377,7 +358,7 @@ public: // Native currency conversions, to/from display format static uint64 convertToDisplayAmount(const STAmount& internalAmount, uint64 totalNow, uint64 totalInit); static STAmount convertToInternalAmount(uint64 displayAmount, uint64 totalNow, uint64 totalInit, - const char* name = NULL); + SField::ref name = sfGeneric); static std::string createHumanCurrency(const uint160& uCurrency); static STAmount deserialize(SerializerIterator&); @@ -394,19 +375,18 @@ class STHash128 : public SerializedType protected: uint128 value; - STHash128* duplicate() const { return new STHash128(name, value); } - static STHash128* construct(SerializerIterator&, const char* name = NULL); + STHash128* duplicate() const { return new STHash128(*this); } + static STHash128* construct(SerializerIterator&, SField::ref name); public: STHash128(const uint128& v) : value(v) { ; } - STHash128(const char* n, const uint128& v) : SerializedType(n), value(v) { ; } - STHash128(const char* n) : SerializedType(n) { ; } + STHash128(SField::ref n, const uint128& v) : SerializedType(n), value(v) { ; } + STHash128(SField::ref n) : SerializedType(n) { ; } STHash128() { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 20; } SerializedTypeID getSType() const { return STI_HASH128; } virtual std::string getText() const; void add(Serializer& s) const { s.add128(value); } @@ -423,19 +403,18 @@ class STHash160 : public SerializedType protected: uint160 value; - STHash160* duplicate() const { return new STHash160(name, value); } - static STHash160* construct(SerializerIterator&, const char* name = NULL); + STHash160* duplicate() const { return new STHash160(*this); } + static STHash160* construct(SerializerIterator&, SField::ref name); public: STHash160(const uint160& v) : value(v) { ; } - STHash160(const char* n, const uint160& v) : SerializedType(n), value(v) { ; } - STHash160(const char* n) : SerializedType(n) { ; } + STHash160(SField::ref n, const uint160& v) : SerializedType(n), value(v) { ; } + STHash160(SField::ref n) : SerializedType(n) { ; } STHash160() { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 20; } SerializedTypeID getSType() const { return STI_HASH160; } virtual std::string getText() const; void add(Serializer& s) const { s.add160(value); } @@ -452,19 +431,18 @@ class STHash256 : public SerializedType protected: uint256 value; - STHash256* duplicate() const { return new STHash256(name, value); } - static STHash256* construct(SerializerIterator&, const char* name = NULL); + STHash256* duplicate() const { return new STHash256(*this); } + static STHash256* construct(SerializerIterator&, SField::ref); public: STHash256(const uint256& v) : value(v) { ; } - STHash256(const char* n, const uint256& v) : SerializedType(n), value(v) { ; } - STHash256(const char* n) : SerializedType(n) { ; } + STHash256(SField::ref n, const uint256& v) : SerializedType(n), value(v) { ; } + STHash256(SField::ref n) : SerializedType(n) { ; } STHash256() { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const { return 32; } SerializedTypeID getSType() const { return STI_HASH256; } std::string getText() const; void add(Serializer& s) const { s.add256(value); } @@ -481,20 +459,19 @@ class STVariableLength : public SerializedType protected: std::vector value; - virtual STVariableLength* duplicate() const { return new STVariableLength(name, value); } - static STVariableLength* construct(SerializerIterator&, const char* name = NULL); + virtual STVariableLength* duplicate() const { return new STVariableLength(*this); } + static STVariableLength* construct(SerializerIterator&, SField::ref); public: STVariableLength(const std::vector& v) : value(v) { ; } - STVariableLength(const char* n, const std::vector& v) : SerializedType(n), value(v) { ; } - STVariableLength(const char* n) : SerializedType(n) { ; } - STVariableLength(SerializerIterator&, const char* name = NULL); + STVariableLength(SField::ref n, const std::vector& v) : SerializedType(n), value(v) { ; } + STVariableLength(SField::ref n) : SerializedType(n) { ; } + STVariableLength(SerializerIterator&, SField::ref name = sfGeneric); STVariableLength() { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const; virtual SerializedTypeID getSType() const { return STI_VL; } virtual std::string getText() const; void add(Serializer& s) const { s.addVL(value); } @@ -511,16 +488,16 @@ public: class STAccount : public STVariableLength { protected: - virtual STAccount* duplicate() const { return new STAccount(name, value); } - static STAccount* construct(SerializerIterator&, const char* name = NULL); + virtual STAccount* duplicate() const { return new STAccount(*this); } + static STAccount* construct(SerializerIterator&, SField::ref); public: STAccount(const std::vector& v) : STVariableLength(v) { ; } - STAccount(const char* n, const std::vector& v) : STVariableLength(n, v) { ; } - STAccount(const char* n) : STVariableLength(n) { ; } + STAccount(SField::ref n, const std::vector& v) : STVariableLength(n, v) { ; } + STAccount(SField::ref n) : STVariableLength(n) { ; } STAccount() { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } SerializedTypeID getSType() const { return STI_ACCOUNT; } @@ -649,19 +626,18 @@ class STPathSet : public SerializedType protected: std::vector value; - STPathSet* duplicate() const { return new STPathSet(name, value); } - static STPathSet* construct(SerializerIterator&, const char* name = NULL); + STPathSet* duplicate() const { return new STPathSet(*this); } + static STPathSet* construct(SerializerIterator&, SField::ref); public: STPathSet() { ; } - STPathSet(const char* n) : SerializedType(n) { ; } + STPathSet(SField::ref n) : SerializedType(n) { ; } STPathSet(const std::vector& v) : value(v) { ; } - STPathSet(const char* n, const std::vector& v) : SerializedType(n), value(v) { ; } - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + STPathSet(SField::ref n, const std::vector& v) : SerializedType(n), value(v) { ; } + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } - int getLength() const; // std::string getText() const; void add(Serializer& s) const; virtual Json::Value getJson(int) const; @@ -722,20 +698,19 @@ class STVector256 : public SerializedType protected: std::vector mValue; - STVector256* duplicate() const { return new STVector256(name, mValue); } - static STVector256* construct(SerializerIterator&, const char* name = NULL); + STVector256* duplicate() const { return new STVector256(*this); } + static STVector256* construct(SerializerIterator&, SField::ref); public: STVector256() { ; } - STVector256(const char* n) : SerializedType(n) { ; } - STVector256(const char* n, const std::vector& v) : SerializedType(n), mValue(v) { ; } + STVector256(SField::ref n) : SerializedType(n) { ; } + STVector256(SField::ref n, const std::vector& v) : SerializedType(n), mValue(v) { ; } STVector256(const std::vector& vector) : mValue(vector) { ; } SerializedTypeID getSType() const { return STI_VECTOR256; } - int getLength() const { return Serializer::lengthVL(mValue.size() * (256 / 8)); } void add(Serializer& s) const; - static std::auto_ptr deserialize(SerializerIterator& sit, const char* name) + static std::auto_ptr deserialize(SerializerIterator& sit, SField::ref name) { return std::auto_ptr(construct(sit, name)); } const std::vector& peekValue() const { return mValue; } diff --git a/src/SerializedValidation.cpp b/src/SerializedValidation.cpp index 9ae32c31bb..edd4fe721b 100644 --- a/src/SerializedValidation.cpp +++ b/src/SerializedValidation.cpp @@ -4,29 +4,33 @@ #include "HashPrefixes.h" SOElement SerializedValidation::sValidationFormat[] = { - { sfFlags, "Flags", STI_UINT32, SOE_FLAGS, 0 }, - { sfLedgerHash, "LedgerHash", STI_HASH256, SOE_REQUIRED, 0 }, - { sfSigningTime, "SignTime", STI_UINT32, SOE_REQUIRED, 0 }, - { sfSigningKey, "SigningKey", STI_VL, SOE_REQUIRED, 0 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 }, + { sfFlags, SOE_REQUIRED }, + { sfLedgerHash, SOE_REQUIRED }, + { sfLedgerSequence, SOE_OPTIONAL }, + { sfCloseTime, SOE_OPTIONAL }, + { sfLoadFee, SOE_OPTIONAL }, + { sfBaseFee, SOE_OPTIONAL }, + { sfSigningTime, SOE_REQUIRED }, + { sfSigningPubKey, SOE_REQUIRED }, + { sfInvalid, SOE_END } }; const uint32 SerializedValidation::sFullFlag = 0x00010000; SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature) - : STObject(sValidationFormat, sit), mSignature(sit, "Signature"), mTrusted(false) + : STObject(sValidationFormat, sit, sfValidation), mSignature(sit, sfSignature), mTrusted(false) { if (checkSignature && !isValid()) throw std::runtime_error("Invalid validation"); } SerializedValidation::SerializedValidation(const uint256& ledgerHash, uint32 signTime, const NewcoinAddress& naSeed, bool isFull) - : STObject(sValidationFormat), mSignature("Signature"), mTrusted(false) + : STObject(sValidationFormat, sfValidation), mSignature(sfSignature), mTrusted(false) { setValueFieldH256(sfLedgerHash, ledgerHash); setValueFieldU32(sfSigningTime, signTime); if (naSeed.isValid()) - setValueFieldVL(sfSigningKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); + setValueFieldVL(sfSigningPubKey, NewcoinAddress::createNodePublic(naSeed).getNodePublic()); if (!isFull) setFlag(sFullFlag); NewcoinAddress::createNodePrivate(naSeed).signNodePrivate(getSigningHash(), mSignature.peekValue()); @@ -69,7 +73,7 @@ bool SerializedValidation::isValid(const uint256& signingHash) const { try { - NewcoinAddress naPublicKey = NewcoinAddress::createNodePublic(getValueFieldVL(sfSigningKey)); + NewcoinAddress naPublicKey = NewcoinAddress::createNodePublic(getValueFieldVL(sfSigningPubKey)); return naPublicKey.isValid() && naPublicKey.verifyNodePublic(signingHash, mSignature.peekValue()); } catch (...) @@ -81,7 +85,7 @@ bool SerializedValidation::isValid(const uint256& signingHash) const NewcoinAddress SerializedValidation::getSignerPublic() const { NewcoinAddress a; - a.setNodePublic(getValueFieldVL(sfSigningKey)); + a.setNodePublic(getValueFieldVL(sfSigningPubKey)); return a; } diff --git a/src/Serializer.h b/src/Serializer.h index e1c251508c..8666efe4c3 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -9,6 +9,7 @@ #include "key.h" #include "uint256.h" +#include "FieldNames.h" typedef std::pair > TaggedListItem; @@ -69,6 +70,7 @@ public: bool getFieldID(int& type, int& name, int offset) const; int addFieldID(int type, int name); + int addFieldID(SerializedTypeID type, int name) { return addFieldID(static_cast(type), name); } // normal hash functions uint160 getRIPEMD160(int size=-1) const; @@ -92,7 +94,7 @@ public: int getDataLength() const { return mData.size(); } const void* getDataPtr() const { return &mData.front(); } void* getDataPtr() { return &mData.front(); } - int getLength() { return mData.size(); } + int getLength() const { return mData.size(); } const std::vector& peekData() const { return mData; } std::vector getData() const { return mData; } std::string getString() const { return std::string(static_cast(getDataPtr()), size()); } @@ -143,11 +145,12 @@ protected: public: SerializerIterator(const Serializer& s) : mSerializer(s), mPos(0) { ; } - void reset(void) { mPos=0; } + void reset(void) { mPos = 0; } void setPos(int p) { mPos = p; } const Serializer& operator*(void) { return mSerializer; } int getPos(void) { return mPos; } + bool empty() { return mPos == mSerializer.getLength(); } int getBytesLeft(); // get functions throw on error diff --git a/src/Transaction.cpp b/src/Transaction.cpp index c6488cb8a0..ec209bdf16 100644 --- a/src/Transaction.cpp +++ b/src/Transaction.cpp @@ -18,7 +18,7 @@ Transaction::Transaction(const SerializedTransaction::pointer& sit, bool bValida { try { - mFromPubKey.setAccountPublic(mTransaction->peekSigningPubKey()); + mFromPubKey.setAccountPublic(mTransaction->getSigningPubKey()); mTransactionID = mTransaction->getTransactionID(); mAccountFrom = mTransaction->getSourceAccount(); } @@ -92,12 +92,7 @@ bool Transaction::sign(const NewcoinAddress& naAccountPrivate) Log(lsWARNING) << "No private key for signing"; bResult = false; } - else if (!getSTransaction()->sign(naAccountPrivate)) - { - Log(lsWARNING) << "Failed to make signature"; - assert(false); - bResult = false; - } + getSTransaction()->sign(naAccountPrivate); if (bResult) { diff --git a/src/TransactionEngine.cpp b/src/TransactionEngine.cpp index 3dc45c7c15..8847ca87e1 100644 --- a/src/TransactionEngine.cpp +++ b/src/TransactionEngine.cpp @@ -105,7 +105,7 @@ TER TransactionEngine::applyTransaction(const SerializedTransaction& txn, Transa NewcoinAddress naSigningPubKey; if (tesSUCCESS == terResult) - naSigningPubKey = NewcoinAddress::createAccountPublic(txn.peekSigningPubKey()); + naSigningPubKey = NewcoinAddress::createAccountPublic(txn.getSigningPubKey()); // Consistency: really signed. if ((tesSUCCESS == terResult) && !isSetBit(params, tapNO_CHECK_SIGN) && !txn.checkSign(naSigningPubKey)) diff --git a/src/TransactionErr.h b/src/TransactionErr.h index 7ce5cd6109..576f3dbf80 100644 --- a/src/TransactionErr.h +++ b/src/TransactionErr.h @@ -111,6 +111,8 @@ enum TER // aka TransactionEngineResult #define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE) #define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY) #define isTepPartial(x) ((x) >= tepPATH_PARTIAL) +#define isTepSuccess(x) ((x) >= tesSUCCESS) +#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS) bool transResultInfo(TER terCode, std::string& strToken, std::string& strHuman); std::string transToken(TER terCode); diff --git a/src/TransactionFormats.cpp b/src/TransactionFormats.cpp index a66f36d41b..cebc37a49c 100644 --- a/src/TransactionFormats.cpp +++ b/src/TransactionFormats.cpp @@ -1,133 +1,119 @@ - #include "TransactionFormats.h" -#define S_FIELD(x) sf##x, #x +#define TF_BASE \ + { sfTransactionType, SOE_REQUIRED }, \ + { sfFlags, SOE_REQUIRED }, \ + { sfSourceTag, SOE_OPTIONAL }, \ + { sfAccount, SOE_REQUIRED }, \ + { sfSequence, SOE_REQUIRED }, \ + { sfFee, SOE_REQUIRED }, \ + { sfSigningPubKey, SOE_REQUIRED }, \ + { sfTxnSignature, SOE_OPTIONAL }, -TransactionFormat InnerTxnFormats[]= +TransactionFormat InnerTxnFormats[]= { - { "AccountSet", ttACCOUNT_SET, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(SourceTag), STI_UINT32, 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(Domain), STI_VL, SOE_IFFLAG, 16 }, - { S_FIELD(TransferRate), STI_UINT32, SOE_IFFLAG, 32 }, - { S_FIELD(PublishHash), STI_HASH256, SOE_IFFLAG, 64 }, - { S_FIELD(PublishSize), STI_UINT32, SOE_IFFLAG, 128 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "Claim", ttCLAIM, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(PublicKey), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(Signature), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "CreditSet", ttCREDIT_SET, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(LimitAmount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(QualityIn), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(QualityOut), STI_UINT32, SOE_IFFLAG, 2 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 4 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, + { "AccountSet", ttACCOUNT_SET, { TF_BASE + { sfEmailHash, SOE_OPTIONAL }, + { sfWalletLocator, SOE_OPTIONAL }, + { sfMessageKey, SOE_OPTIONAL }, + { sfDomain, SOE_OPTIONAL }, + { sfTransferRate, SOE_OPTIONAL }, + { sfPublishHash, SOE_OPTIONAL }, + { sfPublishSize, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, + { "Claim", ttCLAIM, { TF_BASE + { sfGenerator, SOE_REQUIRED }, + { sfPublicKey, SOE_REQUIRED }, + { sfSignature, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, + { "CreditSet", ttCREDIT_SET, { TF_BASE + { sfLimitAmount, SOE_OPTIONAL }, + { sfQualityIn, SOE_OPTIONAL }, + { sfQualityOut, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, /* - { "Invoice", ttINVOICE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Target), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 2 }, - { S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 4 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, + { "Invoice", ttINVOICE, { TF_BASE + { sfTarget, SOE_REQUIRED }, + { sfAmount, SOE_REQUIRED }, + { sfDestination, SOE_OPTIONAL }, + { sfIdentifier, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, */ - { "NicknameSet", ttNICKNAME_SET, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 }, - { S_FIELD(MinimumOffer), STI_AMOUNT, SOE_IFFLAG, 1 }, - { S_FIELD(Signature), STI_VL, SOE_IFFLAG, 2 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 4 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "OfferCreate", ttOFFER_CREATE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(TakerPays), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(TakerGets), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { S_FIELD(Expiration), STI_UINT32, SOE_IFFLAG, 2 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "OfferCancel", ttOFFER_CANCEL, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(OfferSequence), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "PasswordFund", ttPASSWORD_FUND, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "PasswordSet", ttPASSWORD_SET, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(AuthorizedKey), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(PublicKey), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(Signature), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "Payment", ttPAYMENT, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Destination), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(SendMax), STI_AMOUNT, SOE_IFFLAG, 1 }, - { S_FIELD(Paths), STI_PATHSET, SOE_IFFLAG, 2 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 4 }, - { S_FIELD(InvoiceID), STI_HASH256, SOE_IFFLAG, 8 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "WalletAdd", ttWALLET_ADD, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Amount), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(AuthorizedKey), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(PublicKey), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(Signature), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 1 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "Contract", ttCONTRACT, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Expiration), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(BondAmount), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(StampEscrow), STI_UINT32, SOE_REQUIRED, 0 }, - { S_FIELD(RippleEscrow), STI_AMOUNT, SOE_REQUIRED, 0 }, - { S_FIELD(CreateCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(FundCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(RemoveCode), STI_VL, SOE_REQUIRED, 0 }, - { S_FIELD(ExpireCode), STI_VL, SOE_REQUIRED, 0 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, - { "Contract", ttCONTRACT_REMOVE, { - { S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 }, - { S_FIELD(Target), STI_ACCOUNT, SOE_REQUIRED, 0 }, - { sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } } - }, + { "NicknameSet", ttNICKNAME_SET, { TF_BASE + { sfNickname, SOE_REQUIRED }, + { sfMinimumOffer, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, + { "OfferCreate", ttOFFER_CREATE, { TF_BASE + { sfTakerPays, SOE_REQUIRED }, + { sfTakerGets, SOE_REQUIRED }, + { sfExpiration, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, + { "OfferCancel", ttOFFER_CANCEL, { TF_BASE + { sfOfferSequence, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, + { "PasswordFund", ttPASSWORD_FUND, { TF_BASE + { sfDestination, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, + { "PasswordSet", ttPASSWORD_SET, { TF_BASE + { sfAuthorizedKey, SOE_REQUIRED }, + { sfGenerator, SOE_REQUIRED }, + { sfPublicKey, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, + { "Payment", ttPAYMENT, { TF_BASE + { sfDestination, SOE_REQUIRED }, + { sfAmount, SOE_REQUIRED }, + { sfSendMax, SOE_OPTIONAL }, + { sfPaths, SOE_OPTIONAL }, + { sfInvoiceID, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, + { "WalletAdd", ttWALLET_ADD, { TF_BASE + { sfAmount, SOE_REQUIRED }, + { sfAuthorizedKey, SOE_REQUIRED }, + { sfPublicKey, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, + { "Contract", ttCONTRACT, { TF_BASE + { sfExpiration, SOE_REQUIRED }, + { sfBondAmount, SOE_REQUIRED }, + { sfStampEscrow, SOE_REQUIRED }, + { sfRippleEscrow, SOE_REQUIRED }, + { sfCreateCode, SOE_OPTIONAL }, + { sfFundCode, SOE_OPTIONAL }, + { sfRemoveCode, SOE_OPTIONAL }, + { sfExpireCode, SOE_OPTIONAL }, + { sfInvalid, SOE_END } } + }, + { "RemoveContract", ttCONTRACT_REMOVE, { TF_BASE + { sfTarget, SOE_REQUIRED }, + { sfInvalid, SOE_END } } + }, { NULL, ttINVALID } }; -TransactionFormat* getTxnFormat(TransactionType t) +TransactionFormat* getTxnFormat(TransactionType t) +{ + return getTxnFormat(static_cast(t)); +} + +TransactionFormat* getTxnFormat(int t) { TransactionFormat* f = InnerTxnFormats; while (f->t_name != NULL) { - if (f->t_type == t) return f; + if (f->t_type == t) + return f; ++f; - } + } return NULL; } -// vim:ts=4 +// vim:ts=4 diff --git a/src/TransactionFormats.h b/src/TransactionFormats.h index 72ff3f6e3f..57b155285f 100644 --- a/src/TransactionFormats.h +++ b/src/TransactionFormats.h @@ -23,17 +23,11 @@ enum TransactionType struct TransactionFormat { - const char *t_name; - TransactionType t_type; - SOElement elements[16]; + const char * t_name; + TransactionType t_type; + SOElement elements[24]; }; -const int TransactionISigningPubKey = 0; -const int TransactionISourceID = 1; -const int TransactionISequence = 2; -const int TransactionIType = 3; -const int TransactionIFee = 4; - const int TransactionMinLen = 32; const int TransactionMaxLen = 1048576; @@ -52,5 +46,6 @@ const uint32 tfNoRippleDirect = 0x00080000; extern TransactionFormat InnerTxnFormats[]; extern TransactionFormat* getTxnFormat(TransactionType t); +extern TransactionFormat* getTxnFormat(int t); #endif // vim:ts=4 diff --git a/src/TransactionMeta.cpp b/src/TransactionMeta.cpp index 4c179f0b70..3f687897c1 100644 --- a/src/TransactionMeta.cpp +++ b/src/TransactionMeta.cpp @@ -66,7 +66,7 @@ Json::Value TMNEThread::getJson(int) const TMNEAmount::TMNEAmount(int type, SerializerIterator& sit) : TransactionMetaNodeEntry(type) { - mAmount = *dynamic_cast(STAmount::deserialize(sit, NULL).get()); // Ouch + mAmount = *dynamic_cast(STAmount::deserialize(sit, sfAmount).get()); // Ouch } void TMNEAmount::addRaw(Serializer& s) const diff --git a/src/Version.h b/src/Version.h index f35da8166c..9d7a56be2e 100644 --- a/src/Version.h +++ b/src/Version.h @@ -5,7 +5,7 @@ // #define SERVER_VERSION_MAJOR 0 -#define SERVER_VERSION_MINOR 5 +#define SERVER_VERSION_MINOR 6 #define SERVER_VERSION_SUB "-a" #define SERVER_NAME "NewCoin" @@ -15,12 +15,12 @@ (SERVER_NAME "-" SV_STRINGIZE(SERVER_VERSION_MAJOR) "." SV_STRINGIZE(SERVER_VERSION_MINOR) SERVER_VERSION_SUB) // Version we prefer to speak: -#define PROTO_VERSION_MAJOR 0 -#define PROTO_VERSION_MINOR 8 +#define PROTO_VERSION_MAJOR 1 +#define PROTO_VERSION_MINOR 1 // Version we will speak to: -#define MIN_PROTO_MAJOR 0 -#define MIN_PROTO_MINOR 8 +#define MIN_PROTO_MAJOR 1 +#define MIN_PROTO_MINOR 1 #define MAKE_VERSION_INT(maj,min) ((maj << 16) | min) #define GET_VERSION_MAJOR(ver) (ver >> 16)