Reorganize source file hierarchy:

* Rename unity files
* Move some modules to new subdirectories
* Remove obsolete Visual Studio project files
* Remove obsolete coding style and TODO list
This commit is contained in:
Vinnie Falco
2014-06-03 14:48:34 -07:00
parent 39a387b54c
commit 4f1d1d2a8a
774 changed files with 6924 additions and 10355 deletions

View File

@@ -0,0 +1,236 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/unit_test/suite.h>
#include <beast/module/core/diagnostic/FatalError.h>
#include <beast/module/core/diagnostic/SemanticVersion.h>
namespace ripple {
char const* BuildInfo::getRawVersionString ()
{
static char const* const rawText =
//--------------------------------------------------------------------------
//
// The build version number (edit this for each release)
//
"0.25.1"
//
// Must follow the format described here:
//
// http://semver.org/
//
//--------------------------------------------------------------------------
;
return rawText;
}
BuildInfo::Protocol const& BuildInfo::getCurrentProtocol ()
{
static Protocol currentProtocol (
//--------------------------------------------------------------------------
//
// The protocol version we speak and prefer (edit this if necessary)
//
1, // major
2 // minor
//
//--------------------------------------------------------------------------
);
return currentProtocol;
}
BuildInfo::Protocol const& BuildInfo::getMinimumProtocol ()
{
static Protocol minimumProtocol (
//--------------------------------------------------------------------------
//
// The oldest protocol version we will accept. (edit this if necessary)
//
1, // major
2 // minor
//
//--------------------------------------------------------------------------
);
return minimumProtocol;
}
//
//
// Don't touch anything below this line
//
//------------------------------------------------------------------------------
beast::String const& BuildInfo::getVersionString ()
{
struct SanityChecker
{
SanityChecker ()
{
beast::SemanticVersion v;
char const* const rawText = getRawVersionString ();
if (! v.parse (rawText) || v.print () != rawText)
beast::FatalError ("Bad server version string", __FILE__, __LINE__);
versionString = rawText;
}
beast::String versionString;
};
static SanityChecker value;
return value.versionString;
}
char const* BuildInfo::getFullVersionString ()
{
struct PrettyPrinter
{
PrettyPrinter ()
{
beast::String s;
s << "Ripple-" << getVersionString ();
fullVersionString = s.toStdString ();
}
std::string fullVersionString;
};
static PrettyPrinter value;
return value.fullVersionString.c_str ();
}
//------------------------------------------------------------------------------
BuildInfo::Protocol::Protocol ()
: vmajor (0)
, vminor (0)
{
}
BuildInfo::Protocol::Protocol (unsigned short major_, unsigned short minor_)
: vmajor (major_)
, vminor (minor_)
{
}
BuildInfo::Protocol::Protocol (PackedFormat packedVersion)
{
vmajor = (packedVersion >> 16) & 0xffff;
vminor = (packedVersion & 0xffff);
}
BuildInfo::Protocol::PackedFormat BuildInfo::Protocol::toPacked () const noexcept
{
return ((vmajor << 16) & 0xffff0000) | (vminor & 0xffff);
}
std::string BuildInfo::Protocol::toStdString () const noexcept
{
beast::String s;
s << beast::String (vmajor) << "." << beast::String (vminor);
return s.toStdString ();
}
//------------------------------------------------------------------------------
class BuildInfo_test : public beast::unit_test::suite
{
public:
void testVersion ()
{
testcase ("version");
beast::SemanticVersion v;
expect (v.parse (BuildInfo::getRawVersionString ()));
}
void checkProtcol (unsigned short vmajor, unsigned short vminor)
{
typedef BuildInfo::Protocol P;
expect (P (P (vmajor, vminor).toPacked ()) == P (vmajor, vminor));
}
void testProtocol ()
{
typedef BuildInfo::Protocol P;
testcase ("protocol");
expect (P (0, 0).toPacked () == 0);
expect (P (0, 1).toPacked () == 1);
expect (P (0, 65535).toPacked () == 65535);
checkProtcol (0, 0);
checkProtcol (0, 1);
checkProtcol (0, 255);
checkProtcol (0, 65535);
checkProtcol (1, 0);
checkProtcol (1, 65535);
checkProtcol (65535, 65535);
}
void testValues ()
{
testcase ("comparison");
typedef BuildInfo::Protocol P;
expect (P(1,2) == P(1,2));
expect (P(3,4) >= P(3,4));
expect (P(5,6) <= P(5,6));
expect (P(7,8) > P(6,7));
expect (P(7,8) < P(8,9));
expect (P(65535,0) < P(65535,65535));
expect (P(65535,65535) >= P(65535,65535));
expect (BuildInfo::getCurrentProtocol () >= BuildInfo::getMinimumProtocol ());
}
void run ()
{
testVersion ();
testProtocol ();
testValues ();
log <<
" Ripple version: " <<
BuildInfo::getVersionString().toStdString();
}
};
BEAST_DEFINE_TESTSUITE(BuildInfo,ripple_data,ripple);
} // ripple

View File

@@ -0,0 +1,87 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_BUILDINFO_H_INCLUDED
#define RIPPLE_BUILDINFO_H_INCLUDED
namespace ripple {
/** Versioning information for this build. */
struct BuildInfo
{
/** Server version.
Follows the Semantic Versioning Specification:
http://semver.org/
*/
static beast::String const& getVersionString ();
/** Full server version string.
This includes the name of the server. It is used in the peer
protocol hello message and also the headers of some HTTP replies.
*/
static char const* getFullVersionString ();
//--------------------------------------------------------------------------
/** The wire protocol version.
The version consists of two unsigned 16 bit integers representing
major and minor version numbers. All values are permissible.
*/
struct Protocol
{
unsigned short vmajor;
unsigned short vminor;
//----
/** The serialized format of the protocol version. */
typedef std::uint32_t PackedFormat;
Protocol ();
Protocol (unsigned short vmajor, unsigned short vminor);
explicit Protocol (PackedFormat packedVersion);
PackedFormat toPacked () const noexcept;
std::string toStdString () const noexcept;
bool operator== (Protocol const& other) const noexcept { return toPacked () == other.toPacked (); }
bool operator!= (Protocol const& other) const noexcept { return toPacked () != other.toPacked (); }
bool operator>= (Protocol const& other) const noexcept { return toPacked () >= other.toPacked (); }
bool operator<= (Protocol const& other) const noexcept { return toPacked () <= other.toPacked (); }
bool operator> (Protocol const& other) const noexcept { return toPacked () > other.toPacked (); }
bool operator< (Protocol const& other) const noexcept { return toPacked () < other.toPacked (); }
};
/** The protocol version we speak and prefer. */
static Protocol const& getCurrentProtocol ();
/** The oldest protocol version we will accept. */
static Protocol const& getMinimumProtocol ();
static char const* getRawVersionString ();
};
} // ripple
#endif

View File

@@ -0,0 +1,163 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
// These must stay at the top of this file
std::map<int, SField::ptr> SField::codeToField;
int SField::num = 0;
// Solve construction issues for objects with static storage duration.
SField::StaticLockType& SField::getMutex ()
{
static StaticLockType mutex;
return mutex;
}
SField sfInvalid (-1), sfGeneric (0);
SField sfLedgerEntry (STI_LEDGERENTRY, 1, "LedgerEntry");
SField sfTransaction (STI_TRANSACTION, 1, "Transaction");
SField sfValidation (STI_VALIDATION, 1, "Validation");
SField sfHash (STI_HASH256, 257, "hash");
SField sfIndex (STI_HASH256, 258, "index");
#define FIELD(name, type, index) SField sf##name(FIELD_CODE(STI_##type, index), STI_##type, index, #name);
#define TYPE(name, type, index)
#include <ripple/module/data/protocol/SerializeDeclarations.h>
#undef FIELD
#undef TYPE
static int initFields ()
{
sfTxnSignature.notSigningField ();
sfTxnSignatures.notSigningField ();
sfSignature.notSigningField ();
sfIndexes.setMeta (SField::sMD_Never);
sfPreviousTxnID.setMeta (SField::sMD_DeleteFinal);
sfPreviousTxnLgrSeq.setMeta (SField::sMD_DeleteFinal);
sfLedgerEntryType.setMeta (SField::sMD_Never);
sfRootIndex.setMeta (SField::sMD_Always);
return 0;
}
static const int f = initFields ();
SField::SField (SerializedTypeID tid, int fv) : fieldCode (FIELD_CODE (tid, fv)), fieldType (tid), fieldValue (fv),
fieldMeta (sMD_Default), fieldNum (++num), signingField (true), jsonName (nullptr)
{
// call with the map mutex
fieldName = beast::lexicalCast <std::string> (tid) + "/" +
beast::lexicalCast <std::string> (fv);
codeToField[fieldCode] = this;
rawJsonName = getName ();
jsonName = Json::StaticString (rawJsonName.c_str ());
assert ((fv != 1) || ((tid != STI_ARRAY) && (tid != STI_OBJECT)));
}
SField::ref SField::getField (int code)
{
int type = code >> 16;
int field = code % 0xffff;
if ((type <= 0) || (field <= 0))
return sfInvalid;
StaticScopedLockType sl (getMutex ());
std::map<int, SField::ptr>::iterator it = codeToField.find (code);
if (it != codeToField.end ())
return * (it->second);
if (field > 255) // don't dynamically extend types that have no binary encoding
return sfInvalid;
switch (type)
{
// types we are willing to dynamically extend
#define FIELD(name, type, index)
#define TYPE(name, type, index) case STI_##type:
#include <ripple/module/data/protocol/SerializeDeclarations.h>
#undef FIELD
#undef TYPE
break;
default:
return sfInvalid;
}
return * (new SField (static_cast<SerializedTypeID> (type), field));
}
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;
}
std::string SField::getName () const
{
if (!fieldName.empty ())
return fieldName;
if (fieldValue == 0)
return "";
return beast::lexicalCastThrow <std::string> (static_cast<int> (fieldType)) + "/" +
beast::lexicalCastThrow <std::string> (fieldValue);
}
SField::ref SField::getField (const std::string& fieldName)
{
// OPTIMIZEME me with a map. CHECKME this is case sensitive
StaticScopedLockType sl (getMutex ());
typedef std::map<int, SField::ptr>::value_type int_sfref_pair;
BOOST_FOREACH (const int_sfref_pair & fieldPair, codeToField)
{
if (fieldPair.second->fieldName == fieldName)
return * (fieldPair.second);
}
return sfInvalid;
}
SField::~SField ()
{
StaticScopedLockType sl (getMutex ());
std::map<int, ptr>::iterator it = codeToField.find (fieldCode);
if ((it != codeToField.end ()) && (it->second == this))
codeToField.erase (it);
}
} // ripple

View File

@@ -0,0 +1,252 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_FIELDNAMES_H
#define RIPPLE_FIELDNAMES_H
namespace ripple {
// VFALCO TODO lose the macro.
#define FIELD_CODE(type, index) ((static_cast<int>(type) << 16) | index)
enum SerializedTypeID
{
// 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 <ripple/module/data/protocol/SerializeDeclarations.h>
#undef TYPE
#undef FIELD
// high level types
STI_TRANSACTION = 10001,
STI_LEDGERENTRY = 10002,
STI_VALIDATION = 10003,
};
/** Identifies fields.
Fields are necessary to tag data in signed transactions so that
the binary format of the transaction can be canonicalized.
*/
// VFALCO TODO rename this to NamedField
class SField
{
public:
typedef const SField& ref;
typedef SField const* ptr;
static const int sMD_Never = 0x00;
static const int sMD_ChangeOrig = 0x01; // original value when it changes
static const int sMD_ChangeNew = 0x02; // new value when it changes
static const int sMD_DeleteFinal = 0x04; // final value when it is deleted
static const int sMD_Create = 0x08; // value when it's created
static const int sMD_Always = 0x10; // value when node containing it is affected at all
static const int sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create;
public:
const int fieldCode; // (type<<16)|index
const SerializedTypeID fieldType; // STI_*
const int fieldValue; // Code number for protocol
std::string fieldName;
int fieldMeta;
int fieldNum;
bool signingField;
std::string rawJsonName;
Json::StaticString jsonName;
SField(SField const&) = delete;
SField& operator=(SField const&) = delete;
SField (int fc, SerializedTypeID tid, int fv, const char* fn)
: fieldCode (fc)
, fieldType (tid)
, fieldValue (fv)
, fieldName (fn)
, fieldMeta (sMD_Default)
, signingField (true)
, rawJsonName (getName ())
, jsonName (rawJsonName.c_str ())
{
StaticScopedLockType sl (getMutex ());
codeToField[fieldCode] = this;
fieldNum = ++num;
}
SField (SerializedTypeID tid, int fv, const char* fn)
: fieldCode (FIELD_CODE (tid, fv))
, fieldType (tid)
, fieldValue (fv)
, fieldName (fn)
, fieldMeta (sMD_Default)
, signingField (true)
, rawJsonName (getName ())
, jsonName (rawJsonName.c_str ())
{
StaticScopedLockType sl (getMutex ());
codeToField[fieldCode] = this;
fieldNum = ++num;
}
explicit SField (int fc)
: fieldCode (fc)
, fieldType (STI_UNKNOWN)
, fieldValue (0)
, fieldMeta (sMD_Never)
, signingField (true)
, rawJsonName (getName ())
, jsonName (rawJsonName.c_str ())
{
StaticScopedLockType sl (getMutex ());
fieldNum = ++num;
}
~SField ();
static SField::ref getField (int fieldCode);
static SField::ref getField (const std::string& fieldName);
static SField::ref getField (int type, int value)
{
return getField (FIELD_CODE (type, value));
}
static SField::ref getField (SerializedTypeID type, int value)
{
return getField (FIELD_CODE (type, value));
}
std::string getName () const;
bool hasName () const
{
return !fieldName.empty ();
}
Json::StaticString const& getJsonName () const
{
return jsonName;
}
bool isGeneric () const
{
return fieldCode == 0;
}
bool isInvalid () const
{
return fieldCode == -1;
}
bool isUseful () const
{
return fieldCode > 0;
}
bool isKnown () const
{
return fieldType != STI_UNKNOWN;
}
bool isBinary () const
{
return fieldValue < 256;
}
// VFALCO NOTE What is a discardable field?
bool isDiscardable () const
{
return fieldValue > 256;
}
int getCode () const
{
return fieldCode;
}
int getNum () const
{
return fieldNum;
}
static int getNumFields ()
{
return num;
}
bool isSigningField () const
{
return signingField;
}
void notSigningField ()
{
signingField = false;
}
bool shouldMeta (int c) const
{
return (fieldMeta & c) != 0;
}
void setMeta (int c)
{
fieldMeta = c;
}
bool shouldInclude (bool withSigningField) const
{
return (fieldValue < 256) && (withSigningField || signingField);
}
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);
// VFALCO TODO make these private
protected:
static std::map<int, ptr> codeToField;
typedef RippleMutex StaticLockType;
typedef std::lock_guard <StaticLockType> StaticScopedLockType;
static StaticLockType& getMutex ();
// VFALCO NOTE can this be replaced with an atomic int???!
static int num;
SField (SerializedTypeID id, int val);
};
extern SField sfInvalid, sfGeneric, sfLedgerEntry, sfTransaction, sfValidation;
#define FIELD(name, type, index) extern SField sf##name;
#define TYPE(name, type, index)
#include <ripple/module/data/protocol/SerializeDeclarations.h>
#undef FIELD
#undef TYPE
} // ripple
#endif

View File

@@ -0,0 +1,34 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
// The prefix codes are part of the Ripple protocol and existing codes cannot be
// arbitrarily changed.
HashPrefix const HashPrefix::transactionID ('T', 'X', 'N');
HashPrefix const HashPrefix::txNode ('S', 'N', 'D');
HashPrefix const HashPrefix::leafNode ('M', 'L', 'N');
HashPrefix const HashPrefix::innerNode ('M', 'I', 'N');
HashPrefix const HashPrefix::ledgerMaster ('L', 'W', 'R');
HashPrefix const HashPrefix::txSign ('S', 'T', 'X');
HashPrefix const HashPrefix::validation ('V', 'A', 'L');
HashPrefix const HashPrefix::proposal ('P', 'R', 'P');
} // ripple

View File

@@ -0,0 +1,91 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_HASHPREFIX_H
#define RIPPLE_HASHPREFIX_H
namespace ripple {
/** Prefix for hashing functions.
These prefixes are inserted before the source material used to generate
various hashes. This is done to put each hash in its own "space." This way,
two different types of objects with the same binary data will produce
different hashes.
Each prefix is a 4-byte value with the last byte set to zero and the first
three bytes formed from the ASCII equivalent of some arbitrary string. For
example "TXN".
@note Hash prefixes are part of the Ripple protocol.
@ingroup protocol
*/
class HashPrefix
{
private:
std::uint32_t m_prefix;
public:
HashPrefix (char a, char b, char c)
: m_prefix (0)
{
m_prefix = a;
m_prefix = (m_prefix << 8) + b;
m_prefix = (m_prefix << 8) + c;
m_prefix = m_prefix << 8;
}
/** Returns the hash prefix associated with this object */
operator std::uint32_t () const
{
return m_prefix;
}
// VFALCO TODO Expand the description to complete, concise sentences.
//
/** transaction plus signature to give transaction ID */
static HashPrefix const transactionID;
/** transaction plus metadata */
static HashPrefix const txNode;
/** account state */
static HashPrefix const leafNode;
/** inner node in tree */
static HashPrefix const innerNode;
/** ledger master data for signing */
static HashPrefix const ledgerMaster;
/** inner transaction to sign */
static HashPrefix const txSign;
/** validation for signing */
static HashPrefix const validation;
/** proposal for signing */
static HashPrefix const proposal;
};
} // ripple
#endif

View File

@@ -0,0 +1,192 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_KNOWNFORMATS_H_INCLUDED
#define RIPPLE_KNOWNFORMATS_H_INCLUDED
#include <beast/cxx14/memory.h> // <memory>
namespace ripple {
/** Manages a list of known formats.
Each format has a name, an associated KeyType (typically an enumeration),
and a predefined @ref SOElement.
@tparam KeyType The type of key identifying the format.
*/
template <class KeyType>
class KnownFormats
{
public:
/** A known format.
*/
class Item
{
public:
Item (char const* name, KeyType type)
: m_name (name)
, m_type (type)
{
}
Item& operator<< (SOElement const& el)
{
elements.push_back (el);
return *this;
}
/** Retrieve the name of the format.
*/
std::string const& getName () const noexcept
{
return m_name;
}
/** Retrieve the transaction type this format represents.
*/
KeyType getType () const noexcept
{
return m_type;
}
public:
// VFALCO TODO make an accessor for this
SOTemplate elements;
private:
std::string const m_name;
KeyType const m_type;
};
private:
typedef std::map <std::string, Item*> NameMap;
typedef std::map <KeyType, Item*> TypeMap;
public:
/** Create the known formats object.
Derived classes will load the object will all the known formats.
*/
KnownFormats ()
{
}
/** Destroy the known formats object.
The defined formats are deleted.
*/
~KnownFormats ()
{
}
/** Retrieve the type for a format specified by name.
If the format name is unknown, an exception is thrown.
@param name The name of the type.
@return The type.
*/
KeyType findTypeByName (std::string const name) const
{
Item const* const result = findByName (name);
if (result != nullptr)
{
return result->getType ();
}
else
{
throw std::runtime_error ("Unknown format name");
}
}
/** Retrieve a format based on its type.
*/
// VFALCO TODO Can we just return the SOElement& ?
Item const* findByType (KeyType type) const noexcept
{
Item* result = nullptr;
typename TypeMap::const_iterator const iter = m_types.find (type);
if (iter != m_types.end ())
{
result = iter->second;
}
return result;
}
protected:
/** Retrieve a format based on its name.
*/
Item const* findByName (std::string const& name) const noexcept
{
Item* result = nullptr;
typename NameMap::const_iterator const iter = m_names.find (name);
if (iter != m_names.end ())
{
result = iter->second;
}
return result;
}
/** Add a new format.
The new format has the set of common fields already added.
@param name The name of this format.
@param type The type of this format.
@return The created format.
*/
Item& add (char const* name, KeyType type)
{
m_formats.emplace_back (
std::make_unique <Item> (name, type));
auto& item (*m_formats.back());
addCommonFields (item);
m_types [item.getType ()] = &item;
m_names [item.getName ()] = &item;
return item;
}
/** Adds common fields.
This is called for every new item.
*/
virtual void addCommonFields (Item& item) = 0;
private:
std::vector <std::unique_ptr <Item>> m_formats;
NameMap m_names;
TypeMap m_types;
};
} // ripple
#endif

View File

@@ -0,0 +1,137 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
LedgerFormats::LedgerFormats ()
{
add ("AccountRoot", ltACCOUNT_ROOT)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfSequence, SOE_REQUIRED)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfOwnerCount, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfAccountTxnID, SOE_OPTIONAL)
<< SOElement (sfRegularKey, SOE_OPTIONAL)
<< SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement (sfTransferRate, SOE_OPTIONAL)
<< SOElement (sfDomain, SOE_OPTIONAL)
;
add ("Contract", ltCONTRACT)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfIssuer, SOE_REQUIRED)
<< SOElement (sfOwner, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement (sfExpireCode, SOE_OPTIONAL)
;
add ("DirectoryNode", ltDIR_NODE)
<< SOElement (sfOwner, SOE_OPTIONAL) // for owner directories
<< SOElement (sfTakerPaysCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerPaysIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerGetsCurrency, SOE_OPTIONAL) // for order book directories
<< SOElement (sfTakerGetsIssuer, SOE_OPTIONAL) // for order book directories
<< SOElement (sfExchangeRate, SOE_OPTIONAL) // for order book directories
<< SOElement (sfIndexes, SOE_REQUIRED)
<< SOElement (sfRootIndex, SOE_REQUIRED)
<< SOElement (sfIndexNext, SOE_OPTIONAL)
<< SOElement (sfIndexPrevious, SOE_OPTIONAL)
;
add ("GeneratorMap", ltGENERATOR_MAP)
<< SOElement (sfGenerator, SOE_REQUIRED)
;
add ("Nickname", ltNICKNAME)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfMinimumOffer, SOE_OPTIONAL)
;
add ("Offer", ltOFFER)
<< SOElement (sfAccount, SOE_REQUIRED)
<< SOElement (sfSequence, SOE_REQUIRED)
<< SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement (sfBookDirectory, SOE_REQUIRED)
<< SOElement (sfBookNode, SOE_REQUIRED)
<< SOElement (sfOwnerNode, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_OPTIONAL)
;
add ("RippleState", ltRIPPLE_STATE)
<< SOElement (sfBalance, SOE_REQUIRED)
<< SOElement (sfLowLimit, SOE_REQUIRED)
<< SOElement (sfHighLimit, SOE_REQUIRED)
<< SOElement (sfPreviousTxnID, SOE_REQUIRED)
<< SOElement (sfPreviousTxnLgrSeq, SOE_REQUIRED)
<< SOElement (sfLowNode, SOE_OPTIONAL)
<< SOElement (sfLowQualityIn, SOE_OPTIONAL)
<< SOElement (sfLowQualityOut, SOE_OPTIONAL)
<< SOElement (sfHighNode, SOE_OPTIONAL)
<< SOElement (sfHighQualityIn, SOE_OPTIONAL)
<< SOElement (sfHighQualityOut, SOE_OPTIONAL)
;
add ("LedgerHashes", ltLEDGER_HASHES)
<< SOElement (sfFirstLedgerSequence, SOE_OPTIONAL) // Remove if we do a ledger restart
<< SOElement (sfLastLedgerSequence, SOE_OPTIONAL)
<< SOElement (sfHashes, SOE_REQUIRED)
;
add ("EnabledAmendments", ltAMENDMENTS)
<< SOElement (sfAmendments, SOE_REQUIRED)
;
add ("FeeSettings", ltFEE_SETTINGS)
<< SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
;
}
void LedgerFormats::addCommonFields (Item& item)
{
item
<< SOElement(sfLedgerIndex, SOE_OPTIONAL)
<< SOElement(sfLedgerEntryType, SOE_REQUIRED)
<< SOElement(sfFlags, SOE_REQUIRED)
;
}
LedgerFormats* LedgerFormats::getInstance ()
{
return beast::SharedSingleton <LedgerFormats>::getInstance ();
}
} // ripple

View File

@@ -0,0 +1,136 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_LEDGERFORMATS_H_INCLUDED
#define RIPPLE_LEDGERFORMATS_H_INCLUDED
namespace ripple {
/** Ledger entry types.
These are stored in serialized data.
@note Changing these values results in a hard fork.
@ingroup protocol
*/
// Used as the type of a transaction or the type of a ledger entry.
enum LedgerEntryType
{
ltINVALID = -1,
ltACCOUNT_ROOT = 'a',
/** Directory node.
A directory is a vector 256-bit values. Usually they represent
hashes of other objects in the ledger.
Used in an append-only fashion.
(There's a little more information than this, see the template)
*/
ltDIR_NODE = 'd',
ltGENERATOR_MAP = 'g',
/** Describes a trust line.
*/
// VFALCO TODO Rename to TrustLine or something similar.
ltRIPPLE_STATE = 'r',
/** Deprecated.
*/
ltNICKNAME = 'n',
ltOFFER = 'o',
ltCONTRACT = 'c',
ltLEDGER_HASHES = 'h',
ltAMENDMENTS = 'f',
ltFEE_SETTINGS = 's',
};
/**
@ingroup protocol
*/
// Used as a prefix for computing ledger indexes (keys).
// VFALCO TODO Why are there a separate set of prefixes? i.e. class HashPrefix
enum LedgerNameSpace
{
spaceAccount = 'a',
spaceDirNode = 'd',
spaceGenerator = 'g',
spaceNickname = 'n',
spaceRipple = 'r',
spaceOffer = 'o', // Entry for an offer.
spaceOwnerDir = 'O', // Directory of things owned by an account.
spaceBookDir = 'B', // Directory of order books.
spaceContract = 'c',
spaceSkipList = 's',
spaceAmendment = 'f',
spaceFee = 'e',
};
/**
@ingroup protocol
*/
enum LedgerSpecificFlags
{
// ltACCOUNT_ROOT
lsfPasswordSpent = 0x00010000, // True, if password set fee is spent.
lsfRequireDestTag = 0x00020000, // True, to require a DestinationTag for payments.
lsfRequireAuth = 0x00040000, // True, to require a authorization to hold IOUs.
lsfDisallowXRP = 0x00080000, // True, to disallow sending XRP.
lsfDisableMaster = 0x00100000, // True, force regular key
// ltOFFER
lsfPassive = 0x00010000,
lsfSell = 0x00020000, // True, offer was placed as a sell.
// ltRIPPLE_STATE
lsfLowReserve = 0x00010000, // True, if entry counts toward reserve.
lsfHighReserve = 0x00020000,
lsfLowAuth = 0x00040000,
lsfHighAuth = 0x00080000,
lsfLowNoRipple = 0x00100000,
lsfHighNoRipple = 0x00200000,
};
//------------------------------------------------------------------------------
/** Holds the list of known ledger entry formats.
*/
class LedgerFormats : public KnownFormats <LedgerEntryType>
{
public:
LedgerFormats ();
static LedgerFormats* getInstance ();
private:
void addCommonFields (Item& item);
};
} // ripple
#endif

View File

@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_PROTOCOL_H
#define RIPPLE_PROTOCOL_H
#include <cstdint>
namespace ripple {
/** Protocol specific constants, types, and data.
This information is part of the Ripple protocol. Specifically,
it is required for peers to be able to communicate with each other.
@note Changing these will create a hard fork.
@ingroup protocol
@defgroup protocol
*/
struct Protocol
{
/** Smallest legal byte size of a transaction.
*/
static int const txMinSizeBytes = 32;
/** Largest legal byte size of a transaction.
*/
static int const txMaxSizeBytes = 1024 * 1024; // 1048576
};
/** A ledger index.
*/
// VFALCO TODO pick one. I like Index since its not an abbreviation
typedef std::uint32_t LedgerIndex;
// VFALCO NOTE "LedgerSeq" appears in some SQL statement text
typedef std::uint32_t LedgerSeq;
/** A transaction identifier.
*/
// VFALCO TODO maybe rename to TxHash
typedef uint256 TxID;
/** A transaction index.
*/
typedef std::uint32_t TxSeq; // VFALCO NOTE Should read TxIndex or TxNum
/** An account hash.
The hash is used to uniquely identify the account.
*/
//typedef uint160 AccountHash;
//typedef uint260 ValidatorID;
} // ripple
#endif

View File

@@ -0,0 +1,994 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/unit_test/suite.h>
namespace ripple {
SETUP_LOG (RippleAddress)
RippleAddress::RippleAddress ()
: mIsValid (false)
{
nVersion = VER_NONE;
}
void RippleAddress::clear ()
{
nVersion = VER_NONE;
vchData.clear ();
mIsValid = false;
}
bool RippleAddress::isSet () const
{
return nVersion != VER_NONE;
}
std::string RippleAddress::humanAddressType () const
{
switch (nVersion)
{
case VER_NONE:
return "VER_NONE";
case VER_NODE_PUBLIC:
return "VER_NODE_PUBLIC";
case VER_NODE_PRIVATE:
return "VER_NODE_PRIVATE";
case VER_ACCOUNT_ID:
return "VER_ACCOUNT_ID";
case VER_ACCOUNT_PUBLIC:
return "VER_ACCOUNT_PUBLIC";
case VER_ACCOUNT_PRIVATE:
return "VER_ACCOUNT_PRIVATE";
case VER_FAMILY_GENERATOR:
return "VER_FAMILY_GENERATOR";
case VER_FAMILY_SEED:
return "VER_FAMILY_SEED";
}
return "unknown";
}
//
// NodePublic
//
RippleAddress RippleAddress::createNodePublic (const RippleAddress& naSeed)
{
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew;
// YYY Should there be a GetPubKey() equiv that returns a uint256?
naNew.setNodePublic (ckSeed.GetPubKey ());
return naNew;
}
RippleAddress RippleAddress::createNodePublic (Blob const& vPublic)
{
RippleAddress naNew;
naNew.setNodePublic (vPublic);
return naNew;
}
RippleAddress RippleAddress::createNodePublic (const std::string& strPublic)
{
RippleAddress naNew;
naNew.setNodePublic (strPublic);
return naNew;
}
uint160 RippleAddress::getNodeID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodeID");
case VER_NODE_PUBLIC:
// Note, we are encoding the left.
return Hash160 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
Blob const& RippleAddress::getNodePublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodePublic");
case VER_NODE_PUBLIC:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanNodePublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanNodePublic");
case VER_NODE_PUBLIC:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setNodePublic (const std::string& strPublic)
{
mIsValid = SetString (strPublic, VER_NODE_PUBLIC, Base58::getRippleAlphabet ());
return mIsValid;
}
void RippleAddress::setNodePublic (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_NODE_PUBLIC, vPublic);
}
bool RippleAddress::verifyNodePublic (uint256 const& hash, Blob const& vchSig, ECDSA fullyCanonical) const
{
CKey pubkey = CKey ();
bool bVerified;
bVerified = isCanonicalECDSASig (vchSig, fullyCanonical);
if (bVerified && !pubkey.SetPubKey (getNodePublic ()))
{
// Failed to set public key.
bVerified = false;
}
else
{
bVerified = pubkey.Verify (hash, vchSig);
}
return bVerified;
}
bool RippleAddress::verifyNodePublic (uint256 const& hash, const std::string& strSig, ECDSA fullyCanonical) const
{
Blob vchSig (strSig.begin (), strSig.end ());
return verifyNodePublic (hash, vchSig, fullyCanonical);
}
//
// NodePrivate
//
RippleAddress RippleAddress::createNodePrivate (const RippleAddress& naSeed)
{
uint256 uPrivKey;
RippleAddress naNew;
CKey ckSeed (naSeed.getSeed ());
ckSeed.GetPrivateKeyU (uPrivKey);
naNew.setNodePrivate (uPrivKey);
return naNew;
}
Blob const& RippleAddress::getNodePrivateData () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getNodePrivateData");
case VER_NODE_PRIVATE:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
uint256 RippleAddress::getNodePrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source = getNodePrivate");
case VER_NODE_PRIVATE:
return uint256 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanNodePrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanNodePrivate");
case VER_NODE_PRIVATE:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setNodePrivate (const std::string& strPrivate)
{
mIsValid = SetString (strPrivate, VER_NODE_PRIVATE, Base58::getRippleAlphabet ());
return mIsValid;
}
void RippleAddress::setNodePrivate (Blob const& vPrivate)
{
mIsValid = true;
SetData (VER_NODE_PRIVATE, vPrivate);
}
void RippleAddress::setNodePrivate (uint256 hash256)
{
mIsValid = true;
SetData (VER_NODE_PRIVATE, hash256);
}
void RippleAddress::signNodePrivate (uint256 const& hash, Blob& vchSig) const
{
CKey ckPrivKey;
ckPrivKey.SetPrivateKeyU (getNodePrivate ());
if (!ckPrivKey.Sign (hash, vchSig))
throw std::runtime_error ("Signing failed.");
}
//
// AccountID
//
uint160 RippleAddress::getAccountID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountID");
case VER_ACCOUNT_ID:
return uint160 (vchData);
case VER_ACCOUNT_PUBLIC:
// Note, we are encoding the left.
return Hash160 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
typedef RippleMutex StaticLockType;
typedef std::lock_guard <StaticLockType> StaticScopedLockType;
static StaticLockType s_lock;
static ripple::unordered_map< Blob , std::string > rncMap;
std::string RippleAddress::humanAccountID () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountID");
case VER_ACCOUNT_ID:
{
StaticScopedLockType sl (s_lock);
auto it = rncMap.find (vchData);
if (it != rncMap.end ())
return it->second;
// VFALCO NOTE Why do we throw everything out? We could keep two maps
// here, switch back and forth keep one of them full and clear the
// other on a swap - but always check both maps for cache hits.
//
if (rncMap.size () > 250000)
rncMap.clear ();
return rncMap[vchData] = ToString ();
}
case VER_ACCOUNT_PUBLIC:
{
RippleAddress accountID;
(void) accountID.setAccountID (getAccountID ());
return accountID.ToString ();
}
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountID (const std::string& strAccountID, Base58::Alphabet const& alphabet)
{
if (strAccountID.empty ())
{
setAccountID (uint160 ());
mIsValid = true;
}
else
{
mIsValid = SetString (strAccountID, VER_ACCOUNT_ID, alphabet);
}
return mIsValid;
}
void RippleAddress::setAccountID (const uint160& hash160)
{
mIsValid = true;
SetData (VER_ACCOUNT_ID, hash160);
}
//
// AccountPublic
//
RippleAddress RippleAddress::createAccountPublic (const RippleAddress& naGenerator, int iSeq)
{
CKey ckPub (naGenerator, iSeq);
RippleAddress naNew;
naNew.setAccountPublic (ckPub.GetPubKey ());
return naNew;
}
Blob const& RippleAddress::getAccountPublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error ("public not available from account id");
break;
case VER_ACCOUNT_PUBLIC:
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanAccountPublic () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountPublic");
case VER_ACCOUNT_ID:
throw std::runtime_error ("public not available from account id");
case VER_ACCOUNT_PUBLIC:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountPublic (const std::string& strPublic)
{
mIsValid = SetString (strPublic, VER_ACCOUNT_PUBLIC, Base58::getRippleAlphabet ());
return mIsValid;
}
void RippleAddress::setAccountPublic (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_ACCOUNT_PUBLIC, vPublic);
}
void RippleAddress::setAccountPublic (const RippleAddress& generator, int seq)
{
CKey pubkey = CKey (generator, seq);
setAccountPublic (pubkey.GetPubKey ());
}
bool RippleAddress::accountPublicVerify (uint256 const& uHash, Blob const& vucSig, ECDSA fullyCanonical) const
{
CKey ckPublic;
bool bVerified = isCanonicalECDSASig (vucSig, fullyCanonical);
if (bVerified && !ckPublic.SetPubKey (getAccountPublic ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPublicVerify: Bad private key.";
bVerified = false;
}
else
{
bVerified = ckPublic.Verify (uHash, vucSig);
}
return bVerified;
}
RippleAddress RippleAddress::createAccountID (const uint160& uiAccountID)
{
RippleAddress na;
na.setAccountID (uiAccountID);
return na;
}
//
// AccountPrivate
//
RippleAddress RippleAddress::createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq)
{
RippleAddress naNew;
naNew.setAccountPrivate (naGenerator, naSeed, iSeq);
return naNew;
}
uint256 RippleAddress::getAccountPrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return uint256 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanAccountPrivate () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanAccountPrivate");
case VER_ACCOUNT_PRIVATE:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setAccountPrivate (const std::string& strPrivate)
{
mIsValid = SetString (strPrivate, VER_ACCOUNT_PRIVATE, Base58::getRippleAlphabet ());
return mIsValid;
}
void RippleAddress::setAccountPrivate (Blob const& vPrivate)
{
mIsValid = true;
SetData (VER_ACCOUNT_PRIVATE, vPrivate);
}
void RippleAddress::setAccountPrivate (uint256 hash256)
{
mIsValid = true;
SetData (VER_ACCOUNT_PRIVATE, hash256);
}
void RippleAddress::setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq)
{
CKey ckPubkey = CKey (naSeed.getSeed ());
CKey ckPrivkey = CKey (naGenerator, ckPubkey.GetSecretBN (), seq);
uint256 uPrivKey;
ckPrivkey.GetPrivateKeyU (uPrivKey);
setAccountPrivate (uPrivKey);
}
bool RippleAddress::accountPrivateSign (uint256 const& uHash, Blob& vucSig) const
{
CKey ckPrivate;
bool bResult;
if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateSign: Bad private key.";
bResult = false;
}
else
{
bResult = ckPrivate.Sign (uHash, vucSig);
CondLog (!bResult, lsWARNING, RippleAddress) << "accountPrivateSign: Signing failed.";
}
return bResult;
}
Blob RippleAddress::accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const
{
CKey ckPrivate;
CKey ckPublic;
Blob vucCipherText;
if (!ckPublic.SetPubKey (naPublicTo.getAccountPublic ()))
{
// Bad public key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad public key.";
}
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateEncrypt: Bad private key.";
}
else
{
try
{
vucCipherText = ckPrivate.encryptECIES (ckPublic, vucPlainText);
}
catch (...)
{
nothing ();
}
}
return vucCipherText;
}
Blob RippleAddress::accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const
{
CKey ckPrivate;
CKey ckPublic;
Blob vucPlainText;
if (!ckPublic.SetPubKey (naPublicFrom.getAccountPublic ()))
{
// Bad public key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad public key.";
}
else if (!ckPrivate.SetPrivateKeyU (getAccountPrivate ()))
{
// Bad private key.
WriteLog (lsWARNING, RippleAddress) << "accountPrivateDecrypt: Bad private key.";
}
else
{
try
{
vucPlainText = ckPrivate.decryptECIES (ckPublic, vucCipherText);
}
catch (...)
{
nothing ();
}
}
return vucPlainText;
}
//
// Generators
//
Blob const& RippleAddress::getGenerator () const
{
// returns the public generator
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getGenerator");
case VER_FAMILY_GENERATOR:
// Do nothing.
return vchData;
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanGenerator () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanGenerator");
case VER_FAMILY_GENERATOR:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
bool RippleAddress::setGenerator (const std::string& strGenerator)
{
mIsValid = SetString (strGenerator, VER_FAMILY_GENERATOR, Base58::getRippleAlphabet ());
return mIsValid;
}
void RippleAddress::setGenerator (Blob const& vPublic)
{
mIsValid = true;
SetData (VER_FAMILY_GENERATOR, vPublic);
}
RippleAddress RippleAddress::createGeneratorPublic (const RippleAddress& naSeed)
{
CKey ckSeed (naSeed.getSeed ());
RippleAddress naNew;
naNew.setGenerator (ckSeed.GetPubKey ());
return naNew;
}
//
// Seed
//
uint128 RippleAddress::getSeed () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - getSeed");
case VER_FAMILY_SEED:
return uint128 (vchData);
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanSeed1751 () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanSeed1751");
case VER_FAMILY_SEED:
{
std::string strHuman;
std::string strLittle;
std::string strBig;
uint128 uSeed = getSeed ();
strLittle.assign (uSeed.begin (), uSeed.end ());
strBig.assign (strLittle.rbegin (), strLittle.rend ());
RFC1751::getEnglishFromKey (strHuman, strBig);
return strHuman;
}
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
std::string RippleAddress::humanSeed () const
{
switch (nVersion)
{
case VER_NONE:
throw std::runtime_error ("unset source - humanSeed");
case VER_FAMILY_SEED:
return ToString ();
default:
throw std::runtime_error (str (boost::format ("bad source: %d") % int (nVersion)));
}
}
int RippleAddress::setSeed1751 (const std::string& strHuman1751)
{
std::string strKey;
int iResult = RFC1751::getKeyFromEnglish (strKey, strHuman1751);
if (1 == iResult)
{
Blob vchLittle (strKey.rbegin (), strKey.rend ());
uint128 uSeed (vchLittle);
setSeed (uSeed);
}
return iResult;
}
bool RippleAddress::setSeed (const std::string& strSeed)
{
mIsValid = SetString (strSeed, VER_FAMILY_SEED, Base58::getRippleAlphabet ());
return mIsValid;
}
bool RippleAddress::setSeedGeneric (const std::string& strText)
{
RippleAddress naTemp;
bool bResult = true;
uint128 uSeed;
if (strText.empty ()
|| naTemp.setAccountID (strText)
|| naTemp.setAccountPublic (strText)
|| naTemp.setAccountPrivate (strText)
|| naTemp.setNodePublic (strText)
|| naTemp.setNodePrivate (strText))
{
bResult = false;
}
else if (strText.length () == 32 && uSeed.SetHex (strText, true))
{
setSeed (uSeed);
}
else if (setSeed (strText))
{
// Log::out() << "Recognized seed.";
nothing ();
}
else if (1 == setSeed1751 (strText))
{
// Log::out() << "Recognized 1751 seed.";
nothing ();
}
else
{
// Log::out() << "Creating seed from pass phrase.";
setSeed (CKey::PassPhraseToKey (strText));
}
return bResult;
}
void RippleAddress::setSeed (uint128 hash128)
{
mIsValid = true;
SetData (VER_FAMILY_SEED, hash128);
}
void RippleAddress::setSeedRandom ()
{
// XXX Maybe we should call MakeNewKey
uint128 key;
RandomNumbers::getInstance ().fillBytes (key.begin (), key.size ());
RippleAddress::setSeed (key);
}
RippleAddress RippleAddress::createSeedRandom ()
{
RippleAddress naNew;
naNew.setSeedRandom ();
return naNew;
}
RippleAddress RippleAddress::createSeedGeneric (const std::string& strText)
{
RippleAddress naNew;
naNew.setSeedGeneric (strText);
return naNew;
}
//------------------------------------------------------------------------------
class RippleAddress_test : public beast::unit_test::suite
{
public:
void run()
{
// Construct a seed.
RippleAddress naSeed;
expect (naSeed.setSeedGeneric ("masterpassphrase"));
expect (naSeed.humanSeed () == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", naSeed.humanSeed ());
// Create node public/private key pair
RippleAddress naNodePublic = RippleAddress::createNodePublic (naSeed);
RippleAddress naNodePrivate = RippleAddress::createNodePrivate (naSeed);
expect (naNodePublic.humanNodePublic () == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9", naNodePublic.humanNodePublic ());
expect (naNodePrivate.humanNodePrivate () == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe", naNodePrivate.humanNodePrivate ());
// Check node signing.
Blob vucTextSrc = strCopy ("Hello, nurse!");
uint256 uHash = Serializer::getSHA512Half (vucTextSrc);
Blob vucTextSig;
naNodePrivate.signNodePrivate (uHash, vucTextSig);
expect (naNodePublic.verifyNodePublic (uHash, vucTextSig, ECDSA::strict), "Verify failed.");
// Construct a public generator from the seed.
RippleAddress naGenerator = RippleAddress::createGeneratorPublic (naSeed);
expect (naGenerator.humanGenerator () == "fhuJKrhSDzV2SkjLn9qbwm5AaRmrxDPfFsHDCP6yfDZWcxDFz4mt", naGenerator.humanGenerator ());
// Create account #0 public/private key pair.
RippleAddress naAccountPublic0 = RippleAddress::createAccountPublic (naGenerator, 0);
RippleAddress naAccountPrivate0 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 0);
expect (naAccountPublic0.humanAccountID () == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", naAccountPublic0.humanAccountID ());
expect (naAccountPublic0.humanAccountPublic () == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw", naAccountPublic0.humanAccountPublic ());
expect (naAccountPrivate0.humanAccountPrivate () == "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh", naAccountPrivate0.humanAccountPrivate ());
// Create account #1 public/private key pair.
RippleAddress naAccountPublic1 = RippleAddress::createAccountPublic (naGenerator, 1);
RippleAddress naAccountPrivate1 = RippleAddress::createAccountPrivate (naGenerator, naSeed, 1);
expect (naAccountPublic1.humanAccountID () == "r4bYF7SLUMD7QgSLLpgJx38WJSY12ViRjP", naAccountPublic1.humanAccountID ());
expect (naAccountPublic1.humanAccountPublic () == "aBPXpTfuLy1Bhk3HnGTTAqnovpKWQ23NpFMNkAF6F1Atg5vDyPrw", naAccountPublic1.humanAccountPublic ());
expect (naAccountPrivate1.humanAccountPrivate () == "p9JEm822LMrzJii1k7TvdphfENTp6G5jr253Xa5rkzUWVr8ogQt", naAccountPrivate1.humanAccountPrivate ());
// Check account signing.
expect (naAccountPrivate0.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
expect (naAccountPublic0.accountPublicVerify (uHash, vucTextSig, ECDSA::strict), "Verify failed.");
expect (!naAccountPublic1.accountPublicVerify (uHash, vucTextSig, ECDSA::not_strict), "Anti-verify failed.");
expect (!naAccountPublic1.accountPublicVerify (uHash, vucTextSig, ECDSA::strict), "Anti-verify failed.");
expect (naAccountPrivate1.accountPrivateSign (uHash, vucTextSig), "Signing failed.");
expect (naAccountPublic1.accountPublicVerify (uHash, vucTextSig, ECDSA::strict), "Verify failed.");
expect (!naAccountPublic0.accountPublicVerify (uHash, vucTextSig, ECDSA::not_strict), "Anti-verify failed.");
expect (!naAccountPublic0.accountPublicVerify (uHash, vucTextSig, ECDSA::strict), "Anti-verify failed.");
// Check account encryption.
Blob vucTextCipher
= naAccountPrivate0.accountPrivateEncrypt (naAccountPublic1, vucTextSrc);
Blob vucTextRecovered
= naAccountPrivate1.accountPrivateDecrypt (naAccountPublic0, vucTextCipher);
expect (vucTextSrc == vucTextRecovered, "Encrypt-decrypt failed.");
}
};
//------------------------------------------------------------------------------
class RippleIdentifier_test : public beast::unit_test::suite
{
public:
void run ()
{
testcase ("Seed");
RippleAddress seed;
expect (seed.setSeedGeneric ("masterpassphrase"));
expect (seed.humanSeed () == "snoPBrXtMeMyMHUVTgbuqAfg1SUTb", seed.humanSeed ());
testcase ("RipplePublicKey");
RippleAddress deprecatedPublicKey (RippleAddress::createNodePublic (seed));
expect (deprecatedPublicKey.humanNodePublic () ==
"n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9",
deprecatedPublicKey.humanNodePublic ());
RipplePublicKey publicKey (deprecatedPublicKey);
expect (publicKey.to_string() == deprecatedPublicKey.humanNodePublic(),
publicKey.to_string());
testcase ("RipplePrivateKey");
RippleAddress deprecatedPrivateKey (RippleAddress::createNodePrivate (seed));
expect (deprecatedPrivateKey.humanNodePrivate () ==
"pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe",
deprecatedPrivateKey.humanNodePrivate ());
RipplePrivateKey privateKey (deprecatedPrivateKey);
expect (privateKey.to_string() == deprecatedPrivateKey.humanNodePrivate(),
privateKey.to_string());
testcase ("Generator");
RippleAddress generator (RippleAddress::createGeneratorPublic (seed));
expect (generator.humanGenerator () ==
"fhuJKrhSDzV2SkjLn9qbwm5AaRmrxDPfFsHDCP6yfDZWcxDFz4mt",
generator.humanGenerator ());
testcase ("RippleAccountID");
RippleAddress deprecatedAccountPublicKey (
RippleAddress::createAccountPublic (generator, 0));
expect (deprecatedAccountPublicKey.humanAccountID () ==
"rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
deprecatedAccountPublicKey.humanAccountID ());
RippleAccountID accountID (deprecatedAccountPublicKey);
expect (accountID.to_string() ==
deprecatedAccountPublicKey.humanAccountID(),
accountID.to_string());
testcase ("RippleAccountPublicKey");
expect (deprecatedAccountPublicKey.humanAccountPublic () ==
"aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw",
deprecatedAccountPublicKey.humanAccountPublic ());
testcase ("RippleAccountPrivateKey");
RippleAddress deprecatedAccountPrivateKey (
RippleAddress::createAccountPrivate (generator, seed, 0));
expect (deprecatedAccountPrivateKey.humanAccountPrivate () ==
"p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh",
deprecatedAccountPrivateKey.humanAccountPrivate ());
RippleAccountPrivateKey accountPrivateKey (deprecatedAccountPrivateKey);
expect (accountPrivateKey.to_string() ==
deprecatedAccountPrivateKey.humanAccountPrivate(),
privateKey.to_string());
}
};
BEAST_DEFINE_TESTSUITE(RippleAddress,ripple_data,ripple);
BEAST_DEFINE_TESTSUITE(RippleIdentifier,ripple_data,ripple);
} // ripple

View File

@@ -0,0 +1,301 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_RIPPLEADDRESS_H
#define RIPPLE_RIPPLEADDRESS_H
#include <ripple/module/data/crypto/Base58Data.h>
#include <ripple/types/api/UInt160.h>
#include <ripple/types/api/RippleAccountID.h>
#include <ripple/types/api/RippleAccountPrivateKey.h>
#include <ripple/types/api/RippleAccountPublicKey.h>
#include <ripple/types/api/RipplePrivateKey.h>
#include <ripple/types/api/RipplePublicKey.h>
#include <ripple/types/api/RipplePublicKeyHash.h>
#include <ripple/sslutil/api/ECDSACanonical.h>
namespace ripple {
//
// Used to hold addresses and parse and produce human formats.
//
// XXX This needs to be reworked to store data in uint160 and uint256. Conversion to CBase58Data should happen as needed.
class RippleAddress : public CBase58Data
{
private:
typedef enum
{
VER_NONE = 1,
VER_NODE_PUBLIC = 28,
VER_NODE_PRIVATE = 32,
VER_ACCOUNT_ID = 0,
VER_ACCOUNT_PUBLIC = 35,
VER_ACCOUNT_PRIVATE = 34,
VER_FAMILY_GENERATOR = 41,
VER_FAMILY_SEED = 33,
} VersionEncoding;
bool mIsValid;
public:
RippleAddress ();
// For public and private key, checks if they are legal.
bool isValid () const
{
return mIsValid;
}
void clear ();
bool isSet () const;
std::string humanAddressType () const;
//
// Node Public - Also used for Validators
//
uint160 getNodeID () const;
Blob const& getNodePublic () const;
std::string humanNodePublic () const;
bool setNodePublic (const std::string& strPublic);
void setNodePublic (Blob const& vPublic);
bool verifyNodePublic (uint256 const& hash, Blob const& vchSig, ECDSA mustBeFullyCanonical) const;
bool verifyNodePublic (uint256 const& hash, const std::string& strSig, ECDSA mustBeFullyCanonical) const;
static RippleAddress createNodePublic (const RippleAddress& naSeed);
static RippleAddress createNodePublic (Blob const& vPublic);
static RippleAddress createNodePublic (const std::string& strPublic);
//
// Node Private
//
Blob const& getNodePrivateData () const;
uint256 getNodePrivate () const;
std::string humanNodePrivate () const;
bool setNodePrivate (const std::string& strPrivate);
void setNodePrivate (Blob const& vPrivate);
void setNodePrivate (uint256 hash256);
void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
static RippleAddress createNodePrivate (const RippleAddress& naSeed);
//
// Accounts IDs
//
uint160 getAccountID () const;
std::string humanAccountID () const;
bool setAccountID (const std::string& strAccountID, Base58::Alphabet const& alphabet = Base58::getRippleAlphabet());
void setAccountID (const uint160& hash160In);
static RippleAddress createAccountID (const std::string& strAccountID)
{
RippleAddress na;
na.setAccountID (strAccountID);
return na;
}
static RippleAddress createAccountID (const uint160& uiAccountID);
static std::string createHumanAccountID (const uint160& uiAccountID)
{
return createAccountID (uiAccountID).humanAccountID ();
}
static std::string createHumanAccountID (Blob const& vPrivate)
{
return createAccountPrivate (vPrivate).humanAccountID ();
}
//
// Accounts Public
//
Blob const& getAccountPublic () const;
std::string humanAccountPublic () const;
bool setAccountPublic (const std::string& strPublic);
void setAccountPublic (Blob const& vPublic);
void setAccountPublic (const RippleAddress& generator, int seq);
bool accountPublicVerify (uint256 const& uHash, Blob const& vucSig, ECDSA mustBeFullyCanonical) const;
static RippleAddress createAccountPublic (Blob const& vPublic)
{
RippleAddress naNew;
naNew.setAccountPublic (vPublic);
return naNew;
}
static std::string createHumanAccountPublic (Blob const& vPublic)
{
return createAccountPublic (vPublic).humanAccountPublic ();
}
// Create a deterministic public key from a public generator.
static RippleAddress createAccountPublic (const RippleAddress& naGenerator, int iSeq);
//
// Accounts Private
//
uint256 getAccountPrivate () const;
std::string humanAccountPrivate () const;
bool setAccountPrivate (const std::string& strPrivate);
void setAccountPrivate (Blob const& vPrivate);
void setAccountPrivate (uint256 hash256);
void setAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int seq);
bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
// Encrypt a message.
Blob accountPrivateEncrypt (const RippleAddress& naPublicTo, Blob const& vucPlainText) const;
// Decrypt a message.
Blob accountPrivateDecrypt (const RippleAddress& naPublicFrom, Blob const& vucCipherText) const;
static RippleAddress createAccountPrivate (const RippleAddress& naGenerator, const RippleAddress& naSeed, int iSeq);
static RippleAddress createAccountPrivate (Blob const& vPrivate)
{
RippleAddress naNew;
naNew.setAccountPrivate (vPrivate);
return naNew;
}
static std::string createHumanAccountPrivate (Blob const& vPrivate)
{
return createAccountPrivate (vPrivate).humanAccountPrivate ();
}
//
// Generators
// Use to generate a master or regular family.
//
Blob const& getGenerator () const;
std::string humanGenerator () const;
bool setGenerator (const std::string& strGenerator);
void setGenerator (Blob const& vPublic);
// void setGenerator(const RippleAddress& seed);
// Create generator for making public deterministic keys.
static RippleAddress createGeneratorPublic (const RippleAddress& naSeed);
//
// Seeds
// Clients must disallow reconizable entries from being seeds.
uint128 getSeed () const;
std::string humanSeed () const;
std::string humanSeed1751 () const;
bool setSeed (const std::string& strSeed);
int setSeed1751 (const std::string& strHuman1751);
bool setSeedGeneric (const std::string& strText);
void setSeed (uint128 hash128);
void setSeedRandom ();
static RippleAddress createSeedRandom ();
static RippleAddress createSeedGeneric (const std::string& strText);
};
//------------------------------------------------------------------------------
/** RipplePublicKey */
template <>
struct RipplePublicKeyTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
Blob const& b (v.getNodePublic ());
construct (&b.front(), &b.back()+1, value);
}
};
/** RipplePublicKeyHash */
template <>
struct RipplePublicKeyHashTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
uint160 const ui (v.getNodeID ());
construct (ui.begin(), ui.end(), value);
}
};
/** RipplePrivateKey */
template <>
struct RipplePrivateKeyTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
uint256 const ui (v.getNodePrivate ());
construct (ui.begin(), ui.end(), value);
}
};
/** RippleAccountID */
template <>
struct RippleAccountIDTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
uint160 const ui (v.getAccountID ());
construct (ui.begin(), ui.end(), value);
}
};
/** RippleAccountPublicKey */
template <>
struct RippleAccountPublicKeyTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
Blob const& b (v.getAccountPublic ());
construct (&b.front(), &b.back()+1, value);
}
};
/** RippleAccountPrivateKey */
template <>
struct RippleAccountPrivateKeyTraits::assign <RippleAddress>
{
void operator() (value_type& value, RippleAddress const& v) const
{
uint256 const ui (v.getAccountPrivate ());
construct (ui.begin(), ui.end(), value);
}
};
} // ripple
#endif

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_RIPPLESYSTEM_H
#define RIPPLE_RIPPLESYSTEM_H
namespace ripple {
/** Protocol specific constant globals. */
// VFALCO NOTE use these from now on instead of the macros!!
class RippleSystem
{
public:
static inline char const* getSystemName ()
{
return "ripple";
}
static char const* getCurrencyCode ()
{
return "XRP";
}
static char const* getCurrencyCodeRipple ()
{
return "XRR";
}
static int getCurrencyPrecision ()
{
return 6;
}
};
// VFALCO TODO I would love to replace these macros with the language
// constructs above. The problem is the way they are used at
// the point of call, i.e. "User-agent:" SYSTEM_NAME
// It will be necessary to rewrite some of them to use string streams.
//
#define SYSTEM_NAME "ripple"
#define SYSTEM_CURRENCY_CODE "XRP"
#define SYSTEM_CURRENCY_PRECISION 6
#define SYSTEM_CURRENCY_CODE_RIPPLE "XRR"
} // ripple
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
void STAmount::canonicalizeRound (bool isNative, std::uint64_t& value, int& offset, bool roundUp)
{
if (!roundUp) // canonicalize already rounds down
return;
WriteLog (lsTRACE, STAmount) << "canonicalize< " << value << ":" << offset << (roundUp ? " up" : " down");
if (isNative)
{
if (offset < 0)
{
int loops = 0;
while (offset < -1)
{
value /= 10;
++offset;
++loops;
}
value += (loops >= 2) ? 9 : 10; // add before last divide
value /= 10;
++offset;
}
}
else if (value > STAmount::cMaxValue)
{
while (value > (10 * STAmount::cMaxValue))
{
value /= 10;
++offset;
}
value += 9; // add before last divide
value /= 10;
++offset;
}
WriteLog (lsTRACE, STAmount) << "canonicalize> " << value << ":" << offset << (roundUp ? " up" : " down");
}
STAmount STAmount::addRound (const STAmount& v1, const STAmount& v2, bool roundUp)
{
v1.throwComparable (v2);
if (v2.mValue == 0)
return v1;
if (v1.mValue == 0)
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, v2.mIsNegative);
if (v1.mIsNative)
return STAmount (v1.getFName (), v1.getSNValue () + v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset;
std::int64_t vv1 = static_cast<std::int64_t> (v1.mValue), vv2 = static_cast<std::uint64_t> (v2.mValue);
if (v1.mIsNegative)
vv1 = -vv1;
if (v2.mIsNegative)
vv2 = -vv2;
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
std::int64_t fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
std::uint64_t v = static_cast<std::uint64_t> (fv);
canonicalizeRound (false, v, ov1, roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
std::uint64_t v = static_cast<std::uint64_t> (-fv);
canonicalizeRound (false, v, ov1, !roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
}
STAmount STAmount::subRound (const STAmount& v1, const STAmount& v2, bool roundUp)
{
v1.throwComparable (v2);
if (v2.mValue == 0)
return v1;
if (v1.mValue == 0)
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v2.mValue, v2.mOffset, !v2.mIsNegative);
if (v1.mIsNative)
return STAmount (v1.getFName (), v1.getSNValue () - v2.getSNValue ());
int ov1 = v1.mOffset, ov2 = v2.mOffset;
std::int64_t vv1 = static_cast<std::int64_t> (v1.mValue), vv2 = static_cast<std::uint64_t> (v2.mValue);
if (v1.mIsNegative)
vv1 = -vv1;
if (!v2.mIsNegative)
vv2 = -vv2;
if (ov1 < ov2)
{
while (ov1 < (ov2 - 1))
{
vv1 /= 10;
++ov1;
}
if (roundUp)
vv1 += 9;
vv1 /= 10;
++ov1;
}
if (ov2 < ov1)
{
while (ov2 < (ov1 - 1))
{
vv2 /= 10;
++ov2;
}
if (roundUp)
vv2 += 9;
vv2 /= 10;
++ov2;
}
std::int64_t fv = vv1 + vv2;
if ((fv >= -10) && (fv <= 10))
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer);
else if (fv >= 0)
{
std::uint64_t v = static_cast<std::uint64_t> (fv);
canonicalizeRound (false, v, ov1, roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, false);
}
else
{
std::uint64_t v = static_cast<std::uint64_t> (-fv);
canonicalizeRound (false, v, ov1, !roundUp);
return STAmount (v1.getFName (), v1.mCurrency, v1.mIssuer, v, ov1, true);
}
}
STAmount STAmount::mulRound (const STAmount& v1, const STAmount& v2,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{
if (v1 == zero || v2 == zero)
return STAmount (uCurrencyID, uIssuerID);
if (v1.mIsNative && v2.mIsNative && uCurrencyID.isZero ())
{
std::uint64_t minV = (v1.getSNValue () < v2.getSNValue ()) ? v1.getSNValue () : v2.getSNValue ();
std::uint64_t maxV = (v1.getSNValue () < v2.getSNValue ()) ? v2.getSNValue () : v1.getSNValue ();
if (minV > 3000000000ull) // sqrt(cMaxNative)
throw std::runtime_error ("Native value overflow");
if (((maxV >> 32) * minV) > 2095475792ull) // cMaxNative / 2^32
throw std::runtime_error ("Native value overflow");
return STAmount (v1.getFName (), minV * maxV);
}
std::uint64_t value1 = v1.mValue, value2 = v2.mValue;
int offset1 = v1.mOffset, offset2 = v2.mOffset;
if (v1.mIsNative)
{
while (value1 < STAmount::cMinValue)
{
value1 *= 10;
--offset1;
}
}
if (v2.mIsNative)
{
while (value2 < STAmount::cMinValue)
{
value2 *= 10;
--offset2;
}
}
bool resultNegative = v1.mIsNegative != v2.mIsNegative;
// Compute (numerator * denominator) / 10^14 with rounding
// 10^16 <= result <= 10^18
CBigNum v;
if ((BN_add_word64 (&v, value1) != 1) || (BN_mul_word64 (&v, value2) != 1))
throw std::runtime_error ("internal bn error");
if (resultNegative != roundUp) // rounding down is automatic when we divide
BN_add_word64 (&v, tenTo14m1);
if (BN_div_word64 (&v, tenTo14) == ((std::uint64_t) - 1))
throw std::runtime_error ("internal bn error");
// 10^16 <= product <= 10^18
assert (BN_num_bytes (&v) <= 64);
std::uint64_t amount = v.getuint64 ();
int offset = offset1 + offset2 + 14;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
}
STAmount STAmount::divRound (const STAmount& num, const STAmount& den,
const uint160& uCurrencyID, const uint160& uIssuerID, bool roundUp)
{
if (den == zero)
throw std::runtime_error ("division by zero");
if (num == zero)
return STAmount (uCurrencyID, uIssuerID);
std::uint64_t numVal = num.mValue, denVal = den.mValue;
int numOffset = num.mOffset, denOffset = den.mOffset;
if (num.mIsNative)
while (numVal < STAmount::cMinValue)
{
// Need to bring into range
numVal *= 10;
--numOffset;
}
if (den.mIsNative)
while (denVal < STAmount::cMinValue)
{
denVal *= 10;
--denOffset;
}
bool resultNegative = num.mIsNegative != den.mIsNegative;
// Compute (numerator * 10^17) / denominator
CBigNum v;
if ((BN_add_word64 (&v, numVal) != 1) || (BN_mul_word64 (&v, tenTo17) != 1))
throw std::runtime_error ("internal bn error");
if (resultNegative != roundUp) // Rounding down is automatic when we divide
BN_add_word64 (&v, denVal - 1);
if (BN_div_word64 (&v, denVal) == ((std::uint64_t) - 1))
throw std::runtime_error ("internal bn error");
// 10^16 <= quotient <= 10^18
assert (BN_num_bytes (&v) <= 64);
std::uint64_t amount = v.getuint64 ();
int offset = numOffset - denOffset - 17;
canonicalizeRound (uCurrencyID.isZero (), amount, offset, resultNegative != roundUp);
return STAmount (uCurrencyID, uIssuerID, amount, offset, resultNegative);
}
} // ripple

View File

@@ -0,0 +1,732 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <cassert>
#include <beast/module/core/text/LexicalCast.h>
namespace ripple {
STParsedJSON::STParsedJSON (std::string const& name, Json::Value const& json)
{
parse (name, json, sfGeneric, 0, object);
}
//------------------------------------------------------------------------------
std::string STParsedJSON::make_name (std::string const& object,
std::string const& field)
{
if (field.empty ())
return object;
return object + "." + field;
}
Json::Value STParsedJSON::not_an_object (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' is not a JSON object.");
}
Json::Value STParsedJSON::unknown_field (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' is unknown.");
}
Json::Value STParsedJSON::out_of_range (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' is out of range.");
}
Json::Value STParsedJSON::bad_type (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' has bad type.");
}
Json::Value STParsedJSON::invalid_data (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' has invalid data.");
}
Json::Value STParsedJSON::array_expected (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' must be a JSON array.");
}
Json::Value STParsedJSON::string_expected (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' must be a string.");
}
Json::Value STParsedJSON::too_deep (std::string const& object,
std::string const& field)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + make_name (object, field) + "' exceeds nesting depth limit.");
}
Json::Value STParsedJSON::singleton_expected (std::string const& object)
{
return RPC::make_error (rpcINVALID_PARAMS,
"Field '" + object +
"' must be an object with a single key/object value.");
}
//------------------------------------------------------------------------------
bool STParsedJSON::parse (std::string const& json_name,
Json::Value const& json, SField::ref inName, int depth,
std::unique_ptr <STObject>& sub_object)
{
if (! json.isObject ())
{
error = not_an_object (json_name);
return false;
}
SField::ptr name (&inName);
boost::ptr_vector<SerializedType> data;
Json::Value::Members members (json.getMemberNames ());
for (Json::Value::Members::iterator it (members.begin ());
it != members.end (); ++it)
{
std::string const& fieldName = *it;
Json::Value const& value = json [fieldName];
SField::ref field = SField::getField (fieldName);
if (field == sfInvalid)
{
error = unknown_field (json_name, fieldName);
return false;
}
switch (field.fieldType)
{
case STI_UINT8:
try
{
if (value.isString ())
{
// VFALCO TODO wtf?
}
else if (value.isInt ())
{
if (value.asInt () < 0 || value.asInt () > 255)
{
error = out_of_range (json_name, fieldName);
return false;
}
data.push_back (new STUInt8 (field,
range_check_cast <unsigned char> (
value.asInt (), 0, 255)));
}
else if (value.isUInt ())
{
if (value.asUInt () > 255)
{
error = out_of_range (json_name, fieldName);
return false;
}
data.push_back (new STUInt8 (field,
range_check_cast <unsigned char> (
value.asUInt (), 0, 255)));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_UINT16:
try
{
if (value.isString ())
{
std::string strValue = value.asString ();
if (! strValue.empty () &&
((strValue[0] < '0') || (strValue[0] > '9')))
{
if (field == sfTransactionType)
{
TxType const txType (TxFormats::getInstance()->
findTypeByName (strValue));
data.push_back (new STUInt16 (field,
static_cast <std::uint16_t> (txType)));
if (*name == sfGeneric)
name = &sfTransaction;
}
else if (field == sfLedgerEntryType)
{
LedgerEntryType const type (LedgerFormats::getInstance()->
findTypeByName (strValue));
data.push_back (new STUInt16 (field,
static_cast <std::uint16_t> (type)));
if (*name == sfGeneric)
name = &sfLedgerEntry;
}
else
{
error = invalid_data (json_name, fieldName);
return false;
}
}
else
{
data.push_back (new STUInt16 (field,
beast::lexicalCastThrow <std::uint16_t> (strValue)));
}
}
else if (value.isInt ())
{
data.push_back (new STUInt16 (field,
range_check_cast <std::uint16_t> (
value.asInt (), 0, 65535)));
}
else if (value.isUInt ())
{
data.push_back (new STUInt16 (field,
range_check_cast <std::uint16_t> (
value.asUInt (), 0, 65535)));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_UINT32:
try
{
if (value.isString ())
{
data.push_back (new STUInt32 (field,
beast::lexicalCastThrow <std::uint32_t> (value.asString ())));
}
else if (value.isInt ())
{
data.push_back (new STUInt32 (field,
range_check_cast <std::uint32_t> (value.asInt (), 0u, 4294967295u)));
}
else if (value.isUInt ())
{
data.push_back (new STUInt32 (field,
static_cast <std::uint32_t> (value.asUInt ())));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_UINT64:
try
{
if (value.isString ())
{
data.push_back (new STUInt64 (field,
uintFromHex (value.asString ())));
}
else if (value.isInt ())
{
data.push_back (new STUInt64 (field,
range_check_cast<std::uint64_t> (
value.asInt (), 0, 18446744073709551615ull)));
}
else if (value.isUInt ())
{
data.push_back (new STUInt64 (field,
static_cast <std::uint64_t> (value.asUInt ())));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_HASH128:
try
{
if (value.isString ())
{
data.push_back (new STHash128 (field, value.asString ()));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_HASH160:
try
{
if (value.isString ())
{
data.push_back (new STHash160 (field, value.asString ()));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_HASH256:
try
{
if (value.isString ())
{
data.push_back (new STHash256 (field, value.asString ()));
}
else
{
error = bad_type (json_name, fieldName);
return false;
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_VL:
if (! value.isString ())
{
error = bad_type (json_name, fieldName);
return false;
}
try
{
std::pair<Blob, bool> ret(strUnHex (value.asString ()));
if (!ret.second)
throw std::invalid_argument ("invalid data");
data.push_back (new STVariableLength (field, ret.first));
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_AMOUNT:
try
{
data.push_back (new STAmount (field, value));
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_VECTOR256:
if (! value.isArray ())
{
error = array_expected (json_name, fieldName);
return false;
}
try
{
data.push_back (new STVector256 (field));
STVector256* tail (dynamic_cast <STVector256*> (&data.back ()));
assert (tail);
for (Json::UInt i = 0; value.isValidIndex (i); ++i)
{
uint256 s;
s.SetHex (value[i].asString ());
tail->addValue (s);
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_PATHSET:
if (!value.isArray ())
{
error = array_expected (json_name, fieldName);
return false;
}
try
{
data.push_back (new STPathSet (field));
STPathSet* tail = dynamic_cast <STPathSet*> (&data.back ());
assert (tail);
for (Json::UInt i = 0; value.isValidIndex (i); ++i)
{
STPath p;
if (!value[i].isArray ())
{
std::stringstream ss;
ss << fieldName << "[" << i << "]";
error = array_expected (json_name, ss.str ());
return false;
}
for (Json::UInt j = 0; value[i].isValidIndex (j); ++j)
{
std::stringstream ss;
ss << fieldName << "[" << i << "][" << j << "]";
std::string const element_name (
json_name + "." + ss.str());
// each element in this path has some combination of account,
// currency, or issuer
Json::Value pathEl = value[i][j];
if (!pathEl.isObject ())
{
error = not_an_object (element_name);
return false;
}
const Json::Value& account = pathEl["account"];
const Json::Value& currency = pathEl["currency"];
const Json::Value& issuer = pathEl["issuer"];
bool hasCurrency = false;
uint160 uAccount, uCurrency, uIssuer;
if (! account.isNull ())
{
// human account id
if (! account.isString ())
{
error = string_expected (element_name, "account");
return false;
}
std::string const strValue (account.asString ());
if (value.size () == 40) // 160-bit hex account value
uAccount.SetHex (strValue);
{
RippleAddress a;
if (! a.setAccountID (strValue))
{
error = invalid_data (element_name, "account");
return false;
}
uAccount = a.getAccountID ();
}
}
if (!currency.isNull ())
{
// human currency
if (!currency.isString ())
{
error = string_expected (element_name, "currency");
return false;
}
hasCurrency = true;
if (currency.asString ().size () == 40)
{
uCurrency.SetHex (currency.asString ());
}
else if (!STAmount::currencyFromString (
uCurrency, currency.asString ()))
{
error = invalid_data (element_name, "currency");
return false;
}
}
if (!issuer.isNull ())
{
// human account id
if (!issuer.isString ())
{
error = string_expected (element_name, "issuer");
return false;
}
if (issuer.asString ().size () == 40)
{
uIssuer.SetHex (issuer.asString ());
}
else
{
RippleAddress a;
if (!a.setAccountID (issuer.asString ()))
{
error = invalid_data (element_name, "issuer");
return false;
}
uIssuer = a.getAccountID ();
}
}
p.addElement (STPathElement (uAccount, uCurrency, uIssuer, hasCurrency));
}
tail->addPath (p);
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_ACCOUNT:
{
if (! value.isString ())
{
error = bad_type (json_name, fieldName);
return false;
}
std::string strValue = value.asString ();
try
{
if (value.size () == 40) // 160-bit hex account value
{
uint160 v;
v.SetHex (strValue);
data.push_back (new STAccount (field, v));
}
else
{
// ripple address
RippleAddress a;
if (!a.setAccountID (strValue))
{
error = invalid_data (json_name, fieldName);
return false;
}
data.push_back (new STAccount (field, a.getAccountID ()));
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
}
break;
case STI_OBJECT:
case STI_TRANSACTION:
case STI_LEDGERENTRY:
case STI_VALIDATION:
if (! value.isObject ())
{
error = not_an_object (json_name, fieldName);
return false;
}
if (depth > 64)
{
error = too_deep (json_name, fieldName);
return false;
}
try
{
std::unique_ptr <STObject> sub_object_;
bool const success (parse (json_name + "." + fieldName,
value, field, depth + 1, sub_object_));
if (! success)
return false;
data.push_back (sub_object_.release ());
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
case STI_ARRAY:
if (! value.isArray ())
{
error = array_expected (json_name, fieldName);
return false;
}
try
{
data.push_back (new STArray (field));
STArray* tail = dynamic_cast<STArray*> (&data.back ());
assert (tail);
for (Json::UInt i = 0; value.isValidIndex (i); ++i)
{
bool const isObject (value[i].isObject());
bool const singleKey (isObject
? value [i].size() == 1
: true);
if (!isObject || !singleKey)
{
std::stringstream ss;
ss << json_name << "." << fieldName << "[" << i << "]";
error = singleton_expected (ss.str ());
return false;
}
// TODO: There doesn't seem to be a nice way to get just the
// first/only key in an object without copying all keys into
// a vector
std::string const objectName (value[i].getMemberNames()[0]);;
SField::ref nameField (SField::getField(objectName));
if (nameField == sfInvalid)
{
error = unknown_field (json_name, objectName);
return false;
}
Json::Value const objectFields (value[i][objectName]);
std::unique_ptr <STObject> sub_object_;
{
std::stringstream ss;
ss << json_name << "." << fieldName <<
"[" << i << "]." << objectName;
bool const success (parse (ss.str (), objectFields,
nameField, depth + 1, sub_object_));
if (! success)
return false;
}
tail->push_back (*sub_object_);
}
}
catch (...)
{
error = invalid_data (json_name, fieldName);
return false;
}
break;
default:
error = bad_type (json_name, fieldName);
return false;
}
}
sub_object.reset (new STObject (*name, data));
return true;
}
} // ripple

View File

@@ -0,0 +1,84 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_DATA_STPARSEDJSON_H
#define RIPPLE_DATA_STPARSEDJSON_H
namespace ripple {
/** Holds the serialized result of parsing input JSON.
This does validation and checking on the provided JSON.
*/
class STParsedJSON
{
public:
/** Parses and creates an STParsedJSON object.
The result of the parsing is stored in object and error.
Exceptions:
Does not throw.
@param name The name of the JSON field, used in diagnostics.
@param json The JSON-RPC to parse.
*/
STParsedJSON (std::string const& name,
Json::Value const& json);
/** The STObject if the parse was successful. */
std::unique_ptr <STObject> object;
/** On failure, an appropriate set of error values. */
Json::Value error;
private:
static std::string make_name (std::string const& object,
std::string const& field);
static Json::Value not_an_object (std::string const& object,
std::string const& field = std::string());
static Json::Value unknown_field (std::string const& object,
std::string const& field = std::string());
static Json::Value out_of_range (std::string const& object,
std::string const& field = std::string());
static Json::Value bad_type (std::string const& object,
std::string const& field = std::string());
static Json::Value invalid_data (std::string const& object,
std::string const& field = std::string());
static Json::Value array_expected (std::string const& object,
std::string const& field = std::string());
static Json::Value string_expected (std::string const& object,
std::string const& field = std::string());
static Json::Value too_deep (std::string const& object,
std::string const& field = std::string());
static Json::Value singleton_expected (
std::string const& object);
bool parse (std::string const& json_name, Json::Value const& json,
SField::ref inName, int depth, std::unique_ptr <STObject>& sub_object);
};
} // ripple
#endif

View File

@@ -0,0 +1,205 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
// This is not really a header file, but it can be used as one with
// appropriate #define statements.
/*
Common type common field - 1 byte
Common type uncommon field - 2 bytes
...
Rarity of fields determines the number of bytes.
This is done to reduce the average size of the messages.
*/
// types (common)
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)
// 9-13 are reserved
TYPE (Object, OBJECT, 14)
TYPE (Array, ARRAY, 15)
// types (uncommon)
TYPE (Int8, UINT8, 16)
TYPE (Hash160, HASH160, 17)
TYPE (PathSet, PATHSET, 18)
TYPE (Vector256, VECTOR256, 19)
// 8-bit integers
FIELD (CloseResolution, UINT8, 1)
FIELD (TemplateEntryType, UINT8, 2)
FIELD (TransactionResult, UINT8, 3)
// 16-bit integers
FIELD (LedgerEntryType, UINT16, 1)
FIELD (TransactionType, UINT16, 2)
// 32-bit integers (common)
FIELD (Flags, UINT32, 2)
FIELD (SourceTag, UINT32, 3)
FIELD (Sequence, UINT32, 4)
FIELD (PreviousTxnLgrSeq, 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 (WalletSize, UINT32, 12)
FIELD (OwnerCount, UINT32, 13)
FIELD (DestinationTag, UINT32, 14)
// 32-bit integers (uncommon)
FIELD (HighQualityIn, UINT32, 16)
FIELD (HighQualityOut, UINT32, 17)
FIELD (LowQualityIn, UINT32, 18)
FIELD (LowQualityOut, UINT32, 19)
FIELD (QualityIn, UINT32, 20)
FIELD (QualityOut, UINT32, 21)
FIELD (StampEscrow, UINT32, 22)
FIELD (BondAmount, UINT32, 23)
FIELD (LoadFee, UINT32, 24)
FIELD (OfferSequence, UINT32, 25)
FIELD (FirstLedgerSequence, UINT32, 26) // Deprecated: do not use
FIELD (LastLedgerSequence, UINT32, 27)
FIELD (TransactionIndex, UINT32, 28)
FIELD (OperationLimit, UINT32, 29)
FIELD (ReferenceFeeUnits, UINT32, 30)
FIELD (ReserveBase, UINT32, 31)
FIELD (ReserveIncrement, UINT32, 32)
FIELD (SetFlag, UINT32, 33)
FIELD (ClearFlag, UINT32, 34)
// 64-bit integers
FIELD (IndexNext, UINT64, 1)
FIELD (IndexPrevious, UINT64, 2)
FIELD (BookNode, UINT64, 3)
FIELD (OwnerNode, UINT64, 4)
FIELD (BaseFee, UINT64, 5)
FIELD (ExchangeRate, UINT64, 6)
FIELD (LowNode, UINT64, 7)
FIELD (HighNode, UINT64, 8)
// 128-bit
FIELD (EmailHash, HASH128, 1)
// 256-bit (common)
FIELD (LedgerHash, HASH256, 1)
FIELD (ParentHash, HASH256, 2)
FIELD (TransactionHash, HASH256, 3)
FIELD (AccountHash, HASH256, 4)
FIELD (PreviousTxnID, HASH256, 5)
FIELD (LedgerIndex, HASH256, 6)
FIELD (WalletLocator, HASH256, 7)
FIELD (RootIndex, HASH256, 8)
FIELD (AccountTxnID, HASH256, 9)
// 256-bit (uncommon)
FIELD (BookDirectory, HASH256, 16)
FIELD (InvoiceID, HASH256, 17)
FIELD (Nickname, HASH256, 18)
FIELD (Amendment, HASH256, 19)
// 160-bit (common)
FIELD (TakerPaysCurrency, HASH160, 1)
FIELD (TakerPaysIssuer, HASH160, 2)
FIELD (TakerGetsCurrency, HASH160, 3)
FIELD (TakerGetsIssuer, HASH160, 4)
// currency amount (common)
FIELD (Amount, AMOUNT, 1)
FIELD (Balance, AMOUNT, 2)
FIELD (LimitAmount, AMOUNT, 3)
FIELD (TakerPays, AMOUNT, 4)
FIELD (TakerGets, AMOUNT, 5)
FIELD (LowLimit, AMOUNT, 6)
FIELD (HighLimit, AMOUNT, 7)
FIELD (Fee, AMOUNT, 8)
FIELD (SendMax, AMOUNT, 9)
// currency amount (uncommon)
FIELD (MinimumOffer, AMOUNT, 16)
FIELD (RippleEscrow, AMOUNT, 17)
FIELD (DeliveredAmount, AMOUNT, 18)
// variable length
FIELD (PublicKey, VL, 1)
FIELD (MessageKey, VL, 2)
FIELD (SigningPubKey, VL, 3)
FIELD (TxnSignature, VL, 4)
FIELD (Generator, VL, 5)
FIELD (Signature, VL, 6)
FIELD (Domain, VL, 7)
FIELD (FundCode, VL, 8)
FIELD (RemoveCode, VL, 9)
FIELD (ExpireCode, VL, 10)
FIELD (CreateCode, VL, 11)
FIELD (MemoType, VL, 12)
FIELD (MemoData, VL, 13)
// account
FIELD (Account, ACCOUNT, 1)
FIELD (Owner, ACCOUNT, 2)
FIELD (Destination, ACCOUNT, 3)
FIELD (Issuer, ACCOUNT, 4)
FIELD (Target, ACCOUNT, 7)
FIELD (RegularKey, ACCOUNT, 8)
// path set
FIELD (Paths, PATHSET, 1)
// vector of 256-bit
FIELD (Indexes, VECTOR256, 1)
FIELD (Hashes, VECTOR256, 2)
FIELD (Amendments, VECTOR256, 3)
// inner object
// OBJECT/1 is reserved for end of object
FIELD (TransactionMetaData, OBJECT, 2)
FIELD (CreatedNode, OBJECT, 3)
FIELD (DeletedNode, OBJECT, 4)
FIELD (ModifiedNode, OBJECT, 5)
FIELD (PreviousFields, OBJECT, 6)
FIELD (FinalFields, OBJECT, 7)
FIELD (NewFields, OBJECT, 8)
FIELD (TemplateEntry, OBJECT, 9)
FIELD (Memo, OBJECT, 10)
// array of objects
// ARRAY/1 is reserved for end of array
FIELD (SigningAccounts, ARRAY, 2)
FIELD (TxnSignatures, ARRAY, 3)
FIELD (Signatures, ARRAY, 4)
FIELD (Template, ARRAY, 5)
FIELD (Necessary, ARRAY, 6)
FIELD (Sufficient, ARRAY, 7)
FIELD (AffectedNodes, ARRAY, 8)
FIELD (Memos, ARRAY, 9)
// vim:ts=4

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,527 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_SERIALIZEDOBJECT_H
#define RIPPLE_SERIALIZEDOBJECT_H
#include <boost/ptr_container/ptr_vector.hpp> // VFALCO NOTE this looks like junk
namespace ripple {
class STArray;
class STObject
: public SerializedType
, public CountedObject <STObject>
{
public:
static char const* getCountedObjectName () { return "STObject"; }
STObject () : mType (nullptr)
{
;
}
explicit STObject (SField::ref name) : SerializedType (name), mType (nullptr)
{
;
}
STObject (const SOTemplate & type, SField::ref name) : SerializedType (name)
{
set (type);
}
STObject (const SOTemplate & type, SerializerIterator & sit, SField::ref name) : SerializedType (name)
{
set (sit);
setType (type);
}
STObject (SField::ref name, boost::ptr_vector<SerializedType>& data) : SerializedType (name), mType (nullptr)
{
mData.swap (data);
}
std::unique_ptr <STObject> oClone () const
{
return std::unique_ptr<STObject> (new STObject (*this));
}
virtual ~STObject () { }
static std::unique_ptr<SerializedType> deserialize (SerializerIterator & sit, SField::ref name);
bool setType (const SOTemplate & type);
bool isValidForType ();
bool isFieldAllowed (SField::ref);
bool isFree () const
{
return mType == nullptr;
}
void set (const SOTemplate&);
bool set (SerializerIterator & u, int depth = 0);
virtual SerializedTypeID getSType () const
{
return STI_OBJECT;
}
virtual bool isEquivalent (const SerializedType & t) const;
virtual bool isDefault () const
{
return mData.empty ();
}
virtual void add (Serializer & s) const
{
add (s, true); // just inner elements
}
void add (Serializer & s, bool withSignature) const;
// VFALCO NOTE does this return an expensive copy of an object with a dynamic buffer?
// VFALCO TODO Remove this function and fix the few callers.
Serializer getSerializer () const
{
Serializer s;
add (s);
return s;
}
std::string getFullText () const;
std::string getText () const;
virtual Json::Value getJson (int options) const;
int addObject (const SerializedType & t)
{
mData.push_back (t.clone ().release ());
return mData.size () - 1;
}
int giveObject (std::unique_ptr<SerializedType> t)
{
mData.push_back (t.release ());
return mData.size () - 1;
}
int giveObject (SerializedType * t)
{
mData.push_back (t);
return mData.size () - 1;
}
const boost::ptr_vector<SerializedType>& peekData () const
{
return mData;
}
boost::ptr_vector<SerializedType>& 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 ();
}
bool setFlag (std::uint32_t);
bool clearFlag (std::uint32_t);
bool isFlag(std::uint32_t) const;
std::uint32_t getFlags () const;
uint256 getHash (std::uint32_t prefix) const;
uint256 getSigningHash (std::uint32_t 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 (SField::ref field) const;
SField::ref getFieldSType (int index) 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, bool createOkay = false);
// these throw if the field type doesn't match, or return default values if the
// field is optional but not present
std::string getFieldString (SField::ref field) const;
unsigned char getFieldU8 (SField::ref field) const;
std::uint16_t getFieldU16 (SField::ref field) const;
std::uint32_t getFieldU32 (SField::ref field) const;
std::uint64_t getFieldU64 (SField::ref field) const;
uint128 getFieldH128 (SField::ref field) const;
uint160 getFieldH160 (SField::ref field) const;
uint256 getFieldH256 (SField::ref field) const;
RippleAddress getFieldAccount (SField::ref field) const;
uint160 getFieldAccount160 (SField::ref field) const;
Blob getFieldVL (SField::ref field) const;
const STAmount& getFieldAmount (SField::ref field) const;
const STPathSet& getFieldPathSet (SField::ref field) const;
const STVector256& getFieldV256 (SField::ref field) const;
const STArray& getFieldArray (SField::ref field) const;
void setFieldU8 (SField::ref field, unsigned char);
void setFieldU16 (SField::ref field, std::uint16_t);
void setFieldU32 (SField::ref field, std::uint32_t);
void setFieldU64 (SField::ref field, std::uint64_t);
void setFieldH128 (SField::ref field, const uint128&);
void setFieldH160 (SField::ref field, const uint160&);
void setFieldH256 (SField::ref field, uint256 const& );
void setFieldVL (SField::ref field, Blob const&);
void setFieldAccount (SField::ref field, const uint160&);
void setFieldAccount (SField::ref field, const RippleAddress & addr)
{
setFieldAccount (field, addr.getAccountID ());
}
void setFieldAmount (SField::ref field, const STAmount&);
void setFieldPathSet (SField::ref field, const STPathSet&);
void setFieldV256 (SField::ref field, const STVector256 & v);
STObject& peekFieldObject (SField::ref 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::unique_ptr <SerializedType> makeDefaultObject (SerializedTypeID id, SField::ref name);
// VFALCO TODO remove the 'depth' parameter
static std::unique_ptr<SerializedType> makeDeserializedObject (
SerializedTypeID id,
SField::ref name,
SerializerIterator&,
int depth);
static std::unique_ptr<SerializedType> makeNonPresentObject (SField::ref name)
{
return makeDefaultObject (STI_NOTPRESENT, name);
}
static std::unique_ptr<SerializedType> makeDefaultObject (SField::ref name)
{
return makeDefaultObject (name.fieldType, name);
}
// field iterator stuff
typedef boost::ptr_vector<SerializedType>::iterator iterator;
typedef boost::ptr_vector<SerializedType>::const_iterator const_iterator;
iterator begin ()
{
return mData.begin ();
}
iterator end ()
{
return mData.end ();
}
const_iterator begin () const
{
return mData.begin ();
}
const_iterator end () const
{
return mData.end ();
}
bool empty () const
{
return mData.empty ();
}
bool hasMatchingEntry (const SerializedType&);
bool operator== (const STObject & o) const;
bool operator!= (const STObject & o) const
{
return ! (*this == o);
}
private:
/** Returns a value or throws if out of range.
This will throw if the source value cannot be represented
within the destination type.
*/
// VFALCO NOTE This won't work right
/*
template <class T, class U>
static T getWithRangeCheck (U v)
{
if (v < std::numeric_limits <T>::min ()) ||
v > std::numeric_limits <T>::max ())
{
throw std::runtime_error ("Value out of range");
}
return static_cast <T> (v);
}
*/
STObject* duplicate () const
{
return new STObject (*this);
}
private:
boost::ptr_vector<SerializedType> mData;
const SOTemplate* mType;
};
//------------------------------------------------------------------------------
// VFALCO TODO these parameters should not be const references.
template <typename T, typename U>
static T range_check_cast (const U& value, const T& minimum, const T& maximum)
{
if ((value < minimum) || (value > maximum))
throw std::runtime_error ("Value out of range");
return static_cast<T> (value);
}
inline STObject::iterator range_begin (STObject& x)
{
return x.begin ();
}
inline STObject::iterator range_end (STObject& x)
{
return x.end ();
}
//------------------------------------------------------------------------------
class STArray
: public SerializedType
, public CountedObject <STArray>
{
public:
static char const* getCountedObjectName () { return "STArray"; }
typedef boost::ptr_vector<STObject> vector;
typedef boost::ptr_vector<STObject>::iterator iterator;
typedef boost::ptr_vector<STObject>::const_iterator const_iterator;
typedef boost::ptr_vector<STObject>::reverse_iterator reverse_iterator;
typedef boost::ptr_vector<STObject>::const_reverse_iterator const_reverse_iterator;
typedef boost::ptr_vector<STObject>::size_type size_type;
public:
STArray ()
{
;
}
explicit STArray (int n)
{
value.reserve (n);
}
explicit STArray (SField::ref f) : SerializedType (f)
{
;
}
STArray (SField::ref f, int n) : SerializedType (f)
{
value.reserve (n);
}
STArray (SField::ref f, const vector & v) : SerializedType (f), value (v)
{
;
}
explicit STArray (vector & v) : value (v)
{
;
}
static std::unique_ptr<SerializedType> deserialize (SerializerIterator & sit, SField::ref name)
{
return std::unique_ptr<SerializedType> (construct (sit, name));
}
const vector& getValue () const
{
return value;
}
vector& getValue ()
{
return value;
}
// VFALCO NOTE as long as we're married to boost why not use boost::iterator_facade?
//
// vector-like functions
void push_back (const STObject & object)
{
value.push_back (object.oClone ().release ());
}
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);
}
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 ();
}
void swap (STArray & a)
{
value.swap (a.value);
}
virtual std::string getFullText () const;
virtual std::string getText () const;
virtual Json::Value getJson (int) const;
virtual void add (Serializer & s) const;
void sort (bool (*compare) (const STObject & o1, const STObject & o2));
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;
virtual bool isDefault () const
{
return value.empty ();
}
private:
vector value;
STArray* duplicate () const
{
return new STArray (*this);
}
static STArray* construct (SerializerIterator&, SField::ref);
};
inline STArray::iterator range_begin (STArray& x)
{
return x.begin ();
}
inline STArray::iterator range_end (STArray& x)
{
return x.end ();
}
} // ripple
#endif

View File

@@ -0,0 +1,64 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
SOTemplate::SOTemplate ()
{
}
void SOTemplate::push_back (SOElement const& r)
{
// Ensure there is the enough space in the index mapping
// table for all possible fields.
//
if (mIndex.empty ())
{
// Unmapped indices will be set to -1
//
mIndex.resize (SField::getNumFields () + 1, -1);
}
// Make sure the field's index is in range
//
assert (r.e_field.getNum () < mIndex.size ());
// Make sure that this field hasn't already been assigned
//
assert (getIndex (r.e_field) == -1);
// Add the field to the index mapping table
//
mIndex [r.e_field.getNum ()] = mTypes.size ();
// Append the new element.
//
mTypes.push_back (value_type (new SOElement (r)));
}
int SOTemplate::getIndex (SField::ref f) const
{
// The mapping table should be large enough for any possible field
//
assert (f.getNum () < mIndex.size ());
return mIndex[f.getNum ()];
}
} // ripple

View File

@@ -0,0 +1,94 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_SERIALIZEDOBJECTTEMPLATE_H
#define RIPPLE_SERIALIZEDOBJECTTEMPLATE_H
namespace ripple {
/** Flags for elements in a SerializedObjectTemplate.
*/
// VFALCO NOTE these don't look like bit-flags...
enum SOE_Flags
{
SOE_INVALID = -1,
SOE_REQUIRED = 0, // required
SOE_OPTIONAL = 1, // optional, may be present with default value
SOE_DEFAULT = 2, // optional, if present, must not have default value
};
//------------------------------------------------------------------------------
/** An element in a SerializedObjectTemplate.
*/
class SOElement
{
public:
SField::ref e_field;
SOE_Flags const flags;
SOElement (SField::ref fieldName, SOE_Flags flags)
: e_field (fieldName)
, flags (flags)
{
}
};
//------------------------------------------------------------------------------
/** Defines the fields and their attributes within a SerializedObject.
Each subclass of SerializedObject will provide its own template
describing the available fields and their metadata attributes.
*/
class SOTemplate
{
public:
typedef std::unique_ptr <SOElement const> value_type;
typedef std::vector <value_type> list_type;
/** Create an empty template.
After creating the template, call @ref push_back with the
desired fields.
@see push_back
*/
SOTemplate ();
// VFALCO NOTE Why do we even bother with the 'private' keyword if
// this function is present?
//
list_type const& peek () const
{
return mTypes;
}
/** Add an element to the template. */
void push_back (SOElement const& r);
/** Retrieve the position of a named field. */
int getIndex (SField::ref) const;
private:
list_type mTypes;
std::vector <int> mIndex; // field num -> index
};
} // ripple
#endif

View File

@@ -0,0 +1,625 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
SETUP_LOG (SerializedType)
const STAmount saZero (CURRENCY_ONE, ACCOUNT_ONE, 0);
const STAmount saOne (CURRENCY_ONE, ACCOUNT_ONE, 1);
SerializedType& SerializedType::operator= (const SerializedType& t)
{
if ((t.fName != fName) && fName->isUseful () && t.fName->isUseful ())
{
WriteLog ((t.getSType () == STI_AMOUNT) ? lsTRACE : lsWARNING, SerializedType) // This is common for amounts
<< "Caution: " << t.fName->getName () << " not replacing " << fName->getName ();
}
if (!fName->isUseful ()) fName = t.fName;
return *this;
}
bool SerializedType::isEquivalent (const SerializedType& t) const
{
assert (getSType () == STI_NOTPRESENT);
if (t.getSType () == STI_NOTPRESENT)
return true;
WriteLog (lsDEBUG, SerializedType) << "notEquiv " << getFullText() << " not STI_NOTPRESENT";
return false;
}
void STPathSet::printDebug ()
{
// VFALCO NOTE Can't use Log::out() because of std::endl
//
for (int i = 0; i < value.size (); i++)
{
std::cerr << i << ": ";
for (int j = 0; j < value[i].mPath.size (); j++)
{
//STPathElement pe = value[i].mPath[j];
RippleAddress nad;
nad.setAccountID (value[i].mPath[j].mAccountID);
std::cerr << " " << nad.humanAccountID ();
//std::cerr << " " << pe.mAccountID.GetHex();
}
std::cerr << std::endl;
}
}
void STPath::printDebug ()
{
Log::out() << "STPath:";
for (int i = 0; i < mPath.size (); i++)
{
RippleAddress nad;
nad.setAccountID (mPath[i].mAccountID);
Log::out() << " " << i << ": " << nad.humanAccountID ();
}
}
std::string SerializedType::getFullText () const
{
std::string ret;
if (getSType () != STI_NOTPRESENT)
{
if (fName->hasName ())
{
ret = fName->fieldName;
ret += " = ";
}
ret += getText ();
}
return ret;
}
STUInt8* STUInt8::construct (SerializerIterator& u, SField::ref name)
{
return new STUInt8 (name, u.get8 ());
}
std::string STUInt8::getText () const
{
if (getFName () == sfTransactionResult)
{
std::string token, human;
if (transResultInfo (static_cast<TER> (value), token, human))
return human;
}
return beast::lexicalCastThrow <std::string> (value);
}
Json::Value STUInt8::getJson (int) const
{
if (getFName () == sfTransactionResult)
{
std::string token, human;
if (transResultInfo (static_cast<TER> (value), token, human))
return token;
else
WriteLog (lsWARNING, SerializedType) << "Unknown result code in metadata: " << value;
}
return value;
}
bool STUInt8::isEquivalent (const SerializedType& t) const
{
const STUInt8* v = dynamic_cast<const STUInt8*> (&t);
return v && (value == v->value);
}
STUInt16* STUInt16::construct (SerializerIterator& u, SField::ref name)
{
return new STUInt16 (name, u.get16 ());
}
std::string STUInt16::getText () const
{
if (getFName () == sfLedgerEntryType)
{
LedgerFormats::Item const* const item =
LedgerFormats::getInstance ()->findByType (static_cast <LedgerEntryType> (value));
if (item != nullptr)
return item->getName ();
}
if (getFName () == sfTransactionType)
{
TxFormats::Item const* const item =
TxFormats::getInstance()->findByType (static_cast <TxType> (value));
if (item != nullptr)
return item->getName ();
}
return beast::lexicalCastThrow <std::string> (value);
}
Json::Value STUInt16::getJson (int) const
{
if (getFName () == sfLedgerEntryType)
{
LedgerFormats::Item const* const item =
LedgerFormats::getInstance ()->findByType (static_cast <LedgerEntryType> (value));
if (item != nullptr)
return item->getName ();
}
if (getFName () == sfTransactionType)
{
TxFormats::Item const* const item =
TxFormats::getInstance()->findByType (static_cast <TxType> (value));
if (item != nullptr)
return item->getName ();
}
return value;
}
bool STUInt16::isEquivalent (const SerializedType& t) const
{
const STUInt16* v = dynamic_cast<const STUInt16*> (&t);
return v && (value == v->value);
}
STUInt32* STUInt32::construct (SerializerIterator& u, SField::ref name)
{
return new STUInt32 (name, u.get32 ());
}
std::string STUInt32::getText () const
{
return beast::lexicalCastThrow <std::string> (value);
}
Json::Value STUInt32::getJson (int) const
{
return value;
}
bool STUInt32::isEquivalent (const SerializedType& t) const
{
const STUInt32* v = dynamic_cast<const STUInt32*> (&t);
return v && (value == v->value);
}
STUInt64* STUInt64::construct (SerializerIterator& u, SField::ref name)
{
return new STUInt64 (name, u.get64 ());
}
std::string STUInt64::getText () const
{
return beast::lexicalCastThrow <std::string> (value);
}
Json::Value STUInt64::getJson (int) const
{
return strHex (value);
}
bool STUInt64::isEquivalent (const SerializedType& t) const
{
const STUInt64* v = dynamic_cast<const STUInt64*> (&t);
return v && (value == v->value);
}
STHash128* STHash128::construct (SerializerIterator& u, SField::ref name)
{
return new STHash128 (name, u.get128 ());
}
std::string STHash128::getText () const
{
return to_string (value);
}
bool STHash128::isEquivalent (const SerializedType& t) const
{
const STHash128* v = dynamic_cast<const STHash128*> (&t);
return v && (value == v->value);
}
STHash160* STHash160::construct (SerializerIterator& u, SField::ref name)
{
return new STHash160 (name, u.get160 ());
}
std::string STHash160::getText () const
{
return to_string (value);
}
bool STHash160::isEquivalent (const SerializedType& t) const
{
const STHash160* v = dynamic_cast<const STHash160*> (&t);
return v && (value == v->value);
}
STHash256* STHash256::construct (SerializerIterator& u, SField::ref name)
{
return new STHash256 (name, u.get256 ());
}
std::string STHash256::getText () const
{
return to_string (value);
}
bool STHash256::isEquivalent (const SerializedType& t) const
{
const STHash256* v = dynamic_cast<const STHash256*> (&t);
return v && (value == v->value);
}
STVariableLength::STVariableLength (SerializerIterator& st, SField::ref name) : SerializedType (name)
{
value = st.getVL ();
}
std::string STVariableLength::getText () const
{
return strHex (value);
}
STVariableLength* STVariableLength::construct (SerializerIterator& u, SField::ref name)
{
return new STVariableLength (name, u.getVL ());
}
bool STVariableLength::isEquivalent (const SerializedType& t) const
{
const STVariableLength* v = dynamic_cast<const STVariableLength*> (&t);
return v && (value == v->value);
}
std::string STAccount::getText () const
{
uint160 u;
RippleAddress a;
if (!getValueH160 (u))
return STVariableLength::getText ();
a.setAccountID (u);
return a.humanAccountID ();
}
STAccount* STAccount::construct (SerializerIterator& u, SField::ref name)
{
return new STAccount (name, u.getVL ());
}
//
// STVector256
//
// Return a new object from a SerializerIterator.
STVector256* STVector256::construct (SerializerIterator& u, SField::ref name)
{
Blob data = u.getVL ();
Blob ::iterator begin = data.begin ();
std::unique_ptr<STVector256> vec (new STVector256 (name));
int count = data.size () / (256 / 8);
vec->mValue.reserve (count);
unsigned int uStart = 0;
for (unsigned int i = 0; i != count; i++)
{
unsigned int uEnd = uStart + (256 / 8);
// This next line could be optimized to construct a default uint256 in the vector and then copy into it
vec->mValue.push_back (uint256 (Blob (begin + uStart, begin + uEnd)));
uStart = uEnd;
}
return vec.release ();
}
void STVector256::add (Serializer& s) const
{
s.addVL (mValue.empty () ? nullptr : mValue[0].begin (), mValue.size () * (256 / 8));
}
bool STVector256::isEquivalent (const SerializedType& t) const
{
const STVector256* v = dynamic_cast<const STVector256*> (&t);
return v && (mValue == v->mValue);
}
bool STVector256::hasValue (uint256 const& v) const
{
BOOST_FOREACH (uint256 const & hash, mValue)
{
if (hash == v)
return true;
}
return false;
}
//
// STAccount
//
STAccount::STAccount (SField::ref n, const uint160& v) : STVariableLength (n)
{
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
}
bool STAccount::isValueH160 () const
{
return peekValue ().size () == (160 / 8);
}
void STAccount::setValueH160 (const uint160& v)
{
peekValue ().clear ();
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
assert (peekValue ().size () == (160 / 8));
}
bool STAccount::getValueH160 (uint160& v) const
{
if (!isValueH160 ()) return false;
memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
return true;
}
RippleAddress STAccount::getValueNCA () const
{
RippleAddress a;
uint160 v;
if (getValueH160 (v))
a.setAccountID (v);
return a;
}
void STAccount::setValueNCA (const RippleAddress& nca)
{
setValueH160 (nca.getAccountID ());
}
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
{
std::vector<STPath> paths;
std::vector<STPathElement> path;
do
{
int iType = s.get8 ();
if (iType == STPathElement::typeEnd || iType == STPathElement::typeBoundary)
{
if (path.empty ())
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Empty path.";
throw std::runtime_error ("empty path");
}
paths.push_back (path);
path.clear ();
if (iType == STPathElement::typeEnd)
{
return new STPathSet (name, paths);
}
}
else if (iType & ~STPathElement::typeValidBits)
{
WriteLog (lsINFO, SerializedType) << "STPathSet: Bad path element: " << iType;
throw std::runtime_error ("bad path element");
}
else
{
const bool bAccount = !! (iType & STPathElement::typeAccount);
const bool bCurrency = !! (iType & STPathElement::typeCurrency);
const bool bIssuer = !! (iType & STPathElement::typeIssuer);
uint160 uAccountID;
uint160 uCurrency;
uint160 uIssuerID;
if (bAccount)
uAccountID = s.get160 ();
if (bCurrency)
uCurrency = s.get160 ();
if (bIssuer)
uIssuerID = s.get160 ();
path.push_back (STPathElement (uAccountID, uCurrency, uIssuerID, bCurrency));
}
}
while (1);
}
bool STPathSet::isEquivalent (const SerializedType& t) const
{
const STPathSet* v = dynamic_cast<const STPathSet*> (&t);
return v && (value == v->value);
}
bool STPath::hasSeen (const uint160& uAccountId, const uint160& uCurrencyID, const uint160& uIssuerID) const
{
for (int i = 0; i < mPath.size (); ++i)
{
const STPathElement& ele = getElement (i);
if (ele.getAccountID () == uAccountId
&& ele.getCurrency () == uCurrencyID
&& ele.getIssuerID () == uIssuerID)
return true;
}
return false;
}
Json::Value STPath::getJson (int) const
{
Json::Value ret (Json::arrayValue);
BOOST_FOREACH (std::vector<STPathElement>::const_iterator::value_type it, mPath)
{
Json::Value elem (Json::objectValue);
int iType = it.getNodeType ();
elem[jss::type] = iType;
elem[jss::type_hex] = strHex (iType);
if (iType & STPathElement::typeAccount)
elem[jss::account] = RippleAddress::createHumanAccountID (it.getAccountID ());
if (iType & STPathElement::typeCurrency)
elem[jss::currency] = STAmount::createHumanCurrency (it.getCurrency ());
if (iType & STPathElement::typeIssuer)
elem[jss::issuer] = RippleAddress::createHumanAccountID (it.getIssuerID ());
ret.append (elem);
}
return ret;
}
Json::Value STPathSet::getJson (int options) const
{
Json::Value ret (Json::arrayValue);
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
ret.append (it.getJson (options));
return ret;
}
#if 0
std::string STPath::getText () const
{
std::string ret ("[");
bool first = true;
BOOST_FOREACH (const STPathElement & it, mPath)
{
if (!first) ret += ", ";
switch (it.getNodeType ())
{
case STPathElement::typeAccount:
{
ret += RippleAddress::createHumanAccountID (it.getNode ());
break;
}
case STPathElement::typeOffer:
{
ret += "Offer(";
ret += it.getNode ().GetHex ();
ret += ")";
break;
}
default:
throw std::runtime_error ("Unknown path element");
}
first = false;
}
return ret + "]";
}
#endif
#if 0
std::string STPathSet::getText () const
{
std::string ret ("{");
bool firstPath = true;
BOOST_FOREACH (std::vector<STPath>::const_iterator::value_type it, value)
{
if (!firstPath)
{
ret += ", ";
firstPath = false;
}
ret += it.getText ();
}
return ret + "}";
}
#endif
void STPathSet::add (Serializer& s) const
{
bool bFirst = true;
BOOST_FOREACH (const STPath & spPath, value)
{
if (!bFirst)
{
s.add8 (STPathElement::typeBoundary);
}
BOOST_FOREACH (const STPathElement & speElement, spPath)
{
int iType = speElement.getNodeType ();
s.add8 (iType);
if (iType & STPathElement::typeAccount)
s.add160 (speElement.getAccountID ());
if (iType & STPathElement::typeCurrency)
s.add160 (speElement.getCurrency ());
if (iType & STPathElement::typeIssuer)
s.add160 (speElement.getIssuerID ());
}
bFirst = false;
}
s.add8 (STPathElement::typeEnd);
}
} // ripple

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,710 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <beast/unit_test/suite.h>
namespace ripple {
SETUP_LOG (Serializer)
int Serializer::addZeros (size_t uBytes)
{
int ret = mData.size ();
while (uBytes--)
mData.push_back (0);
return ret;
}
int Serializer::add16 (std::uint16_t i)
{
int ret = mData.size ();
mData.push_back (static_cast<unsigned char> (i >> 8));
mData.push_back (static_cast<unsigned char> (i & 0xff));
return ret;
}
int Serializer::add32 (std::uint32_t i)
{
int ret = mData.size ();
mData.push_back (static_cast<unsigned char> (i >> 24));
mData.push_back (static_cast<unsigned char> ((i >> 16) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 8) & 0xff));
mData.push_back (static_cast<unsigned char> (i & 0xff));
return ret;
}
int Serializer::add64 (std::uint64_t i)
{
int ret = mData.size ();
mData.push_back (static_cast<unsigned char> (i >> 56));
mData.push_back (static_cast<unsigned char> ((i >> 48) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 40) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 32) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 24) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 16) & 0xff));
mData.push_back (static_cast<unsigned char> ((i >> 8) & 0xff));
mData.push_back (static_cast<unsigned char> (i & 0xff));
return ret;
}
int Serializer::add128 (const uint128& i)
{
int ret = mData.size ();
mData.insert (mData.end (), i.begin (), i.end ());
return ret;
}
int Serializer::add160 (const uint160& i)
{
int ret = mData.size ();
mData.insert (mData.end (), i.begin (), i.end ());
return ret;
}
int Serializer::add256 (uint256 const& i)
{
int ret = mData.size ();
mData.insert (mData.end (), i.begin (), i.end ());
return ret;
}
int Serializer::addRaw (Blob const& vector)
{
int ret = mData.size ();
mData.insert (mData.end (), vector.begin (), vector.end ());
return ret;
}
int Serializer::addRaw (const Serializer& s)
{
int ret = mData.size ();
mData.insert (mData.end (), s.begin (), s.end ());
return ret;
}
int Serializer::addRaw (const void* ptr, int len)
{
int ret = mData.size ();
mData.insert (mData.end (), (const char*) ptr, ((const char*)ptr) + len);
return ret;
}
bool Serializer::get16 (std::uint16_t& o, int offset) const
{
if ((offset + 2) > mData.size ()) return false;
const unsigned char* ptr = &mData[offset];
o = *ptr++;
o <<= 8;
o |= *ptr;
return true;
}
bool Serializer::get32 (std::uint32_t& o, int offset) const
{
if ((offset + 4) > mData.size ()) return false;
const unsigned char* ptr = &mData[offset];
o = *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr;
return true;
}
bool Serializer::get64 (std::uint64_t& o, int offset) const
{
if ((offset + 8) > mData.size ()) return false;
const unsigned char* ptr = &mData[offset];
o = *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr++;
o <<= 8;
o |= *ptr;
return true;
}
bool Serializer::get128 (uint128& o, int offset) const
{
if ((offset + (128 / 8)) > mData.size ()) return false;
memcpy (o.begin (), & (mData.front ()) + offset, (128 / 8));
return true;
}
bool Serializer::get160 (uint160& o, int offset) const
{
if ((offset + (160 / 8)) > mData.size ()) return false;
memcpy (o.begin (), & (mData.front ()) + offset, (160 / 8));
return true;
}
bool Serializer::get256 (uint256& o, int offset) const
{
if ((offset + (256 / 8)) > mData.size ()) return false;
memcpy (o.begin (), & (mData.front ()) + offset, (256 / 8));
return true;
}
uint256 Serializer::get256 (int offset) const
{
uint256 ret;
if ((offset + (256 / 8)) > mData.size ()) return ret;
memcpy (ret.begin (), & (mData.front ()) + offset, (256 / 8));
return ret;
}
int Serializer::addFieldID (int type, int name)
{
int ret = mData.size ();
assert ((type > 0) && (type < 256) && (name > 0) && (name < 256));
if (type < 16)
{
if (name < 16) // common type, common name
mData.push_back (static_cast<unsigned char> ((type << 4) | name));
else
{
// common type, uncommon name
mData.push_back (static_cast<unsigned char> (type << 4));
mData.push_back (static_cast<unsigned char> (name));
}
}
else if (name < 16)
{
// uncommon type, common name
mData.push_back (static_cast<unsigned char> (name));
mData.push_back (static_cast<unsigned char> (type));
}
else
{
// uncommon type, uncommon name
mData.push_back (static_cast<unsigned char> (0));
mData.push_back (static_cast<unsigned char> (type));
mData.push_back (static_cast<unsigned char> (name));
}
return ret;
}
bool Serializer::getFieldID (int& type, int& name, int offset) const
{
if (!get8 (type, offset))
{
WriteLog (lsWARNING, Serializer) << "gFID: unable to get type";
return false;
}
name = type & 15;
type >>= 4;
if (type == 0)
{
// uncommon type
if (!get8 (type, ++offset))
return false;
if ((type == 0) || (type < 16))
{
WriteLog (lsWARNING, Serializer) << "gFID: uncommon type out of range " << type;
return false;
}
}
if (name == 0)
{
// uncommon name
if (!get8 (name, ++offset))
return false;
if ((name == 0) || (name < 16))
{
WriteLog (lsWARNING, Serializer) << "gFID: uncommon name out of range " << name;
return false;
}
}
return true;
}
int Serializer::add8 (unsigned char byte)
{
int ret = mData.size ();
mData.push_back (byte);
return ret;
}
bool Serializer::get8 (int& byte, int offset) const
{
if (offset >= mData.size ()) return false;
byte = mData[offset];
return true;
}
bool Serializer::chop (int bytes)
{
if (bytes > mData.size ()) return false;
mData.resize (mData.size () - bytes);
return true;
}
int Serializer::removeLastByte ()
{
int size = mData.size () - 1;
if (size < 0)
{
assert (false);
return -1;
}
int ret = mData[size];
mData.resize (size);
return ret;
}
bool Serializer::getRaw (Blob& o, int offset, int length) const
{
if ((offset + length) > mData.size ()) return false;
o.assign (mData.begin () + offset, mData.begin () + offset + length);
return true;
}
Blob Serializer::getRaw (int offset, int length) const
{
Blob o;
if ((offset + length) > mData.size ()) return o;
o.assign (mData.begin () + offset, mData.begin () + offset + length);
return o;
}
uint160 Serializer::getRIPEMD160 (int size) const
{
uint160 ret;
if ((size < 0) || (size > mData.size ())) size = mData.size ();
RIPEMD160 (& (mData.front ()), size, (unsigned char*) &ret);
return ret;
}
uint256 Serializer::getSHA256 (int size) const
{
uint256 ret;
if ((size < 0) || (size > mData.size ())) size = mData.size ();
SHA256 (& (mData.front ()), size, (unsigned char*) &ret);
return ret;
}
uint256 Serializer::getSHA512Half (int size) const
{
assert (size != 0);
if (size == 0)
return uint256();
if (size < 0 || size > mData.size())
return getSHA512Half (mData);
return getSHA512Half (const_byte_view (
mData.data(), mData.data() + size));
}
uint256 Serializer::getSHA512Half (const_byte_view v)
{
uint256 j[2];
SHA512 (v.data(), v.size(),
reinterpret_cast<unsigned char*> (j));
return j[0];
}
uint256 Serializer::getSHA512Half (const unsigned char* data, int len)
{
uint256 j[2];
SHA512 (data, len, (unsigned char*) j);
return j[0];
}
uint256 Serializer::getPrefixHash (std::uint32_t prefix, const unsigned char* data, int len)
{
char be_prefix[4];
be_prefix[0] = static_cast<unsigned char> (prefix >> 24);
be_prefix[1] = static_cast<unsigned char> ((prefix >> 16) & 0xff);
be_prefix[2] = static_cast<unsigned char> ((prefix >> 8) & 0xff);
be_prefix[3] = static_cast<unsigned char> (prefix & 0xff);
uint256 j[2];
SHA512_CTX ctx;
SHA512_Init (&ctx);
SHA512_Update (&ctx, &be_prefix[0], 4);
SHA512_Update (&ctx, data, len);
SHA512_Final (reinterpret_cast<unsigned char*> (&j[0]), &ctx);
return j[0];
}
int Serializer::addVL (Blob const& vector)
{
int ret = addRaw (encodeVL (vector.size ()));
addRaw (vector);
assert (mData.size () == (ret + vector.size () + encodeLengthLength (vector.size ())));
return ret;
}
int Serializer::addVL (const void* ptr, int len)
{
int ret = addRaw (encodeVL (len));
if (len)
addRaw (ptr, len);
return ret;
}
int Serializer::addVL (const std::string& string)
{
int ret = addRaw (string.size ());
if (!string.empty ())
addRaw (string.data (), string.size ());
return ret;
}
bool Serializer::getVL (Blob& objectVL, int offset, int& length) const
{
int b1;
if (!get8 (b1, offset++)) return false;
int datLen, lenLen = decodeLengthLength (b1);
try
{
if (lenLen == 1)
datLen = decodeVLLength (b1);
else if (lenLen == 2)
{
int b2;
if (!get8 (b2, offset++)) return false;
datLen = decodeVLLength (b1, b2);
}
else if (lenLen == 3)
{
int b2, b3;
if (!get8 (b2, offset++)) return false;
if (!get8 (b3, offset++)) return false;
datLen = decodeVLLength (b1, b2, b3);
}
else return false;
}
catch (...)
{
return false;
}
length = lenLen + datLen;
return getRaw (objectVL, offset, datLen);
}
bool Serializer::getVLLength (int& length, int offset) const
{
int b1;
if (!get8 (b1, offset++)) return false;
int lenLen = decodeLengthLength (b1);
try
{
if (lenLen == 1)
length = decodeVLLength (b1);
else if (lenLen == 2)
{
int b2;
if (!get8 (b2, offset++)) return false;
length = decodeVLLength (b1, b2);
}
else if (lenLen == 3)
{
int b2, b3;
if (!get8 (b2, offset++)) return false;
if (!get8 (b3, offset++)) return false;
length = decodeVLLength (b1, b2, b3);
}
else return false;
}
catch (...)
{
return false;
}
return true;
}
Blob Serializer::encodeVL (int length)
{
unsigned char lenBytes[4];
if (length <= 192)
{
lenBytes[0] = static_cast<unsigned char> (length);
return Blob (&lenBytes[0], &lenBytes[1]);
}
else if (length <= 12480)
{
length -= 193;
lenBytes[0] = 193 + static_cast<unsigned char> (length >> 8);
lenBytes[1] = static_cast<unsigned char> (length & 0xff);
return Blob (&lenBytes[0], &lenBytes[2]);
}
else if (length <= 918744)
{
length -= 12481;
lenBytes[0] = 241 + static_cast<unsigned char> (length >> 16);
lenBytes[1] = static_cast<unsigned char> ((length >> 8) & 0xff);
lenBytes[2] = static_cast<unsigned char> (length & 0xff);
return Blob (&lenBytes[0], &lenBytes[3]);
}
else throw std::overflow_error ("lenlen");
}
int Serializer::encodeLengthLength (int length)
{
if (length < 0) throw std::overflow_error ("len<0");
if (length <= 192) return 1;
if (length <= 12480) return 2;
if (length <= 918744) return 3;
throw std::overflow_error ("len>918744");
}
int Serializer::decodeLengthLength (int b1)
{
if (b1 < 0) throw std::overflow_error ("b1<0");
if (b1 <= 192) return 1;
if (b1 <= 240) return 2;
if (b1 <= 254) return 3;
throw std::overflow_error ("b1>254");
}
int Serializer::decodeVLLength (int b1)
{
if (b1 < 0) throw std::overflow_error ("b1<0");
if (b1 > 254) throw std::overflow_error ("b1>254");
return b1;
}
int Serializer::decodeVLLength (int b1, int b2)
{
if (b1 < 193) throw std::overflow_error ("b1<193");
if (b1 > 240) throw std::overflow_error ("b1>240");
return 193 + (b1 - 193) * 256 + b2;
}
int Serializer::decodeVLLength (int b1, int b2, int b3)
{
if (b1 < 241) throw std::overflow_error ("b1<241");
if (b1 > 254) throw std::overflow_error ("b1>254");
return 12481 + (b1 - 241) * 65536 + b2 * 256 + b3;
}
void Serializer::TestSerializer ()
{
Serializer s (64);
}
int SerializerIterator::getBytesLeft ()
{
return mSerializer.size () - mPos;
}
void SerializerIterator::getFieldID (int& type, int& field)
{
if (!mSerializer.getFieldID (type, field, mPos))
throw std::runtime_error ("invalid serializer getFieldID");
++mPos;
if (type >= 16)
++mPos;
if (field >= 16)
++mPos;
}
unsigned char SerializerIterator::get8 ()
{
int val;
if (!mSerializer.get8 (val, mPos)) throw std::runtime_error ("invalid serializer get8");
++mPos;
return val;
}
std::uint16_t SerializerIterator::get16 ()
{
std::uint16_t val;
if (!mSerializer.get16 (val, mPos)) throw std::runtime_error ("invalid serializer get16");
mPos += 16 / 8;
return val;
}
std::uint32_t SerializerIterator::get32 ()
{
std::uint32_t val;
if (!mSerializer.get32 (val, mPos)) throw std::runtime_error ("invalid serializer get32");
mPos += 32 / 8;
return val;
}
std::uint64_t SerializerIterator::get64 ()
{
std::uint64_t val;
if (!mSerializer.get64 (val, mPos)) throw std::runtime_error ("invalid serializer get64");
mPos += 64 / 8;
return val;
}
uint128 SerializerIterator::get128 ()
{
uint128 val;
if (!mSerializer.get128 (val, mPos)) throw std::runtime_error ("invalid serializer get128");
mPos += 128 / 8;
return val;
}
uint160 SerializerIterator::get160 ()
{
uint160 val;
if (!mSerializer.get160 (val, mPos)) throw std::runtime_error ("invalid serializer get160");
mPos += 160 / 8;
return val;
}
uint256 SerializerIterator::get256 ()
{
uint256 val;
if (!mSerializer.get256 (val, mPos)) throw std::runtime_error ("invalid serializer get256");
mPos += 256 / 8;
return val;
}
Blob SerializerIterator::getVL ()
{
int length;
Blob vl;
if (!mSerializer.getVL (vl, mPos, length)) throw std::runtime_error ("invalid serializer getVL");
mPos += length;
return vl;
}
Blob SerializerIterator::getRaw (int iLength)
{
int iPos = mPos;
mPos += iLength;
return mSerializer.getRaw (iPos, iLength);
}
//------------------------------------------------------------------------------
class Serializer_test : public beast::unit_test::suite
{
public:
void run ()
{
Serializer s1;
s1.add32 (3);
s1.add256 (uint256 ());
Serializer s2;
s2.add32 (0x12345600);
s2.addRaw (s1.peekData ());
expect (s1.getPrefixHash (0x12345600) == s2.getSHA512Half ());
}
};
BEAST_DEFINE_TESTSUITE(Serializer,ripple_data,ripple);
} // ripple

View File

@@ -0,0 +1,310 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_SERIALIZER_H
#define RIPPLE_SERIALIZER_H
#include <ripple/common/byte_view.h>
namespace ripple {
class CKey; // forward declaration
class Serializer
{
public:
typedef boost::shared_ptr<Serializer> pointer;
protected:
Blob mData;
public:
Serializer (int n = 256)
{
mData.reserve (n);
}
Serializer (Blob const& data) : mData (data)
{
;
}
Serializer (const std::string& data) : mData (data.data (), (data.data ()) + data.size ())
{
;
}
Serializer (Blob ::iterator begin, Blob ::iterator end) :
mData (begin, end)
{
;
}
Serializer (Blob ::const_iterator begin, Blob ::const_iterator end) :
mData (begin, end)
{
;
}
// assemble functions
int add8 (unsigned char byte);
int add16 (std::uint16_t);
int add32 (std::uint32_t); // ledger indexes, account sequence, timestamps
int add64 (std::uint64_t); // native currency amounts
int add128 (const uint128&); // private key generators
int add160 (const uint160&); // account names, hankos
int add256 (uint256 const& ); // transaction and ledger hashes
int addRaw (Blob const& vector);
int addRaw (const void* ptr, int len);
int addRaw (const Serializer& s);
int addZeros (size_t uBytes);
int addVL (Blob const& vector);
int addVL (const std::string& string);
int addVL (const void* ptr, int len);
// disassemble functions
bool get8 (int&, int offset) const;
bool get8 (unsigned char&, int offset) const;
bool get16 (std::uint16_t&, int offset) const;
bool get32 (std::uint32_t&, int offset) const;
bool get64 (std::uint64_t&, int offset) const;
bool get128 (uint128&, int offset) const;
bool get160 (uint160&, int offset) const;
bool get256 (uint256&, int offset) const;
uint256 get256 (int offset) const;
bool getRaw (Blob&, int offset, int length) const;
Blob getRaw (int offset, int length) const;
bool getVL (Blob& objectVL, int offset, int& length) const;
bool getVLLength (int& length, int offset) const;
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<int> (type), name);
}
// normal hash functions
uint160 getRIPEMD160 (int size = -1) const;
uint256 getSHA256 (int size = -1) const;
uint256 getSHA512Half (int size = -1) const;
static uint256 getSHA512Half (const_byte_view v);
static uint256 getSHA512Half (const unsigned char* data, int len);
// prefix hash functions
static uint256 getPrefixHash (std::uint32_t prefix, const unsigned char* data, int len);
uint256 getPrefixHash (std::uint32_t prefix) const
{
return getPrefixHash (prefix, & (mData.front ()), mData.size ());
}
static uint256 getPrefixHash (std::uint32_t prefix, Blob const& data)
{
return getPrefixHash (prefix, & (data.front ()), data.size ());
}
static uint256 getPrefixHash (std::uint32_t prefix, const std::string& strData)
{
return getPrefixHash (prefix, reinterpret_cast<const unsigned char*> (strData.data ()), strData.size ());
}
// totality functions
Blob const& peekData () const
{
return mData;
}
Blob getData () const
{
return mData;
}
Blob& modData ()
{
return mData;
}
int getCapacity () const
{
return mData.capacity ();
}
int getDataLength () const
{
return mData.size ();
}
const void* getDataPtr () const
{
return &mData.front ();
}
void* getDataPtr ()
{
return &mData.front ();
}
int getLength () const
{
return mData.size ();
}
std::string getString () const
{
return std::string (static_cast<const char*> (getDataPtr ()), size ());
}
void secureErase ()
{
memset (& (mData.front ()), 0, mData.size ());
erase ();
}
void erase ()
{
mData.clear ();
}
int removeLastByte ();
bool chop (int num);
// vector-like functions
Blob ::iterator begin ()
{
return mData.begin ();
}
Blob ::iterator end ()
{
return mData.end ();
}
Blob ::const_iterator begin () const
{
return mData.begin ();
}
Blob ::const_iterator end () const
{
return mData.end ();
}
Blob ::size_type size () const
{
return mData.size ();
}
void reserve (size_t n)
{
mData.reserve (n);
}
void resize (size_t n)
{
mData.resize (n);
}
size_t capacity () const
{
return mData.capacity ();
}
bool operator== (Blob const& v)
{
return v == mData;
}
bool operator!= (Blob const& v)
{
return v != mData;
}
bool operator== (const Serializer& v)
{
return v.mData == mData;
}
bool operator!= (const Serializer& v)
{
return v.mData != mData;
}
std::string getHex () const
{
std::stringstream h;
for (unsigned char const& element : mData)
{
h <<
std::setw (2) <<
std::hex <<
std::setfill ('0') <<
static_cast<unsigned int>(element);
}
return h.str ();
}
// low-level VL length encode/decode functions
static Blob encodeVL (int length);
static int lengthVL (int length)
{
return length + encodeLengthLength (length);
}
static int encodeLengthLength (int length); // length to encode length
static int decodeLengthLength (int b1);
static int decodeVLLength (int b1);
static int decodeVLLength (int b1, int b2);
static int decodeVLLength (int b1, int b2, int b3);
static void TestSerializer ();
};
class SerializerIterator
{
protected:
const Serializer& mSerializer;
int mPos;
public:
// Reference is not const because we don't want to bind to a temporary
SerializerIterator (Serializer& s) : mSerializer (s), mPos (0)
{
;
}
const Serializer& operator* (void)
{
return mSerializer;
}
void reset (void)
{
mPos = 0;
}
void setPos (int p)
{
mPos = p;
}
int getPos (void)
{
return mPos;
}
bool empty ()
{
return mPos == mSerializer.getLength ();
}
int getBytesLeft ();
// get functions throw on error
unsigned char get8 ();
std::uint16_t get16 ();
std::uint32_t get32 ();
std::uint64_t get64 ();
uint128 get128 ();
uint160 get160 ();
uint256 get256 ();
void getFieldID (int& type, int& field);
Blob getRaw (int iLength);
Blob getVL ();
};
} // ripple
#endif

View File

@@ -0,0 +1,156 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman)
{
static struct
{
TER terCode;
const char* cpToken;
const char* cpHuman;
} transResultInfoA[] =
{
{ tecCLAIM, "tecCLAIM", "Fee claimed. Sequence used. No action." },
{ tecDIR_FULL, "tecDIR_FULL", "Can not add entry to full directory." },
{ tecFAILED_PROCESSING, "tecFAILED_PROCESSING", "Failed to correctly process transaction." },
{ tecINSUF_RESERVE_LINE, "tecINSUF_RESERVE_LINE", "Insufficient reserve to add trust line." },
{ tecINSUF_RESERVE_OFFER, "tecINSUF_RESERVE_OFFER", "Insufficient reserve to create offer." },
{ tecNO_DST, "tecNO_DST", "Destination does not exist. Send XRP to create it." },
{ tecNO_DST_INSUF_XRP, "tecNO_DST_INSUF_XRP", "Destination does not exist. Too little XRP sent to create it." },
{ tecNO_LINE_INSUF_RESERVE, "tecNO_LINE_INSUF_RESERVE", "No such line. Too little reserve to create it." },
{ tecNO_LINE_REDUNDANT, "tecNO_LINE_REDUNDANT", "Can't set non-existant line to default." },
{ tecPATH_DRY, "tecPATH_DRY", "Path could not send partial amount." },
{ tecPATH_PARTIAL, "tecPATH_PARTIAL", "Path could not send full amount." },
{ tecMASTER_DISABLED, "tecMASTER_DISABLED", "Master key is disabled." },
{ tecNO_REGULAR_KEY, "tecNO_REGULAR_KEY", "Regular key is not set." },
{ tecUNFUNDED, "tecUNFUNDED", "One of _ADD, _OFFER, or _SEND. Deprecated." },
{ tecUNFUNDED_ADD, "tecUNFUNDED_ADD", "Insufficient XRP balance for WalletAdd." },
{ tecUNFUNDED_OFFER, "tecUNFUNDED_OFFER", "Insufficient balance to fund created offer." },
{ tecUNFUNDED_PAYMENT, "tecUNFUNDED_PAYMENT", "Insufficient XRP balance to send." },
{ tecOWNERS, "tecOWNERS", "Non-zero owner count." },
{ tecNO_ISSUER, "tecNO_ISSUER", "Issuer account does not exist." },
{ tecNO_AUTH, "tecNO_AUTH", "Not authorized to hold asset." },
{ tecNO_LINE, "tecNO_LINE", "No such line." },
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
{ tefALREADY, "tefALREADY", "The exact transaction was already in this ledger." },
{ tefBAD_ADD_AUTH, "tefBAD_ADD_AUTH", "Not authorized to add account." },
{ tefBAD_AUTH, "tefBAD_AUTH", "Transaction's public key is not authorized." },
{ tefBAD_CLAIM_ID, "tefBAD_CLAIM_ID", "Malformed: Bad claim id." },
{ tefBAD_GEN_AUTH, "tefBAD_GEN_AUTH", "Not authorized to claim generator." },
{ tefBAD_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
{ tefCLAIMED, "tefCLAIMED", "Can not claim a previously claimed account." },
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
{ tefGEN_IN_USE, "tefGEN_IN_USE", "Generator already in use." },
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
{ tefNO_AUTH_REQUIRED, "tefNO_AUTH_REQUIRED", "Auth is not required." },
{ tefPAST_SEQ, "tefPAST_SEQ", "This sequence number has already past." },
{ tefWRONG_PRIOR, "tefWRONG_PRIOR", "This previous transaction does not match." },
{ tefMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." },
{ tefMAX_LEDGER, "tefMAX_LEDGER", "Ledger sequence too high." },
{ telLOCAL_ERROR, "telLOCAL_ERROR", "Local failure." },
{ telBAD_DOMAIN, "telBAD_DOMAIN", "Domain too long." },
{ telBAD_PATH_COUNT, "telBAD_PATH_COUNT", "Malformed: Too many paths." },
{ telBAD_PUBLIC_KEY, "telBAD_PUBLIC_KEY", "Public key too long." },
{ telFAILED_PROCESSING, "telFAILED_PROCESSING", "Failed to correctly process transaction." },
{ telINSUF_FEE_P, "telINSUF_FEE_P", "Fee insufficient." },
{ telNO_DST_PARTIAL, "telNO_DST_PARTIAL", "Partial payment to create account not allowed." },
{ temMALFORMED, "temMALFORMED", "Malformed transaction." },
{ temBAD_AMOUNT, "temBAD_AMOUNT", "Can only send positive amounts." },
{ temBAD_AUTH_MASTER, "temBAD_AUTH_MASTER", "Auth for unclaimed account needs correct master key." },
{ temBAD_CURRENCY, "temBAD_CURRENCY", "Malformed: Bad currency." },
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
{ temBAD_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
{ temBAD_ISSUER, "temBAD_ISSUER", "Malformed: Bad issuer." },
{ temBAD_LIMIT, "temBAD_LIMIT", "Limits must be non-negative." },
{ temBAD_OFFER, "temBAD_OFFER", "Malformed: Bad offer." },
{ temBAD_PATH, "temBAD_PATH", "Malformed: Bad path." },
{ temBAD_PATH_LOOP, "temBAD_PATH_LOOP", "Malformed: Loop in path." },
{ temBAD_PUBLISH, "temBAD_PUBLISH", "Malformed: Bad publish." },
{ temBAD_SIGNATURE, "temBAD_SIGNATURE", "Malformed: Bad signature." },
{ temBAD_SRC_ACCOUNT, "temBAD_SRC_ACCOUNT", "Malformed: Bad source account." },
{ temBAD_TRANSFER_RATE, "temBAD_TRANSFER_RATE", "Malformed: Transfer rate must be >= 1.0" },
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
{ temBAD_SEND_XRP_LIMIT, "temBAD_SEND_XRP_LIMIT", "Malformed: Limit quality is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_MAX, "temBAD_SEND_XRP_MAX", "Malformed: Send max is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_NO_DIRECT, "temBAD_SEND_XRP_NO_DIRECT", "Malformed: No Ripple direct is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PARTIAL, "temBAD_SEND_XRP_PARTIAL", "Malformed: Partial payment is not allowed for XRP to XRP." },
{ temBAD_SEND_XRP_PATHS, "temBAD_SEND_XRP_PATHS", "Malformed: Paths are not allowed for XRP to XRP." },
{ temDST_IS_SRC, "temDST_IS_SRC", "Destination may not be source." },
{ temDST_NEEDED, "temDST_NEEDED", "Destination not specified." },
{ temINVALID, "temINVALID", "The transaction is ill-formed." },
{ temINVALID_FLAG, "temINVALID_FLAG", "The transaction has an invalid flag." },
{ temREDUNDANT, "temREDUNDANT", "Sends same currency to self." },
{ temREDUNDANT_SEND_MAX, "temREDUNDANT_SEND_MAX", "Send max is redundant." },
{ temRIPPLE_EMPTY, "temRIPPLE_EMPTY", "PathSet with no paths." },
{ temUNCERTAIN, "temUNCERTAIN", "In process of determining result. Never returned." },
{ temUNKNOWN, "temUNKNOWN", "The transactions requires logic not implemented yet." },
{ terRETRY, "terRETRY", "Retry transaction." },
{ terFUNDS_SPENT, "terFUNDS_SPENT", "Can't set password, password set funds already spent." },
{ terINSUF_FEE_B, "terINSUF_FEE_B", "Account balance can't pay fee." },
{ terLAST, "terLAST", "Process last." },
{ terNO_RIPPLE, "terNO_RIPPLE", "Path does not permit rippling." },
{ terNO_ACCOUNT, "terNO_ACCOUNT", "The source account does not exist." },
{ terNO_AUTH, "terNO_AUTH", "Not authorized to hold IOUs." },
{ terNO_LINE, "terNO_LINE", "No such line." },
{ terPRE_SEQ, "terPRE_SEQ", "Missing/inapplicable prior transaction." },
{ terOWNERS, "terOWNERS", "Non-zero owner count." },
{ tesSUCCESS, "tesSUCCESS", "The transaction was applied." },
};
int iIndex = RIPPLE_ARRAYSIZE (transResultInfoA);
while (iIndex-- && transResultInfoA[iIndex].terCode != terCode)
;
if (iIndex >= 0)
{
strToken = transResultInfoA[iIndex].cpToken;
strHuman = transResultInfoA[iIndex].cpHuman;
}
return iIndex >= 0;
}
std::string transToken (TER terCode)
{
std::string strToken;
std::string strHuman;
return transResultInfo (terCode, strToken, strHuman) ? strToken : "-";
}
std::string transHuman (TER terCode)
{
std::string strToken;
std::string strHuman;
return transResultInfo (terCode, strToken, strHuman) ? strHuman : "-";
}
} // ripple

View File

@@ -0,0 +1,193 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TER_H
#define RIPPLE_TER_H
namespace ripple {
// See https://ripple.com/wiki/Transaction_errors
// VFALCO TODO do not use auto-incrementing. Explicitly assign each
// constant so there is no possibility of someone coming in
// and screwing it up.
//
// VFALCO TODO consider renaming TER to TxErr or TxResult for clarity.
//
enum TER // aka TransactionEngineResult
{
// Note: Range is stable. Exact numbers are currently unstable. Use tokens.
// -399 .. -300: L Local error (transaction fee inadequate, exceeds local limit)
// Only valid during non-consensus processing.
// Implications:
// - Not forwarded
// - No fee check
telLOCAL_ERROR = -399,
telBAD_DOMAIN, // VFALCO TODO should read "telBAD_DOMAIN = -398," etc...
telBAD_PATH_COUNT,
telBAD_PUBLIC_KEY,
telFAILED_PROCESSING,
telINSUF_FEE_P,
telNO_DST_PARTIAL,
// -299 .. -200: M Malformed (bad signature)
// Causes:
// - Transaction corrupt.
// Implications:
// - Not applied
// - Not forwarded
// - Reject
// - Can not succeed in any imagined ledger.
temMALFORMED = -299,
temBAD_AMOUNT,
temBAD_AUTH_MASTER,
temBAD_CURRENCY,
temBAD_FEE,
temBAD_EXPIRATION,
temBAD_ISSUER,
temBAD_LIMIT,
temBAD_OFFER,
temBAD_PATH,
temBAD_PATH_LOOP,
temBAD_PUBLISH,
temBAD_TRANSFER_RATE,
temBAD_SEND_XRP_LIMIT,
temBAD_SEND_XRP_MAX,
temBAD_SEND_XRP_NO_DIRECT,
temBAD_SEND_XRP_PARTIAL,
temBAD_SEND_XRP_PATHS,
temBAD_SIGNATURE,
temBAD_SRC_ACCOUNT,
temBAD_SEQUENCE,
temDST_IS_SRC,
temDST_NEEDED,
temINVALID,
temINVALID_FLAG,
temREDUNDANT,
temREDUNDANT_SEND_MAX,
temRIPPLE_EMPTY,
temUNCERTAIN, // An intermediate result used internally, should never be returned.
temUNKNOWN,
// -199 .. -100: F Failure (sequence number previously used)
// Causes:
// - Transaction cannot succeed because of ledger state.
// - Unexpected ledger state.
// - C++ exception.
// Implications:
// - Not applied
// - Not forwarded
// - Could succeed in an imagined ledger.
tefFAILURE = -199,
tefALREADY,
tefBAD_ADD_AUTH,
tefBAD_AUTH,
tefBAD_CLAIM_ID,
tefBAD_GEN_AUTH,
tefBAD_LEDGER,
tefCLAIMED,
tefCREATED,
tefDST_TAG_NEEDED,
tefEXCEPTION,
tefGEN_IN_USE,
tefINTERNAL,
tefNO_AUTH_REQUIRED, // Can't set auth if auth is not required.
tefPAST_SEQ,
tefWRONG_PRIOR,
tefMASTER_DISABLED,
tefMAX_LEDGER,
// -99 .. -1: R Retry (sequence too high, no funds for txn fee, originating account non-existent)
// Causes:
// - Prior application of another, possibly non-existant, another transaction could allow this transaction to succeed.
// Implications:
// - Not applied
// - Not forwarded
// - Might succeed later
// - Hold
// - Makes hole in sequence which jams transactions.
terRETRY = -99,
terFUNDS_SPENT, // This is a free transaction, therefore don't burden network.
terINSUF_FEE_B, // Can't pay fee, therefore don't burden network.
terNO_ACCOUNT, // Can't pay fee, therefore don't burden network.
terNO_AUTH, // Not authorized to hold IOUs.
terNO_LINE, // Internal flag.
terOWNERS, // Can't succeed with non-zero owner count.
terPRE_SEQ, // Can't pay fee, no point in forwarding, therefore don't burden network.
terLAST, // Process after all other transactions
terNO_RIPPLE, // Rippling not allowed
// 0: S Success (success)
// Causes:
// - Success.
// Implications:
// - Applied
// - Forwarded
tesSUCCESS = 0,
// 100 .. 159 C Claim fee only (ripple transaction with no good paths, pay to non-existent account, no path)
// Causes:
// - Success, but does not achieve optimal result.
// - Invalid transaction or no effect, but claim fee to use the sequence number.
// Implications:
// - Applied
// - Forwarded
// Only allowed as a return code of appliedTransaction when !tapRetry. Otherwise, treated as terRETRY.
//
// DO NOT CHANGE THESE NUMBERS: They appear in ledger meta data.
tecCLAIM = 100,
tecPATH_PARTIAL = 101,
tecUNFUNDED_ADD = 102,
tecUNFUNDED_OFFER = 103,
tecUNFUNDED_PAYMENT = 104,
tecFAILED_PROCESSING = 105,
tecDIR_FULL = 121,
tecINSUF_RESERVE_LINE = 122,
tecINSUF_RESERVE_OFFER = 123,
tecNO_DST = 124,
tecNO_DST_INSUF_XRP = 125,
tecNO_LINE_INSUF_RESERVE = 126,
tecNO_LINE_REDUNDANT = 127,
tecPATH_DRY = 128,
tecUNFUNDED = 129, // Deprecated, old ambiguous unfunded.
tecMASTER_DISABLED = 130,
tecNO_REGULAR_KEY = 131,
tecOWNERS = 132,
tecNO_ISSUER = 133,
tecNO_AUTH = 134,
tecNO_LINE = 135,
};
// VFALCO TODO change these to normal functions.
#define isTelLocal(x) ((x) >= telLOCAL_ERROR && (x) < temMALFORMED)
#define isTemMalformed(x) ((x) >= temMALFORMED && (x) < tefFAILURE)
#define isTefFailure(x) ((x) >= tefFAILURE && (x) < terRETRY)
#define isTerRetry(x) ((x) >= terRETRY && (x) < tesSUCCESS)
#define isTesSuccess(x) ((x) == tesSUCCESS)
#define isTecClaim(x) ((x) >= tecCLAIM)
// VFALCO TODO group these into a shell class along with the defines above.
extern bool transResultInfo (TER terCode, std::string& strToken, std::string& strHuman);
extern std::string transToken (TER terCode);
extern std::string transHuman (TER terCode);
} // ripple
#endif

View File

@@ -0,0 +1,88 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TXFLAGS_H
#define RIPPLE_TXFLAGS_H
namespace ripple {
//
// Transaction flags.
//
/** Transaction flags.
These flags modify the behavior of an operation.
@note Changing these will create a hard fork
@ingroup protocol
*/
class TxFlag
{
public:
static std::uint32_t const requireDestTag = 0x00010000;
};
// VFALCO TODO Move all flags into this container after some study.
// Universal Transaction flags:
const std::uint32_t tfFullyCanonicalSig = 0x80000000;
const std::uint32_t tfUniversal = tfFullyCanonicalSig;
const std::uint32_t tfUniversalMask = ~ tfUniversal;
// AccountSet flags:
// VFALCO TODO Javadoc comment every one of these constants
//const std::uint32_t TxFlag::requireDestTag = 0x00010000;
const std::uint32_t tfOptionalDestTag = 0x00020000;
const std::uint32_t tfRequireAuth = 0x00040000;
const std::uint32_t tfOptionalAuth = 0x00080000;
const std::uint32_t tfDisallowXRP = 0x00100000;
const std::uint32_t tfAllowXRP = 0x00200000;
const std::uint32_t tfAccountSetMask = ~ (tfUniversal | TxFlag::requireDestTag | tfOptionalDestTag
| tfRequireAuth | tfOptionalAuth
| tfDisallowXRP | tfAllowXRP);
// AccountSet SetFlag/ClearFlag values
const std::uint32_t asfRequireDest = 1;
const std::uint32_t asfRequireAuth = 2;
const std::uint32_t asfDisallowXRP = 3;
const std::uint32_t asfDisableMaster = 4;
const std::uint32_t asfAccountTxnID = 5;
// OfferCreate flags:
const std::uint32_t tfPassive = 0x00010000;
const std::uint32_t tfImmediateOrCancel = 0x00020000;
const std::uint32_t tfFillOrKill = 0x00040000;
const std::uint32_t tfSell = 0x00080000;
const std::uint32_t tfOfferCreateMask = ~ (tfUniversal | tfPassive | tfImmediateOrCancel | tfFillOrKill | tfSell);
// Payment flags:
const std::uint32_t tfNoRippleDirect = 0x00010000;
const std::uint32_t tfPartialPayment = 0x00020000;
const std::uint32_t tfLimitQuality = 0x00040000;
const std::uint32_t tfPaymentMask = ~ (tfUniversal | tfPartialPayment | tfLimitQuality | tfNoRippleDirect);
// TrustSet flags:
const std::uint32_t tfSetfAuth = 0x00010000;
const std::uint32_t tfSetNoRipple = 0x00020000;
const std::uint32_t tfClearNoRipple = 0x00040000;
const std::uint32_t tfTrustSetMask = ~ (tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple);
} // ripple
#endif

View File

@@ -0,0 +1,118 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
namespace ripple {
TxFormats::TxFormats ()
{
add ("AccountSet", ttACCOUNT_SET)
<< SOElement (sfEmailHash, SOE_OPTIONAL)
<< SOElement (sfWalletLocator, SOE_OPTIONAL)
<< SOElement (sfWalletSize, SOE_OPTIONAL)
<< SOElement (sfMessageKey, SOE_OPTIONAL)
<< SOElement (sfDomain, SOE_OPTIONAL)
<< SOElement (sfTransferRate, SOE_OPTIONAL)
<< SOElement (sfSetFlag, SOE_OPTIONAL)
<< SOElement (sfClearFlag, SOE_OPTIONAL)
;
add ("TrustSet", ttTRUST_SET)
<< SOElement (sfLimitAmount, SOE_OPTIONAL)
<< SOElement (sfQualityIn, SOE_OPTIONAL)
<< SOElement (sfQualityOut, SOE_OPTIONAL)
;
add ("OfferCreate", ttOFFER_CREATE)
<< SOElement (sfTakerPays, SOE_REQUIRED)
<< SOElement (sfTakerGets, SOE_REQUIRED)
<< SOElement (sfExpiration, SOE_OPTIONAL)
<< SOElement (sfOfferSequence, SOE_OPTIONAL)
;
add ("OfferCancel", ttOFFER_CANCEL)
<< SOElement (sfOfferSequence, SOE_REQUIRED)
;
add ("SetRegularKey", ttREGULAR_KEY_SET)
<< SOElement (sfRegularKey, SOE_OPTIONAL)
;
add ("Payment", ttPAYMENT)
<< SOElement (sfDestination, SOE_REQUIRED)
<< SOElement (sfAmount, SOE_REQUIRED)
<< SOElement (sfSendMax, SOE_OPTIONAL)
<< SOElement (sfPaths, SOE_DEFAULT)
<< SOElement (sfInvoiceID, SOE_OPTIONAL)
<< SOElement (sfDestinationTag, SOE_OPTIONAL)
;
add ("Contract", ttCONTRACT)
<< SOElement (sfExpiration, SOE_REQUIRED)
<< SOElement (sfBondAmount, SOE_REQUIRED)
<< SOElement (sfStampEscrow, SOE_REQUIRED)
<< SOElement (sfRippleEscrow, SOE_REQUIRED)
<< SOElement (sfCreateCode, SOE_OPTIONAL)
<< SOElement (sfFundCode, SOE_OPTIONAL)
<< SOElement (sfRemoveCode, SOE_OPTIONAL)
<< SOElement (sfExpireCode, SOE_OPTIONAL)
;
add ("RemoveContract", ttCONTRACT_REMOVE)
<< SOElement (sfTarget, SOE_REQUIRED)
;
add ("EnableAmendment", ttAMENDMENT)
<< SOElement (sfAmendment, SOE_REQUIRED)
;
add ("SetFee", ttFEE)
<< SOElement (sfBaseFee, SOE_REQUIRED)
<< SOElement (sfReferenceFeeUnits, SOE_REQUIRED)
<< SOElement (sfReserveBase, SOE_REQUIRED)
<< SOElement (sfReserveIncrement, SOE_REQUIRED)
;
}
void TxFormats::addCommonFields (Item& item)
{
item
<< SOElement(sfTransactionType, SOE_REQUIRED)
<< SOElement(sfFlags, SOE_OPTIONAL)
<< SOElement(sfSourceTag, SOE_OPTIONAL)
<< SOElement(sfAccount, SOE_REQUIRED)
<< SOElement(sfSequence, SOE_REQUIRED)
<< SOElement(sfPreviousTxnID, SOE_OPTIONAL) // Deprecated: Do not use
<< SOElement(sfLastLedgerSequence, SOE_OPTIONAL)
<< SOElement(sfAccountTxnID, SOE_OPTIONAL)
<< SOElement(sfFee, SOE_REQUIRED)
<< SOElement(sfOperationLimit, SOE_OPTIONAL)
<< SOElement(sfMemos, SOE_OPTIONAL)
<< SOElement(sfSigningPubKey, SOE_REQUIRED)
<< SOElement(sfTxnSignature, SOE_OPTIONAL)
;
}
TxFormats* TxFormats::getInstance ()
{
static TxFormats instance;
//return SharedSingleton <TxFormats>::getInstance ();
return &instance;
}
} // ripple

View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef RIPPLE_TXFORMATS_H_INCLUDED
#define RIPPLE_TXFORMATS_H_INCLUDED
namespace ripple {
/** Transaction type identifiers.
These are part of the binary message format.
@ingroup protocol
*/
enum TxType
{
ttINVALID = -1,
ttPAYMENT = 0,
ttCLAIM = 1, // open
ttWALLET_ADD = 2,
ttACCOUNT_SET = 3,
ttPASSWORD_FUND = 4, // open
ttREGULAR_KEY_SET = 5,
ttNICKNAME_SET = 6, // open
ttOFFER_CREATE = 7,
ttOFFER_CANCEL = 8,
ttCONTRACT = 9,
ttCONTRACT_REMOVE = 10, // can we use the same msg as offer cancel
ttTRUST_SET = 20,
ttAMENDMENT = 100,
ttFEE = 101,
};
/** Manages the list of known transaction formats.
*/
class TxFormats : public KnownFormats <TxType>
{
private:
void addCommonFields (Item& item);
public:
/** Create the object.
This will load the object will all the known transaction formats.
*/
TxFormats ();
static TxFormats* getInstance ();
};
} // ripple
#endif