diff --git a/src/Amount.cpp b/src/Amount.cpp index b78dbd491e..9c5d0df513 100644 --- a/src/Amount.cpp +++ b/src/Amount.cpp @@ -106,7 +106,7 @@ STAmount::STAmount(SField::ref n, const Json::Value& v) else if (value.isUInt()) mValue = v.asUInt(); else if (value.isString()) - { // FIXME: If it has a '.' we have to process it specially! + { if (mIsNative) { int64 val = lexical_cast_st(value.asString()); @@ -127,8 +127,23 @@ STAmount::STAmount(SField::ref n, const Json::Value& v) if (mIsNative) return; - // parse currency and issuer - // WRITEME + if (!currencyFromString(mCurrency, currency.asString())) + throw std::runtime_error("invalid currency"); + + if (!issuer.isString()) + throw std::runtime_error("invalid issuer"); + + if (issuer.size() == (160/4)) + mIssuer.SetHex(issuer.asString()); + else + { + NewcoinAddress is; + if(!is.setAccountID(issuer.asString())) + throw std::runtime_error("invalid issuer"); + mIssuer = is.getAccountID(); + } + if (mIssuer.isZero()) + throw std::runtime_error("invalid issuer"); canonicalize(); } diff --git a/src/Pathfinder.cpp b/src/Pathfinder.cpp index a83771a57f..4f0276a451 100644 --- a/src/Pathfinder.cpp +++ b/src/Pathfinder.cpp @@ -154,7 +154,7 @@ void Pathfinder::addOptions(PathOption::pointer tail) { // we have a ripple line from the tail to somewhere else PathOption::pointer pathOption(new PathOption(tail)); - STPathElement ele(line->getAccountIDPeer().getAccountID(), uint160(),uint160()); + STPathElement ele(line->getAccountIDPeer().getAccountID(), uint160(), uint160()); pathOption->mPath.addElement(ele); diff --git a/src/SerializedObject.cpp b/src/SerializedObject.cpp index 74137bcc37..3f2fcdaa8f 100644 --- a/src/SerializedObject.cpp +++ b/src/SerializedObject.cpp @@ -946,10 +946,77 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r break; case STI_VECTOR256: - // WRITEME + if (!value.isArray()) + throw std::runtime_error("Incorrect type"); + { + data.push_back(new STVector256(field)); + STVector256* tail = dynamic_cast(&data.back()); + assert(tail); + for (Json::UInt i = 0; !object.isValidIndex(i); ++i) + { + uint256 s; + s.SetHex(object[i].asString()); + tail->addValue(s); + } + } + break; case STI_PATHSET: - // WRITEME + if (!value.isArray()) + throw std::runtime_error("Path set must be array"); + { + data.push_back(new STPathSet(field)); + STPathSet* tail = dynamic_cast(&data.back()); + assert(tail); + for (Json::UInt i = 0; !object.isValidIndex(i); ++i) + { + STPath p; + if (!object[i].isArray()) + throw std::runtime_error("Path must be array"); + for (Json::UInt j = 0; !object[i].isValidIndex(j); ++j) + { // each element in this path has some combination of account, currency, or issuer + + Json::Value pathEl = object[i][j]; + if (!pathEl.isObject()) + throw std::runtime_error("Path elements must be objects"); + const Json::Value& account = pathEl["account"]; + const Json::Value& currency = pathEl["currency"]; + const Json::Value& issuer = pathEl["issuer"]; + + uint160 uAccount, uCurrency, uIssuer; + bool hasCurrency; + if (!account.isNull()) + { // human account id + if (!account.isString()) + throw std::runtime_error("path element accounts must be strings"); + std::string strValue = account.asString(); + if (value.size() == 40) // 160-bit hex account value + uAccount.SetHex(strvalue); + { + NewcoinAddress a; + if (!a.setAccountPublic(strValue)) + throw std::runtime_error("Account in path element invalid"); + uAccount = a.getAccountID(); + } + } + if (!currency.isNull()) + { // human currency + if (!currency.isString()) + throw std::runtime_error("path element currencies must be strings"); + hasCurrency = true; + // WRITEME + } + if (!issuer.isNull()) + { // human account id + if (!issuer.isString()) + throw std::runtime_error("path element issuers must be strings"); + // WRITEME + } + p.addElement(STPathElement(uAccount, uCurrency, uIssuer, hasCurrency)); + } + tail->addPath(p); + } + } break; case STI_ACCOUNT: @@ -985,7 +1052,15 @@ std::auto_ptr STObject::parseJson(const Json::Value& object, SField::r break; case STI_ARRAY: - // WRITEME + if (!value.isArray()) + throw std::runtime_error("Inner value is not an array"); + { + data.push_back(new STArray(field)); + STArray* tail = dynamic_cast(&data.back()); + assert(tail); + for (Json::UInt i = 0; !object.isValidIndex(i); ++i) + tail->push_back(*STObject::parseJson(object[i], sfGeneric, depth + 1)); + } default: throw std::runtime_error("Invalid field type"); diff --git a/src/SerializedObject.h b/src/SerializedObject.h index 6de71dcbf5..ed8d06560e 100644 --- a/src/SerializedObject.h +++ b/src/SerializedObject.h @@ -65,11 +65,15 @@ public: std::string getText() const; virtual Json::Value getJson(int options) const; - int addObject(const SerializedType& t) { mData.push_back(t.clone()); return mData.size() - 1; } - int giveObject(std::auto_ptr t) { mData.push_back(t); return mData.size() - 1; } - int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; } + int addObject(const SerializedType& t) { mData.push_back(t.clone()); return mData.size() - 1; } + int giveObject(std::auto_ptr t) { mData.push_back(t); return mData.size() - 1; } + int giveObject(SerializedType* t) { mData.push_back(t); return mData.size() - 1; } const boost::ptr_vector& peekData() const { return mData; } - boost::ptr_vector& peekData() { return mData; } + boost::ptr_vector& peekData() { return mData; } + SerializedType& front() { return mData.front(); } + const SerializedType& front() const { return mData.front(); } + SerializedType& back() { return mData.back(); } + const SerializedType& back() const { return mData.back(); } int getCount() const { return mData.size(); } @@ -189,6 +193,10 @@ public: reverse_iterator rend() { return value.rend(); } const_reverse_iterator rend() const { return value.rend(); } iterator erase(iterator pos) { return value.erase(pos); } + STObject& front() { return value.front(); } + const STObject& front() const { return value.front(); } + STObject& back() { return value.back(); } + const STObject& back() const { return value.back(); } void pop_back() { value.pop_back(); } bool empty() const { return value.empty(); } void clear() { value.clear(); } diff --git a/src/SerializedTypes.cpp b/src/SerializedTypes.cpp index 097395b5ca..92316d8b96 100644 --- a/src/SerializedTypes.cpp +++ b/src/SerializedTypes.cpp @@ -365,8 +365,8 @@ Json::Value STPath::getJson(int) const Json::Value elem(Json::objectValue); int iType = it.getNodeType(); - elem["type"] = it.getNodeType(); - elem["type_hex"] = strHex(it.getNodeType()); + elem["type"] = iType; + elem["type_hex"] = strHex(iType); if (iType & STPathElement::typeAccount) elem["account"] = NewcoinAddress::createHumanAccountID(it.getAccountID()); diff --git a/src/SerializedTypes.h b/src/SerializedTypes.h index a91e2fe97c..0c1cd3bac2 100644 --- a/src/SerializedTypes.h +++ b/src/SerializedTypes.h @@ -539,12 +539,13 @@ protected: uint160 mIssuerID; public: - STPathElement(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID) - : mAccountID(uAccountID), mCurrencyID(uCurrencyID), mIssuerID(uIssuerID) + STPathElement(const uint160& uAccountID, const uint160& uCurrencyID, const uint160& uIssuerID, + bool forceCurrency = false) + : mAccountID(uAccountID), mCurrencyID(uCurrencyID), mIssuerID(uIssuerID) { mType = (uAccountID.isZero() ? 0 : STPathElement::typeAccount) - | (uCurrencyID.isZero() ? 0 : STPathElement::typeCurrency) + | ((uCurrencyID.isZero() && !forceCurrency) ? 0 : STPathElement::typeCurrency) | (uIssuerID.isZero() ? 0 : STPathElement::typeIssuer); } @@ -722,12 +723,11 @@ public: std::vector& peekValue() { return mValue; } virtual bool isEquivalent(const SerializedType& t) const; - std::vector getValue() const { return mValue; } - - bool isEmpty() const { return mValue.empty(); } - - void setValue(const STVector256& v) { mValue = v.mValue; } - void setValue(const std::vector& v) { mValue = v; } + std::vector getValue() const { return mValue; } + bool isEmpty() const { return mValue.empty(); } + void setValue(const STVector256& v) { mValue = v.mValue; } + void setValue(const std::vector& v) { mValue = v; } + void addValue(const uint256& v) { mValue.push_back(v); } Json::Value getJson(int) const; };