mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Clean up and restructure sources
This commit is contained in:
236
src/ripple/data/protocol/BuildInfo.cpp
Normal file
236
src/ripple/data/protocol/BuildInfo.cpp
Normal 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.26.4-alpha"
|
||||
//
|
||||
// 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 << "rippled-" << 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
|
||||
87
src/ripple/data/protocol/BuildInfo.h
Normal file
87
src/ripple/data/protocol/BuildInfo.h
Normal 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
|
||||
34
src/ripple/data/protocol/HashPrefix.cpp
Normal file
34
src/ripple/data/protocol/HashPrefix.cpp
Normal 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
|
||||
91
src/ripple/data/protocol/HashPrefix.h
Normal file
91
src/ripple/data/protocol/HashPrefix.h
Normal 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
|
||||
192
src/ripple/data/protocol/KnownFormats.h
Normal file
192
src/ripple/data/protocol/KnownFormats.h
Normal 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
|
||||
127
src/ripple/data/protocol/LedgerFormats.cpp
Normal file
127
src/ripple/data/protocol/LedgerFormats.cpp
Normal file
@@ -0,0 +1,127 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/module/core/memory/SharedSingleton.h>
|
||||
|
||||
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 ("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 ("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)
|
||||
;
|
||||
|
||||
add ("Ticket", ltTICKET)
|
||||
<< SOElement (sfAccount, SOE_REQUIRED)
|
||||
<< SOElement (sfSequence, SOE_REQUIRED)
|
||||
<< SOElement (sfOwnerNode, SOE_REQUIRED)
|
||||
<< SOElement (sfTarget, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
}
|
||||
|
||||
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
|
||||
145
src/ripple/data/protocol/LedgerFormats.h
Normal file
145
src/ripple/data/protocol/LedgerFormats.h
Normal file
@@ -0,0 +1,145 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
ltRIPPLE_STATE = 'r',
|
||||
|
||||
ltTICKET = 'T',
|
||||
|
||||
/* Deprecated. */
|
||||
ltOFFER = 'o',
|
||||
|
||||
ltLEDGER_HASHES = 'h',
|
||||
|
||||
ltAMENDMENTS = 'f',
|
||||
|
||||
ltFEE_SETTINGS = 's',
|
||||
|
||||
// No longer used or supported. Left here to prevent accidental
|
||||
// reassignment of the ledger type.
|
||||
ltNICKNAME = 'n',
|
||||
|
||||
ltNotUsed01 = 'c',
|
||||
};
|
||||
|
||||
/**
|
||||
@ingroup protocol
|
||||
*/
|
||||
// Used as a prefix for computing ledger indexes (keys).
|
||||
enum LedgerNameSpace
|
||||
{
|
||||
spaceAccount = 'a',
|
||||
spaceDirNode = 'd',
|
||||
spaceGenerator = 'g',
|
||||
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',
|
||||
spaceTicket = 'T',
|
||||
|
||||
// No longer used or supported. Left here to reserve the space and
|
||||
// avoid accidental reuse of the space.
|
||||
spaceNickname = 'n',
|
||||
};
|
||||
|
||||
/**
|
||||
@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
|
||||
lsfNoFreeze = 0x00200000, // True, cannot freeze ripple states
|
||||
lsfGlobalFreeze = 0x00400000, // True, all assets frozen
|
||||
|
||||
// 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,
|
||||
lsfLowFreeze = 0x00400000, // True, low side has set freeze flag
|
||||
lsfHighFreeze = 0x00800000, // True, high side has set freeze flag
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** 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
|
||||
67
src/ripple/data/protocol/Protocol.h
Normal file
67
src/ripple/data/protocol/Protocol.h
Normal file
@@ -0,0 +1,67 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/types/base_uint.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
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
1012
src/ripple/data/protocol/RippleAddress.cpp
Normal file
1012
src/ripple/data/protocol/RippleAddress.cpp
Normal file
File diff suppressed because it is too large
Load Diff
304
src/ripple/data/protocol/RippleAddress.h
Normal file
304
src/ripple/data/protocol/RippleAddress.h
Normal file
@@ -0,0 +1,304 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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/data/crypto/Base58Data.h>
|
||||
|
||||
#include <ripple/types/UInt160.h>
|
||||
#include <ripple/types/UintTypes.h>
|
||||
#include <ripple/types/RippleAccountID.h>
|
||||
#include <ripple/types/RippleAccountPrivateKey.h>
|
||||
#include <ripple/types/RippleAccountPublicKey.h>
|
||||
#include <ripple/types/RipplePrivateKey.h>
|
||||
#include <ripple/types/RipplePublicKey.h>
|
||||
#include <ripple/types/RipplePublicKeyHash.h>
|
||||
#include <ripple/sslutil/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 only 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
|
||||
//
|
||||
NodeID getNodeID () const;
|
||||
Blob const& getNodePublic () const;
|
||||
|
||||
std::string humanNodePublic () const;
|
||||
|
||||
bool setNodePublic (std::string const& strPublic);
|
||||
void setNodePublic (Blob const& vPublic);
|
||||
bool verifyNodePublic (uint256 const& hash, Blob const& vchSig,
|
||||
ECDSA mustBeFullyCanonical) const;
|
||||
bool verifyNodePublic (uint256 const& hash, std::string const& strSig,
|
||||
ECDSA mustBeFullyCanonical) const;
|
||||
|
||||
static RippleAddress createNodePublic (RippleAddress const& naSeed);
|
||||
static RippleAddress createNodePublic (Blob const& vPublic);
|
||||
static RippleAddress createNodePublic (std::string const& strPublic);
|
||||
|
||||
//
|
||||
// Node Private
|
||||
//
|
||||
Blob const& getNodePrivateData () const;
|
||||
uint256 getNodePrivate () const;
|
||||
|
||||
std::string humanNodePrivate () const;
|
||||
|
||||
bool setNodePrivate (std::string const& strPrivate);
|
||||
void setNodePrivate (Blob const& vPrivate);
|
||||
void setNodePrivate (uint256 hash256);
|
||||
void signNodePrivate (uint256 const& hash, Blob& vchSig) const;
|
||||
|
||||
static RippleAddress createNodePrivate (RippleAddress const& naSeed);
|
||||
|
||||
//
|
||||
// Accounts IDs
|
||||
//
|
||||
Account getAccountID () const;
|
||||
|
||||
std::string humanAccountID () const;
|
||||
|
||||
bool setAccountID (
|
||||
std::string const& strAccountID,
|
||||
Base58::Alphabet const& alphabet = Base58::getRippleAlphabet());
|
||||
void setAccountID (Account const& hash160In);
|
||||
|
||||
#if 0
|
||||
static RippleAddress createAccountID (std::string const& strAccountID)
|
||||
{
|
||||
RippleAddress na;
|
||||
na.setAccountID (strAccountID);
|
||||
return na;
|
||||
}
|
||||
#endif
|
||||
|
||||
static RippleAddress createAccountID (Account const& uiAccountID);
|
||||
|
||||
//
|
||||
// Accounts Public
|
||||
//
|
||||
Blob const& getAccountPublic () const;
|
||||
|
||||
std::string humanAccountPublic () const;
|
||||
|
||||
bool setAccountPublic (std::string const& strPublic);
|
||||
void setAccountPublic (Blob const& vPublic);
|
||||
void setAccountPublic (RippleAddress const& 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 (
|
||||
RippleAddress const& naGenerator, int iSeq);
|
||||
|
||||
//
|
||||
// Accounts Private
|
||||
//
|
||||
uint256 getAccountPrivate () const;
|
||||
|
||||
std::string humanAccountPrivate () const;
|
||||
|
||||
bool setAccountPrivate (std::string const& strPrivate);
|
||||
void setAccountPrivate (Blob const& vPrivate);
|
||||
void setAccountPrivate (uint256 hash256);
|
||||
void setAccountPrivate (RippleAddress const& naGenerator,
|
||||
RippleAddress const& naSeed, int seq);
|
||||
|
||||
bool accountPrivateSign (uint256 const& uHash, Blob& vucSig) const;
|
||||
|
||||
// Encrypt a message.
|
||||
Blob accountPrivateEncrypt (
|
||||
RippleAddress const& naPublicTo, Blob const& vucPlainText) const;
|
||||
|
||||
// Decrypt a message.
|
||||
Blob accountPrivateDecrypt (
|
||||
RippleAddress const& naPublicFrom, Blob const& vucCipherText) const;
|
||||
|
||||
static RippleAddress createAccountPrivate (
|
||||
RippleAddress const& generator, RippleAddress const& seed, 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 (std::string const& strGenerator);
|
||||
void setGenerator (Blob const& vPublic);
|
||||
// void setGenerator(RippleAddress const& seed);
|
||||
|
||||
// Create generator for making public deterministic keys.
|
||||
static RippleAddress createGeneratorPublic (RippleAddress const& naSeed);
|
||||
|
||||
//
|
||||
// Seeds
|
||||
// Clients must disallow reconizable entries from being seeds.
|
||||
uint128 getSeed () const;
|
||||
|
||||
std::string humanSeed () const;
|
||||
std::string humanSeed1751 () const;
|
||||
|
||||
bool setSeed (std::string const& strSeed);
|
||||
int setSeed1751 (std::string const& strHuman1751);
|
||||
bool setSeedGeneric (std::string const& strText);
|
||||
void setSeed (uint128 hash128);
|
||||
void setSeedRandom ();
|
||||
|
||||
static RippleAddress createSeedRandom ();
|
||||
static RippleAddress createSeedGeneric (std::string const& 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
|
||||
{
|
||||
auto 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
|
||||
{
|
||||
auto 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
|
||||
61
src/ripple/data/protocol/RippleSystem.h
Normal file
61
src/ripple/data/protocol/RippleSystem.h
Normal file
@@ -0,0 +1,61 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_PRECISION 6
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
399
src/ripple/data/protocol/SField.cpp
Normal file
399
src/ripple/data/protocol/SField.cpp
Normal file
@@ -0,0 +1,399 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/data/protocol/SField.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// These must stay at the top of this file, and in this order
|
||||
// Files-cope statics are preferred here because the SFields must be
|
||||
// file-scope. The following 3 objects must have scope prior to
|
||||
// the file-scope SFields.
|
||||
static std::mutex SField_mutex;
|
||||
static std::map<int, SField::ptr> knownCodeToField;
|
||||
static std::map<int, std::unique_ptr<SField const>> unknownCodeToField;
|
||||
|
||||
int SField::num = 0;
|
||||
|
||||
typedef std::lock_guard <std::mutex> StaticScopedLockType;
|
||||
|
||||
// Give this translation unit only, permission to construct SFields
|
||||
struct SField::make
|
||||
{
|
||||
#ifndef _MSC_VER
|
||||
template <class ...Args>
|
||||
static SField one(SField const* p, Args&& ...args)
|
||||
{
|
||||
SField result(std::forward<Args>(args)...);
|
||||
knownCodeToField[result.fieldCode] = p;
|
||||
return result;
|
||||
}
|
||||
#else // remove this when VS gets variadic templates
|
||||
template <class A0>
|
||||
static SField one(SField const* p, A0&& arg0)
|
||||
{
|
||||
SField result(std::forward<A0>(arg0));
|
||||
knownCodeToField[result.fieldCode] = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class A0, class A1, class A2>
|
||||
static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2)
|
||||
{
|
||||
SField result(std::forward<A0>(arg0), std::forward<A1>(arg1),
|
||||
std::forward<A2>(arg2));
|
||||
knownCodeToField[result.fieldCode] = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class A0, class A1, class A2, class A3>
|
||||
static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2,
|
||||
A3&& arg3)
|
||||
{
|
||||
SField result(std::forward<A0>(arg0), std::forward<A1>(arg1),
|
||||
std::forward<A2>(arg2), std::forward<A3>(arg3));
|
||||
knownCodeToField[result.fieldCode] = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class A0, class A1, class A2, class A3, class A4>
|
||||
static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2,
|
||||
A3&& arg3, A4&& arg4)
|
||||
{
|
||||
SField result(std::forward<A0>(arg0), std::forward<A1>(arg1),
|
||||
std::forward<A2>(arg2), std::forward<A3>(arg3),
|
||||
std::forward<A4>(arg4));
|
||||
knownCodeToField[result.fieldCode] = p;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
using make = SField::make;
|
||||
|
||||
// Construct all compile-time SFields, and register them in the knownCodeToField
|
||||
// database:
|
||||
|
||||
SField const sfInvalid = make::one(&sfInvalid, -1);
|
||||
SField const sfGeneric = make::one(&sfGeneric, 0);
|
||||
SField const sfLedgerEntry = make::one(&sfLedgerEntry, STI_LEDGERENTRY, 257, "LedgerEntry");
|
||||
SField const sfTransaction = make::one(&sfTransaction, STI_TRANSACTION, 257, "Transaction");
|
||||
SField const sfValidation = make::one(&sfValidation, STI_VALIDATION, 257, "Validation");
|
||||
SField const sfMetadata = make::one(&sfMetadata, STI_METADATA, 257, "Metadata");
|
||||
SField const sfHash = make::one(&sfHash, STI_HASH256, 257, "hash");
|
||||
SField const sfIndex = make::one(&sfIndex, STI_HASH256, 258, "index");
|
||||
|
||||
// 8-bit integers
|
||||
SField const sfCloseResolution = make::one(&sfCloseResolution, STI_UINT8, 1, "CloseResolution");
|
||||
SField const sfTemplateEntryType = make::one(&sfTemplateEntryType, STI_UINT8, 2, "TemplateEntryType");
|
||||
SField const sfTransactionResult = make::one(&sfTransactionResult, STI_UINT8, 3, "TransactionResult");
|
||||
|
||||
// 16-bit integers
|
||||
SField const sfLedgerEntryType = make::one(&sfLedgerEntryType, STI_UINT16, 1, "LedgerEntryType", SField::sMD_Never);
|
||||
SField const sfTransactionType = make::one(&sfTransactionType, STI_UINT16, 2, "TransactionType");
|
||||
|
||||
// 32-bit integers (common)
|
||||
SField const sfFlags = make::one(&sfFlags, STI_UINT32, 2, "Flags");
|
||||
SField const sfSourceTag = make::one(&sfSourceTag, STI_UINT32, 3, "SourceTag");
|
||||
SField const sfSequence = make::one(&sfSequence, STI_UINT32, 4, "Sequence");
|
||||
SField const sfPreviousTxnLgrSeq = make::one(&sfPreviousTxnLgrSeq, STI_UINT32, 5, "PreviousTxnLgrSeq", SField::sMD_DeleteFinal);
|
||||
SField const sfLedgerSequence = make::one(&sfLedgerSequence, STI_UINT32, 6, "LedgerSequence");
|
||||
SField const sfCloseTime = make::one(&sfCloseTime, STI_UINT32, 7, "CloseTime");
|
||||
SField const sfParentCloseTime = make::one(&sfParentCloseTime, STI_UINT32, 8, "ParentCloseTime");
|
||||
SField const sfSigningTime = make::one(&sfSigningTime, STI_UINT32, 9, "SigningTime");
|
||||
SField const sfExpiration = make::one(&sfExpiration, STI_UINT32, 10, "Expiration");
|
||||
SField const sfTransferRate = make::one(&sfTransferRate, STI_UINT32, 11, "TransferRate");
|
||||
SField const sfWalletSize = make::one(&sfWalletSize, STI_UINT32, 12, "WalletSize");
|
||||
SField const sfOwnerCount = make::one(&sfOwnerCount, STI_UINT32, 13, "OwnerCount");
|
||||
SField const sfDestinationTag = make::one(&sfDestinationTag, STI_UINT32, 14, "DestinationTag");
|
||||
|
||||
// 32-bit integers (uncommon)
|
||||
SField const sfHighQualityIn = make::one(&sfHighQualityIn, STI_UINT32, 16, "HighQualityIn");
|
||||
SField const sfHighQualityOut = make::one(&sfHighQualityOut, STI_UINT32, 17, "HighQualityOut");
|
||||
SField const sfLowQualityIn = make::one(&sfLowQualityIn, STI_UINT32, 18, "LowQualityIn");
|
||||
SField const sfLowQualityOut = make::one(&sfLowQualityOut, STI_UINT32, 19, "LowQualityOut");
|
||||
SField const sfQualityIn = make::one(&sfQualityIn, STI_UINT32, 20, "QualityIn");
|
||||
SField const sfQualityOut = make::one(&sfQualityOut, STI_UINT32, 21, "QualityOut");
|
||||
SField const sfStampEscrow = make::one(&sfStampEscrow, STI_UINT32, 22, "StampEscrow");
|
||||
SField const sfBondAmount = make::one(&sfBondAmount, STI_UINT32, 23, "BondAmount");
|
||||
SField const sfLoadFee = make::one(&sfLoadFee, STI_UINT32, 24, "LoadFee");
|
||||
SField const sfOfferSequence = make::one(&sfOfferSequence, STI_UINT32, 25, "OfferSequence");
|
||||
SField const sfFirstLedgerSequence = make::one(&sfFirstLedgerSequence, STI_UINT32, 26, "FirstLedgerSequence"); // Deprecated: do not use
|
||||
SField const sfLastLedgerSequence = make::one(&sfLastLedgerSequence, STI_UINT32, 27, "LastLedgerSequence");
|
||||
SField const sfTransactionIndex = make::one(&sfTransactionIndex, STI_UINT32, 28, "TransactionIndex");
|
||||
SField const sfOperationLimit = make::one(&sfOperationLimit, STI_UINT32, 29, "OperationLimit");
|
||||
SField const sfReferenceFeeUnits = make::one(&sfReferenceFeeUnits, STI_UINT32, 30, "ReferenceFeeUnits");
|
||||
SField const sfReserveBase = make::one(&sfReserveBase, STI_UINT32, 31, "ReserveBase");
|
||||
SField const sfReserveIncrement = make::one(&sfReserveIncrement, STI_UINT32, 32, "ReserveIncrement");
|
||||
SField const sfSetFlag = make::one(&sfSetFlag, STI_UINT32, 33, "SetFlag");
|
||||
SField const sfClearFlag = make::one(&sfClearFlag, STI_UINT32, 34, "ClearFlag");
|
||||
|
||||
// 64-bit integers
|
||||
SField const sfIndexNext = make::one(&sfIndexNext, STI_UINT64, 1, "IndexNext");
|
||||
SField const sfIndexPrevious = make::one(&sfIndexPrevious, STI_UINT64, 2, "IndexPrevious");
|
||||
SField const sfBookNode = make::one(&sfBookNode, STI_UINT64, 3, "BookNode");
|
||||
SField const sfOwnerNode = make::one(&sfOwnerNode, STI_UINT64, 4, "OwnerNode");
|
||||
SField const sfBaseFee = make::one(&sfBaseFee, STI_UINT64, 5, "BaseFee");
|
||||
SField const sfExchangeRate = make::one(&sfExchangeRate, STI_UINT64, 6, "ExchangeRate");
|
||||
SField const sfLowNode = make::one(&sfLowNode, STI_UINT64, 7, "LowNode");
|
||||
SField const sfHighNode = make::one(&sfHighNode, STI_UINT64, 8, "HighNode");
|
||||
|
||||
// 128-bit
|
||||
SField const sfEmailHash = make::one(&sfEmailHash, STI_HASH128, 1, "EmailHash");
|
||||
|
||||
// 256-bit (common)
|
||||
SField const sfLedgerHash = make::one(&sfLedgerHash, STI_HASH256, 1, "LedgerHash");
|
||||
SField const sfParentHash = make::one(&sfParentHash, STI_HASH256, 2, "ParentHash");
|
||||
SField const sfTransactionHash = make::one(&sfTransactionHash, STI_HASH256, 3, "TransactionHash");
|
||||
SField const sfAccountHash = make::one(&sfAccountHash, STI_HASH256, 4, "AccountHash");
|
||||
SField const sfPreviousTxnID = make::one(&sfPreviousTxnID, STI_HASH256, 5, "PreviousTxnID", SField::sMD_DeleteFinal);
|
||||
SField const sfLedgerIndex = make::one(&sfLedgerIndex, STI_HASH256, 6, "LedgerIndex");
|
||||
SField const sfWalletLocator = make::one(&sfWalletLocator, STI_HASH256, 7, "WalletLocator");
|
||||
SField const sfRootIndex = make::one(&sfRootIndex, STI_HASH256, 8, "RootIndex", SField::sMD_Always);
|
||||
SField const sfAccountTxnID = make::one(&sfAccountTxnID, STI_HASH256, 9, "AccountTxnID");
|
||||
|
||||
// 256-bit (uncommon)
|
||||
SField const sfBookDirectory = make::one(&sfBookDirectory, STI_HASH256, 16, "BookDirectory");
|
||||
SField const sfInvoiceID = make::one(&sfInvoiceID, STI_HASH256, 17, "InvoiceID");
|
||||
SField const sfNickname = make::one(&sfNickname, STI_HASH256, 18, "Nickname");
|
||||
SField const sfAmendment = make::one(&sfAmendment, STI_HASH256, 19, "Amendment");
|
||||
SField const sfTicketID = make::one(&sfTicketID, STI_HASH256, 20, "TicketID");
|
||||
|
||||
// 160-bit (common)
|
||||
SField const sfTakerPaysCurrency = make::one(&sfTakerPaysCurrency, STI_HASH160, 1, "TakerPaysCurrency");
|
||||
SField const sfTakerPaysIssuer = make::one(&sfTakerPaysIssuer, STI_HASH160, 2, "TakerPaysIssuer");
|
||||
SField const sfTakerGetsCurrency = make::one(&sfTakerGetsCurrency, STI_HASH160, 3, "TakerGetsCurrency");
|
||||
SField const sfTakerGetsIssuer = make::one(&sfTakerGetsIssuer, STI_HASH160, 4, "TakerGetsIssuer");
|
||||
|
||||
// currency amount (common)
|
||||
SField const sfAmount = make::one(&sfAmount, STI_AMOUNT, 1, "Amount");
|
||||
SField const sfBalance = make::one(&sfBalance, STI_AMOUNT, 2, "Balance");
|
||||
SField const sfLimitAmount = make::one(&sfLimitAmount, STI_AMOUNT, 3, "LimitAmount");
|
||||
SField const sfTakerPays = make::one(&sfTakerPays, STI_AMOUNT, 4, "TakerPays");
|
||||
SField const sfTakerGets = make::one(&sfTakerGets, STI_AMOUNT, 5, "TakerGets");
|
||||
SField const sfLowLimit = make::one(&sfLowLimit, STI_AMOUNT, 6, "LowLimit");
|
||||
SField const sfHighLimit = make::one(&sfHighLimit, STI_AMOUNT, 7, "HighLimit");
|
||||
SField const sfFee = make::one(&sfFee, STI_AMOUNT, 8, "Fee");
|
||||
SField const sfSendMax = make::one(&sfSendMax, STI_AMOUNT, 9, "SendMax");
|
||||
|
||||
// currency amount (uncommon)
|
||||
SField const sfMinimumOffer = make::one(&sfMinimumOffer, STI_AMOUNT, 16, "MinimumOffer");
|
||||
SField const sfRippleEscrow = make::one(&sfRippleEscrow, STI_AMOUNT, 17, "RippleEscrow");
|
||||
SField const sfDeliveredAmount = make::one(&sfDeliveredAmount, STI_AMOUNT, 18, "DeliveredAmount");
|
||||
|
||||
// variable length
|
||||
SField const sfPublicKey = make::one(&sfPublicKey, STI_VL, 1, "PublicKey");
|
||||
SField const sfMessageKey = make::one(&sfMessageKey, STI_VL, 2, "MessageKey");
|
||||
SField const sfSigningPubKey = make::one(&sfSigningPubKey, STI_VL, 3, "SigningPubKey");
|
||||
SField const sfTxnSignature = make::one(&sfTxnSignature, STI_VL, 4, "TxnSignature", SField::sMD_Default, false);
|
||||
SField const sfGenerator = make::one(&sfGenerator, STI_VL, 5, "Generator");
|
||||
SField const sfSignature = make::one(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, false);
|
||||
SField const sfDomain = make::one(&sfDomain, STI_VL, 7, "Domain");
|
||||
SField const sfFundCode = make::one(&sfFundCode, STI_VL, 8, "FundCode");
|
||||
SField const sfRemoveCode = make::one(&sfRemoveCode, STI_VL, 9, "RemoveCode");
|
||||
SField const sfExpireCode = make::one(&sfExpireCode, STI_VL, 10, "ExpireCode");
|
||||
SField const sfCreateCode = make::one(&sfCreateCode, STI_VL, 11, "CreateCode");
|
||||
SField const sfMemoType = make::one(&sfMemoType, STI_VL, 12, "MemoType");
|
||||
SField const sfMemoData = make::one(&sfMemoData, STI_VL, 13, "MemoData");
|
||||
SField const sfMemoFormat = make::one(&sfMemoFormat, STI_VL, 14, "MemoFormat");
|
||||
|
||||
// account
|
||||
SField const sfAccount = make::one(&sfAccount, STI_ACCOUNT, 1, "Account");
|
||||
SField const sfOwner = make::one(&sfOwner, STI_ACCOUNT, 2, "Owner");
|
||||
SField const sfDestination = make::one(&sfDestination, STI_ACCOUNT, 3, "Destination");
|
||||
SField const sfIssuer = make::one(&sfIssuer, STI_ACCOUNT, 4, "Issuer");
|
||||
SField const sfTarget = make::one(&sfTarget, STI_ACCOUNT, 7, "Target");
|
||||
SField const sfRegularKey = make::one(&sfRegularKey, STI_ACCOUNT, 8, "RegularKey");
|
||||
|
||||
// path set
|
||||
SField const sfPaths = make::one(&sfPaths, STI_PATHSET, 1, "Paths");
|
||||
|
||||
// vector of 256-bit
|
||||
SField const sfIndexes = make::one(&sfIndexes, STI_VECTOR256, 1, "Indexes", SField::sMD_Never);
|
||||
SField const sfHashes = make::one(&sfHashes, STI_VECTOR256, 2, "Hashes");
|
||||
SField const sfAmendments = make::one(&sfAmendments, STI_VECTOR256, 3, "Amendments");
|
||||
|
||||
// inner object
|
||||
// OBJECT/1 is reserved for end of object
|
||||
SField const sfTransactionMetaData = make::one(&sfTransactionMetaData, STI_OBJECT, 2, "TransactionMetaData");
|
||||
SField const sfCreatedNode = make::one(&sfCreatedNode, STI_OBJECT, 3, "CreatedNode");
|
||||
SField const sfDeletedNode = make::one(&sfDeletedNode, STI_OBJECT, 4, "DeletedNode");
|
||||
SField const sfModifiedNode = make::one(&sfModifiedNode, STI_OBJECT, 5, "ModifiedNode");
|
||||
SField const sfPreviousFields = make::one(&sfPreviousFields, STI_OBJECT, 6, "PreviousFields");
|
||||
SField const sfFinalFields = make::one(&sfFinalFields, STI_OBJECT, 7, "FinalFields");
|
||||
SField const sfNewFields = make::one(&sfNewFields, STI_OBJECT, 8, "NewFields");
|
||||
SField const sfTemplateEntry = make::one(&sfTemplateEntry, STI_OBJECT, 9, "TemplateEntry");
|
||||
SField const sfMemo = make::one(&sfMemo, STI_OBJECT, 10, "Memo");
|
||||
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
SField const sfSigningAccounts = make::one(&sfSigningAccounts, STI_ARRAY, 2, "SigningAccounts");
|
||||
SField const sfTxnSignatures = make::one(&sfTxnSignatures, STI_ARRAY, 3, "TxnSignatures", SField::sMD_Default, false);
|
||||
SField const sfSignatures = make::one(&sfSignatures, STI_ARRAY, 4, "Signatures");
|
||||
SField const sfTemplate = make::one(&sfTemplate, STI_ARRAY, 5, "Template");
|
||||
SField const sfNecessary = make::one(&sfNecessary, STI_ARRAY, 6, "Necessary");
|
||||
SField const sfSufficient = make::one(&sfSufficient, STI_ARRAY, 7, "Sufficient");
|
||||
SField const sfAffectedNodes = make::one(&sfAffectedNodes, STI_ARRAY, 8, "AffectedNodes");
|
||||
SField const sfMemos = make::one(&sfMemos, STI_ARRAY, 9, "Memos");
|
||||
|
||||
SField::SField (SerializedTypeID tid, int fv, const char* fn,
|
||||
int meta, bool signing)
|
||||
: fieldCode (field_code (tid, fv))
|
||||
, fieldType (tid)
|
||||
, fieldValue (fv)
|
||||
, fieldName (fn)
|
||||
, fieldMeta (meta)
|
||||
, fieldNum (++num)
|
||||
, signingField (signing)
|
||||
, rawJsonName (getName ())
|
||||
, jsonName (rawJsonName.c_str ())
|
||||
{
|
||||
}
|
||||
|
||||
SField::SField (int fc)
|
||||
: fieldCode (fc)
|
||||
, fieldType (STI_UNKNOWN)
|
||||
, fieldValue (0)
|
||||
, fieldMeta (sMD_Never)
|
||||
, fieldNum (++num)
|
||||
, signingField (true)
|
||||
, rawJsonName (getName ())
|
||||
, jsonName (rawJsonName.c_str ())
|
||||
{
|
||||
}
|
||||
|
||||
// call with the map mutex to protect num.
|
||||
// This is naturally done with no extra expense
|
||||
// from getField(int code).
|
||||
SField::SField (SerializedTypeID tid, int fv)
|
||||
: fieldCode (field_code (tid, fv)), fieldType (tid), fieldValue (fv),
|
||||
fieldMeta (sMD_Default),
|
||||
fieldNum (++num),
|
||||
signingField (true),
|
||||
jsonName (nullptr)
|
||||
{
|
||||
fieldName = std::to_string (tid) + '/' + std::to_string (fv);
|
||||
rawJsonName = getName ();
|
||||
jsonName = Json::StaticString (rawJsonName.c_str ());
|
||||
assert ((fv != 1) || ((tid != STI_ARRAY) && (tid != STI_OBJECT)));
|
||||
}
|
||||
|
||||
SField::ref SField::getField (int code)
|
||||
{
|
||||
auto it = knownCodeToField.find (code);
|
||||
|
||||
if (it != knownCodeToField.end ())
|
||||
{
|
||||
// 99+% of the time, it will be a valid, known field
|
||||
return * (it->second);
|
||||
}
|
||||
|
||||
int type = code >> 16;
|
||||
int field = code & 0xffff;
|
||||
|
||||
// Don't dynamically extend types that have no binary encoding.
|
||||
if ((field > 255) || (code < 0))
|
||||
return sfInvalid;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
// Types we are willing to dynamically extend
|
||||
// types (common)
|
||||
case STI_UINT16:
|
||||
case STI_UINT32:
|
||||
case STI_UINT64:
|
||||
case STI_HASH128:
|
||||
case STI_HASH256:
|
||||
case STI_AMOUNT:
|
||||
case STI_VL:
|
||||
case STI_ACCOUNT:
|
||||
case STI_OBJECT:
|
||||
case STI_ARRAY:
|
||||
// types (uncommon)
|
||||
case STI_UINT8:
|
||||
case STI_HASH160:
|
||||
case STI_PATHSET:
|
||||
case STI_VECTOR256:
|
||||
break;
|
||||
|
||||
default:
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
{
|
||||
// Lookup in the run-time data base, and create if it does not
|
||||
// yet exist.
|
||||
StaticScopedLockType sl (SField_mutex);
|
||||
|
||||
auto it = unknownCodeToField.find (code);
|
||||
|
||||
if (it != unknownCodeToField.end ())
|
||||
return * (it->second);
|
||||
return *(unknownCodeToField[code] = std::unique_ptr<SField const>(
|
||||
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 std::to_string(static_cast<int> (fieldType)) + "/" +
|
||||
std::to_string(fieldValue);
|
||||
}
|
||||
|
||||
SField::ref SField::getField (std::string const& fieldName)
|
||||
{
|
||||
for (auto const & fieldPair : knownCodeToField)
|
||||
{
|
||||
if (fieldPair.second->fieldName == fieldName)
|
||||
return * (fieldPair.second);
|
||||
}
|
||||
{
|
||||
StaticScopedLockType sl (SField_mutex);
|
||||
|
||||
for (auto const & fieldPair : unknownCodeToField)
|
||||
{
|
||||
if (fieldPair.second->fieldName == fieldName)
|
||||
return * (fieldPair.second);
|
||||
}
|
||||
}
|
||||
return sfInvalid;
|
||||
}
|
||||
|
||||
} // ripple
|
||||
417
src/ripple/data/protocol/SField.h
Normal file
417
src/ripple/data/protocol/SField.h
Normal file
@@ -0,0 +1,417 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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
|
||||
|
||||
#include <ripple/basics/BasicTypes.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
enum SerializedTypeID
|
||||
{
|
||||
// special types
|
||||
STI_UNKNOWN = -2,
|
||||
STI_DONE = -1,
|
||||
STI_NOTPRESENT = 0,
|
||||
|
||||
// // types (common)
|
||||
STI_UINT16 = 1,
|
||||
STI_UINT32 = 2,
|
||||
STI_UINT64 = 3,
|
||||
STI_HASH128 = 4,
|
||||
STI_HASH256 = 5,
|
||||
STI_AMOUNT = 6,
|
||||
STI_VL = 7,
|
||||
STI_ACCOUNT = 8,
|
||||
// 9-13 are reserved
|
||||
STI_OBJECT = 14,
|
||||
STI_ARRAY = 15,
|
||||
|
||||
// types (uncommon)
|
||||
STI_UINT8 = 16,
|
||||
STI_HASH160 = 17,
|
||||
STI_PATHSET = 18,
|
||||
STI_VECTOR256 = 19,
|
||||
|
||||
// high level types
|
||||
// cannot be serialized inside other types
|
||||
STI_TRANSACTION = 10001,
|
||||
STI_LEDGERENTRY = 10002,
|
||||
STI_VALIDATION = 10003,
|
||||
STI_METADATA = 10004,
|
||||
};
|
||||
|
||||
// constexpr
|
||||
inline
|
||||
int
|
||||
field_code(SerializedTypeID id, int index)
|
||||
{
|
||||
return (static_cast<int>(id) << 16) | index;
|
||||
}
|
||||
|
||||
// constexpr
|
||||
inline
|
||||
int
|
||||
field_code(int id, int index)
|
||||
{
|
||||
return (id << 16) | index;
|
||||
}
|
||||
|
||||
/** Identifies fields.
|
||||
|
||||
Fields are necessary to tag data in signed transactions so that
|
||||
the binary format of the transaction can be canonicalized.
|
||||
|
||||
There are two categories of these fields:
|
||||
|
||||
1. Those that are created at compile time.
|
||||
2. Those that are created at run time.
|
||||
|
||||
Both are always const. Category 1 can only be created in FieldNames.cpp.
|
||||
This is enforced at compile time. Category 2 can only be created by
|
||||
calling getField with an as yet unused fieldType and fieldValue (or the
|
||||
equivalent fieldCode).
|
||||
|
||||
Each SField, once constructed, lives until program termination, and there
|
||||
is only one instance per fieldType/fieldValue pair which serves the entire
|
||||
application.
|
||||
*/
|
||||
class SField
|
||||
{
|
||||
public:
|
||||
typedef const SField& ref;
|
||||
typedef SField const* ptr;
|
||||
|
||||
enum
|
||||
{
|
||||
sMD_Never = 0x00,
|
||||
sMD_ChangeOrig = 0x01, // original value when it changes
|
||||
sMD_ChangeNew = 0x02, // new value when it changes
|
||||
sMD_DeleteFinal = 0x04, // final value when it is deleted
|
||||
sMD_Create = 0x08, // value when it's created
|
||||
sMD_Always = 0x10, // value when node containing it is affected at all
|
||||
sMD_Default = sMD_ChangeOrig | sMD_ChangeNew | sMD_DeleteFinal | sMD_Create
|
||||
};
|
||||
|
||||
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;
|
||||
#ifndef _MSC_VER
|
||||
SField(SField&&) = default;
|
||||
#else // remove this when VS gets defaulted move members
|
||||
SField(SField&& sf)
|
||||
: fieldCode (std::move(sf.fieldCode))
|
||||
, fieldType (std::move(sf.fieldType))
|
||||
, fieldValue (std::move(sf.fieldValue))
|
||||
, fieldName (std::move(sf.fieldName))
|
||||
, fieldMeta (std::move(sf.fieldMeta))
|
||||
, fieldNum (std::move(sf.fieldNum))
|
||||
, signingField (std::move(sf.signingField))
|
||||
, rawJsonName (std::move(sf.rawJsonName))
|
||||
, jsonName (rawJsonName.c_str ())
|
||||
{}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// These constructors can only be called from FieldNames.cpp
|
||||
SField (SerializedTypeID tid, int fv, const char* fn,
|
||||
int meta = sMD_Default, bool signing = true);
|
||||
explicit SField (int fc);
|
||||
SField (SerializedTypeID id, int val);
|
||||
|
||||
public:
|
||||
// getField will dynamically construct a new SField if necessary
|
||||
static SField::ref getField (int fieldCode);
|
||||
static SField::ref getField (std::string const& 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;
|
||||
}
|
||||
|
||||
// A discardable field is one that cannot be serialized, and
|
||||
// should be discarded during serialization,like 'hash'.
|
||||
// You cannot serialize an object's hash inside that object,
|
||||
// but you can have it in the JSON representation.
|
||||
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);
|
||||
|
||||
struct make; // public, but still an implementation detail
|
||||
|
||||
private:
|
||||
static int num;
|
||||
};
|
||||
|
||||
extern SField const sfInvalid;
|
||||
extern SField const sfGeneric;
|
||||
extern SField const sfLedgerEntry;
|
||||
extern SField const sfTransaction;
|
||||
extern SField const sfValidation;
|
||||
extern SField const sfMetadata;
|
||||
|
||||
// 8-bit integers
|
||||
extern SField const sfCloseResolution;
|
||||
extern SField const sfTemplateEntryType;
|
||||
extern SField const sfTransactionResult;
|
||||
|
||||
// 16-bit integers
|
||||
extern SField const sfLedgerEntryType;
|
||||
extern SField const sfTransactionType;
|
||||
|
||||
// 32-bit integers (common)
|
||||
extern SField const sfFlags;
|
||||
extern SField const sfSourceTag;
|
||||
extern SField const sfSequence;
|
||||
extern SField const sfPreviousTxnLgrSeq;
|
||||
extern SField const sfLedgerSequence;
|
||||
extern SField const sfCloseTime;
|
||||
extern SField const sfParentCloseTime;
|
||||
extern SField const sfSigningTime;
|
||||
extern SField const sfExpiration;
|
||||
extern SField const sfTransferRate;
|
||||
extern SField const sfWalletSize;
|
||||
extern SField const sfOwnerCount;
|
||||
extern SField const sfDestinationTag;
|
||||
|
||||
// 32-bit integers (uncommon)
|
||||
extern SField const sfHighQualityIn;
|
||||
extern SField const sfHighQualityOut;
|
||||
extern SField const sfLowQualityIn;
|
||||
extern SField const sfLowQualityOut;
|
||||
extern SField const sfQualityIn;
|
||||
extern SField const sfQualityOut;
|
||||
extern SField const sfStampEscrow;
|
||||
extern SField const sfBondAmount;
|
||||
extern SField const sfLoadFee;
|
||||
extern SField const sfOfferSequence;
|
||||
extern SField const sfFirstLedgerSequence; // Deprecated: do not use
|
||||
extern SField const sfLastLedgerSequence;
|
||||
extern SField const sfTransactionIndex;
|
||||
extern SField const sfOperationLimit;
|
||||
extern SField const sfReferenceFeeUnits;
|
||||
extern SField const sfReserveBase;
|
||||
extern SField const sfReserveIncrement;
|
||||
extern SField const sfSetFlag;
|
||||
extern SField const sfClearFlag;
|
||||
|
||||
// 64-bit integers
|
||||
extern SField const sfIndexNext;
|
||||
extern SField const sfIndexPrevious;
|
||||
extern SField const sfBookNode;
|
||||
extern SField const sfOwnerNode;
|
||||
extern SField const sfBaseFee;
|
||||
extern SField const sfExchangeRate;
|
||||
extern SField const sfLowNode;
|
||||
extern SField const sfHighNode;
|
||||
|
||||
// 128-bit
|
||||
extern SField const sfEmailHash;
|
||||
|
||||
// 256-bit (common)
|
||||
extern SField const sfLedgerHash;
|
||||
extern SField const sfParentHash;
|
||||
extern SField const sfTransactionHash;
|
||||
extern SField const sfAccountHash;
|
||||
extern SField const sfPreviousTxnID;
|
||||
extern SField const sfLedgerIndex;
|
||||
extern SField const sfWalletLocator;
|
||||
extern SField const sfRootIndex;
|
||||
extern SField const sfAccountTxnID;
|
||||
|
||||
// 256-bit (uncommon)
|
||||
extern SField const sfBookDirectory;
|
||||
extern SField const sfInvoiceID;
|
||||
extern SField const sfNickname;
|
||||
extern SField const sfAmendment;
|
||||
extern SField const sfTicketID;
|
||||
|
||||
// 160-bit (common)
|
||||
extern SField const sfTakerPaysCurrency;
|
||||
extern SField const sfTakerPaysIssuer;
|
||||
extern SField const sfTakerGetsCurrency;
|
||||
extern SField const sfTakerGetsIssuer;
|
||||
|
||||
// currency amount (common)
|
||||
extern SField const sfAmount;
|
||||
extern SField const sfBalance;
|
||||
extern SField const sfLimitAmount;
|
||||
extern SField const sfTakerPays;
|
||||
extern SField const sfTakerGets;
|
||||
extern SField const sfLowLimit;
|
||||
extern SField const sfHighLimit;
|
||||
extern SField const sfFee;
|
||||
extern SField const sfSendMax;
|
||||
|
||||
// currency amount (uncommon)
|
||||
extern SField const sfMinimumOffer;
|
||||
extern SField const sfRippleEscrow;
|
||||
extern SField const sfDeliveredAmount;
|
||||
|
||||
// variable length
|
||||
extern SField const sfPublicKey;
|
||||
extern SField const sfMessageKey;
|
||||
extern SField const sfSigningPubKey;
|
||||
extern SField const sfTxnSignature;
|
||||
extern SField const sfGenerator;
|
||||
extern SField const sfSignature;
|
||||
extern SField const sfDomain;
|
||||
extern SField const sfFundCode;
|
||||
extern SField const sfRemoveCode;
|
||||
extern SField const sfExpireCode;
|
||||
extern SField const sfCreateCode;
|
||||
extern SField const sfMemoType;
|
||||
extern SField const sfMemoData;
|
||||
extern SField const sfMemoFormat;
|
||||
|
||||
// account
|
||||
extern SField const sfAccount;
|
||||
extern SField const sfOwner;
|
||||
extern SField const sfDestination;
|
||||
extern SField const sfIssuer;
|
||||
extern SField const sfTarget;
|
||||
extern SField const sfRegularKey;
|
||||
|
||||
// path set
|
||||
extern SField const sfPaths;
|
||||
|
||||
// vector of 256-bit
|
||||
extern SField const sfIndexes;
|
||||
extern SField const sfHashes;
|
||||
extern SField const sfAmendments;
|
||||
|
||||
// inner object
|
||||
// OBJECT/1 is reserved for end of object
|
||||
extern SField const sfTransactionMetaData;
|
||||
extern SField const sfCreatedNode;
|
||||
extern SField const sfDeletedNode;
|
||||
extern SField const sfModifiedNode;
|
||||
extern SField const sfPreviousFields;
|
||||
extern SField const sfFinalFields;
|
||||
extern SField const sfNewFields;
|
||||
extern SField const sfTemplateEntry;
|
||||
extern SField const sfMemo;
|
||||
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
extern SField const sfSigningAccounts;
|
||||
extern SField const sfTxnSignatures;
|
||||
extern SField const sfSignatures;
|
||||
extern SField const sfTemplate;
|
||||
extern SField const sfNecessary;
|
||||
extern SField const sfSufficient;
|
||||
extern SField const sfAffectedNodes;
|
||||
extern SField const sfMemos;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
1611
src/ripple/data/protocol/STAmount.cpp
Normal file
1611
src/ripple/data/protocol/STAmount.cpp
Normal file
File diff suppressed because it is too large
Load Diff
473
src/ripple/data/protocol/STAmount.h
Normal file
473
src/ripple/data/protocol/STAmount.h
Normal file
@@ -0,0 +1,473 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_STAMOUNT_H
|
||||
#define RIPPLE_STAMOUNT_H
|
||||
|
||||
#include <ripple/data/protocol/SField.h>
|
||||
#include <ripple/data/protocol/Serializer.h>
|
||||
#include <ripple/data/protocol/SerializedType.h>
|
||||
|
||||
#include <beast/cxx14/memory.h> // <memory>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// Internal form:
|
||||
// 1: If amount is zero, then value is zero and offset is -100
|
||||
// 2: Otherwise:
|
||||
// legal offset range is -96 to +80 inclusive
|
||||
// value range is 10^15 to (10^16 - 1) inclusive
|
||||
// amount = value * [10 ^ offset]
|
||||
|
||||
// Wire form:
|
||||
// High 8 bits are (offset+142), legal range is, 80 to 22 inclusive
|
||||
// Low 56 bits are value, legal range is 10^15 to (10^16 - 1) inclusive
|
||||
class STAmount : public SerializedType
|
||||
{
|
||||
public:
|
||||
typedef std::uint64_t mantissa_type;
|
||||
typedef int exponent_type;
|
||||
typedef std::pair <mantissa_type, exponent_type> rep;
|
||||
|
||||
private:
|
||||
Issue mIssue;
|
||||
mantissa_type mValue;
|
||||
exponent_type mOffset;
|
||||
bool mIsNative; // A shorthand for isXRP(mIssue).
|
||||
bool mIsNegative;
|
||||
|
||||
public:
|
||||
static const int cMinOffset = -96;
|
||||
static const int cMaxOffset = 80;
|
||||
|
||||
static const std::uint64_t cMinValue = 1000000000000000ull;
|
||||
static const std::uint64_t cMaxValue = 9999999999999999ull;
|
||||
static const std::uint64_t cMaxNative = 9000000000000000000ull;
|
||||
|
||||
// Max native value on network.
|
||||
static const std::uint64_t cMaxNativeN = 100000000000000000ull;
|
||||
static const std::uint64_t cNotNative = 0x8000000000000000ull;
|
||||
static const std::uint64_t cPosNative = 0x4000000000000000ull;
|
||||
|
||||
static std::uint64_t uRateOne;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
struct unchecked { };
|
||||
|
||||
// Calls canonicalize
|
||||
STAmount (SField::ref name, Issue const& issue,
|
||||
mantissa_type mantissa, exponent_type exponent,
|
||||
bool native, bool negative);
|
||||
|
||||
// Does not call canonicalize
|
||||
STAmount (SField::ref name, Issue const& issue,
|
||||
mantissa_type mantissa, exponent_type exponent,
|
||||
bool native, bool negative, unchecked);
|
||||
|
||||
STAmount (SField::ref name, std::int64_t mantissa);
|
||||
|
||||
STAmount (SField::ref name,
|
||||
std::uint64_t mantissa = 0, bool negative = false);
|
||||
|
||||
STAmount (SField::ref name, Issue const& issue,
|
||||
std::uint64_t mantissa = 0, int exponent = 0, bool negative = false);
|
||||
|
||||
STAmount (std::uint64_t mantissa = 0, bool negative = false);
|
||||
|
||||
STAmount (Issue const& issue,
|
||||
std::uint64_t mantissa = 0, int exponent = 0, bool negative = false);
|
||||
|
||||
// VFALCO Is this needed when we have the previous signature?
|
||||
STAmount (Issue const& issue,
|
||||
std::uint32_t mantissa, int exponent = 0, bool negative = false);
|
||||
|
||||
STAmount (Issue const& issue, std::int64_t mantissa, int exponent = 0);
|
||||
|
||||
STAmount (Issue const& issue, int mantissa, int exponent = 0);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
private:
|
||||
static
|
||||
std::unique_ptr<STAmount>
|
||||
construct (SerializerIterator&, SField::ref name);
|
||||
|
||||
public:
|
||||
static
|
||||
STAmount
|
||||
createFromInt64 (SField::ref n, std::int64_t v);
|
||||
|
||||
static
|
||||
std::unique_ptr <SerializedType>
|
||||
deserialize (
|
||||
SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return construct (sit, name);
|
||||
}
|
||||
|
||||
static
|
||||
STAmount
|
||||
saFromRate (std::uint64_t uRate = 0)
|
||||
{
|
||||
return STAmount (noIssue(), uRate, -9, false);
|
||||
}
|
||||
|
||||
static
|
||||
STAmount
|
||||
deserialize (SerializerIterator&);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
int exponent() const noexcept { return mOffset; }
|
||||
bool native() const noexcept { return mIsNative; }
|
||||
bool negative() const noexcept { return mIsNegative; }
|
||||
std::uint64_t mantissa() const noexcept { return mValue; }
|
||||
Issue const& issue() const { return mIssue; }
|
||||
|
||||
// These three are deprecated
|
||||
Currency const& getCurrency() const { return mIssue.currency; }
|
||||
Account const& getIssuer() const { return mIssue.account; }
|
||||
bool isNative() const { return mIsNative; }
|
||||
|
||||
int
|
||||
signum() const noexcept
|
||||
{
|
||||
return mValue ? (mIsNegative ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
/** Returns a zero value with the same issuer and currency. */
|
||||
STAmount
|
||||
zeroed() const
|
||||
{
|
||||
// TODO(tom): what does this next comment mean here?
|
||||
// See https://ripplelabs.atlassian.net/browse/WC-1847?jql=
|
||||
return STAmount (mIssue);
|
||||
}
|
||||
|
||||
// When the currency is XRP, the value in raw unsigned units.
|
||||
std::uint64_t
|
||||
getNValue() const;
|
||||
|
||||
// When the currency is XRP, the value in raw signed units.
|
||||
std::int64_t
|
||||
getSNValue() const;
|
||||
|
||||
// VFALCO TODO This can be a free function or just call the
|
||||
// member on the issue.
|
||||
std::string
|
||||
getHumanCurrency() const;
|
||||
|
||||
void
|
||||
setJson (Json::Value&) const;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
explicit operator bool() const noexcept
|
||||
{
|
||||
return *this != zero;
|
||||
}
|
||||
|
||||
bool isComparable (STAmount const&) const;
|
||||
void throwComparable (STAmount const&) const;
|
||||
|
||||
STAmount& operator+= (STAmount const&);
|
||||
STAmount& operator-= (STAmount const&);
|
||||
STAmount& operator+= (std::uint64_t);
|
||||
STAmount& operator-= (std::uint64_t);
|
||||
|
||||
STAmount& operator= (std::uint64_t);
|
||||
STAmount& operator= (beast::Zero)
|
||||
{
|
||||
clear();
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend STAmount operator+ (STAmount const& v1, STAmount const& v2);
|
||||
friend STAmount operator- (STAmount const& v1, STAmount const& v2);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// Modification
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO Remove this, it is only called from the unit test
|
||||
void roundSelf();
|
||||
|
||||
void setNValue (std::uint64_t v);
|
||||
void setSNValue (std::int64_t);
|
||||
|
||||
void negate()
|
||||
{
|
||||
if (*this != zero)
|
||||
mIsNegative = !mIsNegative;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
// VFALCO: Why -100?
|
||||
mOffset = mIsNative ? 0 : -100;
|
||||
mValue = 0;
|
||||
mIsNegative = false;
|
||||
}
|
||||
|
||||
// Zero while copying currency and issuer.
|
||||
void clear (STAmount const& saTmpl)
|
||||
{
|
||||
clear (saTmpl.mIssue);
|
||||
}
|
||||
|
||||
void clear (Issue const& issue)
|
||||
{
|
||||
setIssue(issue);
|
||||
clear();
|
||||
}
|
||||
|
||||
void setIssuer (Account const& uIssuer)
|
||||
{
|
||||
mIssue.account = uIssuer;
|
||||
setIssue(mIssue);
|
||||
}
|
||||
|
||||
/** Set the Issue for this amount and update mIsNative. */
|
||||
void setIssue (Issue const& issue);
|
||||
|
||||
// VFALCO TODO Rename to setValueOnly (it only sets mantissa and exponent)
|
||||
// Make this private
|
||||
bool setValue (std::string const& sAmount);
|
||||
|
||||
bool setFullValue (std::string const& sAmount,
|
||||
std::string const& sCurrency = "", std::string const& sIssuer = "");
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// SerializedType
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
SerializedTypeID
|
||||
getSType() const override
|
||||
{
|
||||
return STI_AMOUNT;
|
||||
}
|
||||
|
||||
std::string
|
||||
getFullText() const override;
|
||||
|
||||
std::string
|
||||
getText() const override;
|
||||
|
||||
Json::Value
|
||||
getJson (int) const override;
|
||||
|
||||
void
|
||||
add (Serializer& s) const override;
|
||||
|
||||
bool
|
||||
isEquivalent (const SerializedType& t) const override;
|
||||
|
||||
bool
|
||||
isDefault() const override
|
||||
{
|
||||
return (mValue == 0) && mIsNative;
|
||||
}
|
||||
|
||||
private:
|
||||
STAmount*
|
||||
duplicate() const override;
|
||||
|
||||
void canonicalize();
|
||||
void set (std::int64_t v);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Creation
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// VFALCO TODO The parameter type should be Quality not uint64_t
|
||||
STAmount
|
||||
amountFromQuality (std::uint64_t rate);
|
||||
|
||||
STAmount
|
||||
amountFromJson (SField::ref name, Json::Value const& v);
|
||||
|
||||
bool
|
||||
amountFromJsonNoThrow (STAmount& result, Json::Value const& jvSource);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Observers
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline
|
||||
bool
|
||||
isLegalNet (STAmount const& value)
|
||||
{
|
||||
return ! value.native() || (value.mantissa() <= STAmount::cMaxNativeN);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Operators
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool operator== (STAmount const& lhs, STAmount const& rhs);
|
||||
bool operator!= (STAmount const& lhs, STAmount const& rhs);
|
||||
bool operator< (STAmount const& lhs, STAmount const& rhs);
|
||||
bool operator> (STAmount const& lhs, STAmount const& rhs);
|
||||
bool operator<= (STAmount const& lhs, STAmount const& rhs);
|
||||
bool operator>= (STAmount const& lhs, STAmount const& rhs);
|
||||
|
||||
// native currency only
|
||||
bool operator< (STAmount const& lhs, std::uint64_t rhs);
|
||||
bool operator> (STAmount const& lhs, std::uint64_t rhs);
|
||||
bool operator<= (STAmount const& lhs, std::uint64_t rhs);
|
||||
bool operator>= (STAmount const& lhs, std::uint64_t rhs);
|
||||
|
||||
STAmount operator+ (STAmount const& lhs, std::uint64_t rhs);
|
||||
STAmount operator- (STAmount const& lhs, std::uint64_t rhs);
|
||||
STAmount operator- (STAmount const& value);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Arithmetic
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
STAmount
|
||||
divide (STAmount const& v1, STAmount const& v2, Issue const& issue);
|
||||
|
||||
inline
|
||||
STAmount
|
||||
divide (STAmount const& v1, STAmount const& v2, STAmount const& saUnit)
|
||||
{
|
||||
return divide (v1, v2, saUnit.issue());
|
||||
}
|
||||
|
||||
inline
|
||||
STAmount
|
||||
divide (STAmount const& v1, STAmount const& v2)
|
||||
{
|
||||
return divide (v1, v2, v1);
|
||||
}
|
||||
|
||||
STAmount
|
||||
multiply (STAmount const& v1, STAmount const& v2, Issue const& issue);
|
||||
|
||||
inline
|
||||
STAmount
|
||||
multiply (STAmount const& v1, STAmount const& v2, STAmount const& saUnit)
|
||||
{
|
||||
return multiply (v1, v2, saUnit.issue());
|
||||
}
|
||||
|
||||
inline
|
||||
STAmount
|
||||
multiply (STAmount const& v1, STAmount const& v2)
|
||||
{
|
||||
return multiply (v1, v2, v1);
|
||||
}
|
||||
|
||||
void
|
||||
canonicalizeRound (bool native, std::uint64_t& mantissa,
|
||||
int& exponent, bool roundUp);
|
||||
|
||||
/* addRound, subRound can end up rounding if the amount subtracted is too small
|
||||
to make a change. Consder (X-d) where d is very small relative to X.
|
||||
If you ask to round down, then (X-d) should not be X unless d is zero.
|
||||
If you ask to round up, (X+d) should never be X unless d is zero. (Assuming X and d are positive).
|
||||
*/
|
||||
// Add, subtract, multiply, or divide rounding result in specified direction
|
||||
STAmount
|
||||
addRound (STAmount const& v1, STAmount const& v2, bool roundUp);
|
||||
|
||||
STAmount
|
||||
subRound (STAmount const& v1, STAmount const& v2, bool roundUp);
|
||||
|
||||
STAmount
|
||||
mulRound (STAmount const& v1, STAmount const& v2,
|
||||
Issue const& issue, bool roundUp);
|
||||
|
||||
inline
|
||||
STAmount
|
||||
mulRound (STAmount const& v1, STAmount const& v2,
|
||||
STAmount const& saUnit, bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, saUnit.issue(), roundUp);
|
||||
}
|
||||
|
||||
inline
|
||||
STAmount
|
||||
mulRound (STAmount const& v1, STAmount const& v2, bool roundUp)
|
||||
{
|
||||
return mulRound (v1, v2, v1.issue(), roundUp);
|
||||
}
|
||||
|
||||
STAmount
|
||||
divRound (STAmount const& v1, STAmount const& v2,
|
||||
Issue const& issue, bool roundUp);
|
||||
|
||||
inline
|
||||
STAmount
|
||||
divRound (STAmount const& v1, STAmount const& v2,
|
||||
STAmount const& saUnit, bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, saUnit.issue(), roundUp);
|
||||
}
|
||||
|
||||
inline
|
||||
STAmount
|
||||
divRound (STAmount const& v1, STAmount const& v2, bool roundUp)
|
||||
{
|
||||
return divRound (v1, v2, v1.issue(), roundUp);
|
||||
}
|
||||
|
||||
// Someone is offering X for Y, what is the rate?
|
||||
// Rate: smaller is better, the taker wants the most out: in/out
|
||||
// VFALCO TODO Return a Quality object
|
||||
std::uint64_t
|
||||
getRate (STAmount const& offerOut, STAmount const& offerIn);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline bool isXRP(STAmount const& amount)
|
||||
{
|
||||
return isXRP (amount.issue().currency);
|
||||
}
|
||||
|
||||
// VFALCO TODO Make static member accessors for these in STAmount
|
||||
extern const STAmount saZero;
|
||||
extern const STAmount saOne;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
528
src/ripple/data/protocol/STAmount.test.cpp
Normal file
528
src/ripple/data/protocol/STAmount.test.cpp
Normal file
@@ -0,0 +1,528 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/data/protocol/STAmount.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class STAmount_test : public beast::unit_test::suite
|
||||
{
|
||||
public:
|
||||
static STAmount serializeAndDeserialize (STAmount const& s)
|
||||
{
|
||||
Serializer ser;
|
||||
s.add (ser);
|
||||
|
||||
SerializerIterator sit (ser);
|
||||
return STAmount::deserialize (sit);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool roundTest (int n, int d, int m)
|
||||
{
|
||||
// check STAmount rounding
|
||||
STAmount num (noIssue(), n);
|
||||
STAmount den (noIssue(), d);
|
||||
STAmount mul (noIssue(), m);
|
||||
STAmount quot = divide (n, d, noIssue());
|
||||
STAmount res = multiply (quot, mul, noIssue());
|
||||
|
||||
expect (! res.isNative (), "Product should not be native");
|
||||
|
||||
res.roundSelf ();
|
||||
|
||||
STAmount cmp (noIssue(), (n * m) / d);
|
||||
|
||||
expect (! cmp.isNative (), "Comparison amount should not be native");
|
||||
|
||||
if (res != cmp)
|
||||
{
|
||||
cmp.throwComparable (res);
|
||||
|
||||
WriteLog (lsWARNING, STAmount) << "(" << num.getText () << "/" << den.getText () << ") X " << mul.getText () << " = "
|
||||
<< res.getText () << " not " << cmp.getText ();
|
||||
|
||||
fail ("Rounding");
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void mulTest (int a, int b)
|
||||
{
|
||||
STAmount aa (noIssue(), a);
|
||||
STAmount bb (noIssue(), b);
|
||||
STAmount prod1 (multiply (aa, bb, noIssue()));
|
||||
|
||||
expect (! prod1.isNative ());
|
||||
|
||||
STAmount prod2 (noIssue(), static_cast<std::uint64_t> (a) * static_cast<std::uint64_t> (b));
|
||||
|
||||
if (prod1 != prod2)
|
||||
{
|
||||
WriteLog (lsWARNING, STAmount) << "nn(" << aa.getFullText () << " * " << bb.getFullText () << ") = " << prod1.getFullText ()
|
||||
<< " not " << prod2.getFullText ();
|
||||
|
||||
fail ("Multiplication result is not exact");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
aa = a;
|
||||
prod1 = multiply (aa, bb, noIssue());
|
||||
|
||||
if (prod1 != prod2)
|
||||
{
|
||||
WriteLog (lsWARNING, STAmount) << "n(" << aa.getFullText () << " * " << bb.getFullText () << ") = " << prod1.getFullText ()
|
||||
<< " not " << prod2.getFullText ();
|
||||
fail ("Multiplication result is not exact");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testSetValue ()
|
||||
{
|
||||
testcase ("set value");
|
||||
|
||||
STAmount saTmp;
|
||||
|
||||
#if 0
|
||||
// Check native floats
|
||||
saTmp.setFullValue ("1^0");
|
||||
BOOST_CHECK_MESSAGE (SYSTEM_CURRENCY_PARTS == saTmp.getNValue (), "float integer failed");
|
||||
saTmp.setFullValue ("0^1");
|
||||
BOOST_CHECK_MESSAGE (SYSTEM_CURRENCY_PARTS / 10 == saTmp.getNValue (), "float fraction failed");
|
||||
saTmp.setFullValue ("0^12");
|
||||
BOOST_CHECK_MESSAGE (12 * SYSTEM_CURRENCY_PARTS / 100 == saTmp.getNValue (), "float fraction failed");
|
||||
saTmp.setFullValue ("1^2");
|
||||
BOOST_CHECK_MESSAGE (SYSTEM_CURRENCY_PARTS + (2 * SYSTEM_CURRENCY_PARTS / 10) == saTmp.getNValue (), "float combined failed");
|
||||
#endif
|
||||
|
||||
// Check native integer
|
||||
saTmp.setFullValue ("1");
|
||||
expect (1 == saTmp.getNValue (), "should be equal");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testNativeCurrency ()
|
||||
{
|
||||
testcase ("native currency");
|
||||
STAmount zeroSt, one (1), hundred (100);
|
||||
// VFALCO NOTE Why repeat "STAmount fail" so many times??
|
||||
unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
|
||||
unexpected (!zeroSt.isNative (), "STAmount fail");
|
||||
unexpected (!hundred.isNative (), "STAmount fail");
|
||||
unexpected (zeroSt != zero, "STAmount fail");
|
||||
unexpected (one == zero, "STAmount fail");
|
||||
unexpected (hundred == zero, "STAmount fail");
|
||||
unexpected ((zeroSt < zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt < one), "STAmount fail");
|
||||
unexpected (! (zeroSt < hundred), "STAmount fail");
|
||||
unexpected ((one < zeroSt), "STAmount fail");
|
||||
unexpected ((one < one), "STAmount fail");
|
||||
unexpected (! (one < hundred), "STAmount fail");
|
||||
unexpected ((hundred < zeroSt), "STAmount fail");
|
||||
unexpected ((hundred < one), "STAmount fail");
|
||||
unexpected ((hundred < hundred), "STAmount fail");
|
||||
unexpected ((zeroSt > zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt > one), "STAmount fail");
|
||||
unexpected ((zeroSt > hundred), "STAmount fail");
|
||||
unexpected (! (one > zeroSt), "STAmount fail");
|
||||
unexpected ((one > one), "STAmount fail");
|
||||
unexpected ((one > hundred), "STAmount fail");
|
||||
unexpected (! (hundred > zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred > one), "STAmount fail");
|
||||
unexpected ((hundred > hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt <= zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt <= one), "STAmount fail");
|
||||
unexpected (! (zeroSt <= hundred), "STAmount fail");
|
||||
unexpected ((one <= zeroSt), "STAmount fail");
|
||||
unexpected (! (one <= one), "STAmount fail");
|
||||
unexpected (! (one <= hundred), "STAmount fail");
|
||||
unexpected ((hundred <= zeroSt), "STAmount fail");
|
||||
unexpected ((hundred <= one), "STAmount fail");
|
||||
unexpected (! (hundred <= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt >= zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt >= one), "STAmount fail");
|
||||
unexpected ((zeroSt >= hundred), "STAmount fail");
|
||||
unexpected (! (one >= zeroSt), "STAmount fail");
|
||||
unexpected (! (one >= one), "STAmount fail");
|
||||
unexpected ((one >= hundred), "STAmount fail");
|
||||
unexpected (! (hundred >= zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred >= one), "STAmount fail");
|
||||
unexpected (! (hundred >= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt == zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt == one), "STAmount fail");
|
||||
unexpected ((zeroSt == hundred), "STAmount fail");
|
||||
unexpected ((one == zeroSt), "STAmount fail");
|
||||
unexpected (! (one == one), "STAmount fail");
|
||||
unexpected ((one == hundred), "STAmount fail");
|
||||
unexpected ((hundred == zeroSt), "STAmount fail");
|
||||
unexpected ((hundred == one), "STAmount fail");
|
||||
unexpected (! (hundred == hundred), "STAmount fail");
|
||||
unexpected ((zeroSt != zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt != one), "STAmount fail");
|
||||
unexpected (! (zeroSt != hundred), "STAmount fail");
|
||||
unexpected (! (one != zeroSt), "STAmount fail");
|
||||
unexpected ((one != one), "STAmount fail");
|
||||
unexpected (! (one != hundred), "STAmount fail");
|
||||
unexpected (! (hundred != zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred != one), "STAmount fail");
|
||||
unexpected ((hundred != hundred), "STAmount fail");
|
||||
unexpected (STAmount ().getText () != "0", "STAmount fail");
|
||||
unexpected (STAmount (31).getText () != "31", "STAmount fail");
|
||||
unexpected (STAmount (310).getText () != "310", "STAmount fail");
|
||||
unexpected (to_string (Currency ()) != "XRP", "cHC(XRP)");
|
||||
Currency c;
|
||||
unexpected (!to_currency (c, "USD"), "create USD currency");
|
||||
unexpected (to_string (c) != "USD", "check USD currency");
|
||||
|
||||
const std::string cur = "015841551A748AD2C1F76FF6ECB0CCCD00000000";
|
||||
unexpected (!to_currency (c, cur), "create custom currency");
|
||||
unexpected (to_string (c) != cur, "check custom currency");
|
||||
unexpected (c != Currency (cur), "check custom currency");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testCustomCurrency ()
|
||||
{
|
||||
testcase ("custom currency");
|
||||
STAmount zeroSt (noIssue()), one (noIssue(), 1), hundred (noIssue(), 100);
|
||||
unexpected (serializeAndDeserialize (zeroSt) != zeroSt, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (one) != one, "STAmount fail");
|
||||
unexpected (serializeAndDeserialize (hundred) != hundred, "STAmount fail");
|
||||
unexpected (zeroSt.isNative (), "STAmount fail");
|
||||
unexpected (hundred.isNative (), "STAmount fail");
|
||||
unexpected (zeroSt != zero, "STAmount fail");
|
||||
unexpected (one == zero, "STAmount fail");
|
||||
unexpected (hundred == zero, "STAmount fail");
|
||||
unexpected ((zeroSt < zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt < one), "STAmount fail");
|
||||
unexpected (! (zeroSt < hundred), "STAmount fail");
|
||||
unexpected ((one < zeroSt), "STAmount fail");
|
||||
unexpected ((one < one), "STAmount fail");
|
||||
unexpected (! (one < hundred), "STAmount fail");
|
||||
unexpected ((hundred < zeroSt), "STAmount fail");
|
||||
unexpected ((hundred < one), "STAmount fail");
|
||||
unexpected ((hundred < hundred), "STAmount fail");
|
||||
unexpected ((zeroSt > zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt > one), "STAmount fail");
|
||||
unexpected ((zeroSt > hundred), "STAmount fail");
|
||||
unexpected (! (one > zeroSt), "STAmount fail");
|
||||
unexpected ((one > one), "STAmount fail");
|
||||
unexpected ((one > hundred), "STAmount fail");
|
||||
unexpected (! (hundred > zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred > one), "STAmount fail");
|
||||
unexpected ((hundred > hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt <= zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt <= one), "STAmount fail");
|
||||
unexpected (! (zeroSt <= hundred), "STAmount fail");
|
||||
unexpected ((one <= zeroSt), "STAmount fail");
|
||||
unexpected (! (one <= one), "STAmount fail");
|
||||
unexpected (! (one <= hundred), "STAmount fail");
|
||||
unexpected ((hundred <= zeroSt), "STAmount fail");
|
||||
unexpected ((hundred <= one), "STAmount fail");
|
||||
unexpected (! (hundred <= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt >= zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt >= one), "STAmount fail");
|
||||
unexpected ((zeroSt >= hundred), "STAmount fail");
|
||||
unexpected (! (one >= zeroSt), "STAmount fail");
|
||||
unexpected (! (one >= one), "STAmount fail");
|
||||
unexpected ((one >= hundred), "STAmount fail");
|
||||
unexpected (! (hundred >= zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred >= one), "STAmount fail");
|
||||
unexpected (! (hundred >= hundred), "STAmount fail");
|
||||
unexpected (! (zeroSt == zeroSt), "STAmount fail");
|
||||
unexpected ((zeroSt == one), "STAmount fail");
|
||||
unexpected ((zeroSt == hundred), "STAmount fail");
|
||||
unexpected ((one == zeroSt), "STAmount fail");
|
||||
unexpected (! (one == one), "STAmount fail");
|
||||
unexpected ((one == hundred), "STAmount fail");
|
||||
unexpected ((hundred == zeroSt), "STAmount fail");
|
||||
unexpected ((hundred == one), "STAmount fail");
|
||||
unexpected (! (hundred == hundred), "STAmount fail");
|
||||
unexpected ((zeroSt != zeroSt), "STAmount fail");
|
||||
unexpected (! (zeroSt != one), "STAmount fail");
|
||||
unexpected (! (zeroSt != hundred), "STAmount fail");
|
||||
unexpected (! (one != zeroSt), "STAmount fail");
|
||||
unexpected ((one != one), "STAmount fail");
|
||||
unexpected (! (one != hundred), "STAmount fail");
|
||||
unexpected (! (hundred != zeroSt), "STAmount fail");
|
||||
unexpected (! (hundred != one), "STAmount fail");
|
||||
unexpected ((hundred != hundred), "STAmount fail");
|
||||
unexpected (STAmount (noIssue()).getText () != "0", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31).getText () != "31", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, 1).getText () != "310", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -1).getText () != "3.1", "STAmount fail");
|
||||
unexpected (STAmount (noIssue(), 31, -2).getText () != "0.31", "STAmount fail");
|
||||
unexpected (multiply (STAmount (noIssue(), 20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 1");
|
||||
unexpected (multiply (STAmount (noIssue(), 20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 2");
|
||||
unexpected (multiply (STAmount (20), STAmount (3), noIssue()).getText () != "60",
|
||||
"STAmount multiply fail 3");
|
||||
unexpected (multiply (STAmount (20), STAmount (3), xrpIssue ()).getText () != "60",
|
||||
"STAmount multiply fail 4");
|
||||
|
||||
if (divide (STAmount (noIssue(), 60), STAmount (3), noIssue()).getText () != "20")
|
||||
{
|
||||
WriteLog (lsFATAL, STAmount) << "60/3 = " <<
|
||||
divide (STAmount (noIssue(), 60),
|
||||
STAmount (3), noIssue()).getText ();
|
||||
fail ("STAmount divide fail");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), noIssue()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
unexpected (divide (STAmount (noIssue(), 60), STAmount (noIssue(), 3), xrpIssue ()).getText () != "20",
|
||||
"STAmount divide fail");
|
||||
|
||||
STAmount a1 (noIssue(), 60), a2 (noIssue(), 10, -1);
|
||||
|
||||
unexpected (divide (a2, a1, noIssue()) != amountFromQuality (getRate (a1, a2)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
|
||||
unexpected (divide (a1, a2, noIssue()) != amountFromQuality (getRate (a2, a1)),
|
||||
"STAmount setRate(getRate) fail");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testArithmetic ()
|
||||
{
|
||||
testcase ("arithmetic");
|
||||
|
||||
CBigNum b;
|
||||
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
std::uint64_t r = rand ();
|
||||
r <<= 32;
|
||||
r |= rand ();
|
||||
b.setuint64 (r);
|
||||
|
||||
if (b.getuint64 () != r)
|
||||
{
|
||||
WriteLog (lsFATAL, STAmount) << r << " != " << b.getuint64 () << " " << b.ToString (16);
|
||||
fail ("setull64/getull64 failure");
|
||||
}
|
||||
else
|
||||
{
|
||||
pass ();
|
||||
}
|
||||
}
|
||||
|
||||
// Test currency multiplication and division operations such as
|
||||
// convertToDisplayAmount, convertToInternalAmount, getRate, getClaimed, and getNeeded
|
||||
|
||||
unexpected (getRate (STAmount (1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 1");
|
||||
|
||||
unexpected (getRate (STAmount (10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 2");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 3");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 4");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 1), STAmount (10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 5");
|
||||
|
||||
unexpected (getRate (STAmount (noIssue(), 10), STAmount (1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 6");
|
||||
|
||||
unexpected (getRate (STAmount (1), STAmount (noIssue(), 10)) != (((100ull - 14) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 7");
|
||||
|
||||
unexpected (getRate (STAmount (10), STAmount (noIssue(), 1)) != (((100ull - 16) << (64 - 8)) | 1000000000000000ull),
|
||||
"STAmount getRate fail 8");
|
||||
|
||||
roundTest (1, 3, 3);
|
||||
roundTest (2, 3, 9);
|
||||
roundTest (1, 7, 21);
|
||||
roundTest (1, 2, 4);
|
||||
roundTest (3, 9, 18);
|
||||
roundTest (7, 11, 44);
|
||||
|
||||
for (int i = 0; i <= 100000; ++i)
|
||||
mulTest (rand () % 10000000, rand () % 10000000);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <class Cond>
|
||||
bool
|
||||
expect (Cond cond, beast::String const& s)
|
||||
{
|
||||
return suite::expect (cond, s.toStdString());
|
||||
}
|
||||
|
||||
template <class Cond>
|
||||
bool
|
||||
expect (Cond cond)
|
||||
{
|
||||
return suite::expect (cond);
|
||||
}
|
||||
|
||||
void testUnderflow ()
|
||||
{
|
||||
testcase ("underflow");
|
||||
|
||||
STAmount bigNative (STAmount::cMaxNative / 2);
|
||||
STAmount bigValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMaxOffset - 1);
|
||||
STAmount smallValue (noIssue(),
|
||||
(STAmount::cMinValue + STAmount::cMaxValue) / 2, STAmount::cMinOffset + 1);
|
||||
STAmount zeroSt (noIssue(), 0);
|
||||
|
||||
STAmount smallXsmall = multiply (smallValue, smallValue, noIssue());
|
||||
|
||||
expect (smallXsmall == zero, "smallXsmall != 0");
|
||||
|
||||
STAmount bigDsmall = divide (smallValue, bigValue, noIssue());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("small/big != 0: ") + bigDsmall.getText ());
|
||||
|
||||
#if 0
|
||||
// TODO(tom): this test makes no sense - we should have no way to have
|
||||
// the currency not be XRP while the account is XRP.
|
||||
bigDsmall = divide (smallValue, bigNative, noCurrency(), xrpAccount ());
|
||||
#endif
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("small/bigNative != 0: ") + bigDsmall.getText ());
|
||||
|
||||
bigDsmall = divide (smallValue, bigValue, xrpIssue ());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("(small/big)->N != 0: ") + bigDsmall.getText ());
|
||||
|
||||
bigDsmall = divide (smallValue, bigNative, xrpIssue ());
|
||||
|
||||
expect (bigDsmall == zero, beast::String ("(small/bigNative)->N != 0: ") + bigDsmall.getText ());
|
||||
|
||||
// very bad offer
|
||||
std::uint64_t r = getRate (smallValue, bigValue);
|
||||
|
||||
expect (r == 0, "getRate(smallOut/bigIn) != 0");
|
||||
|
||||
// very good offer
|
||||
r = getRate (bigValue, smallValue);
|
||||
|
||||
expect (r == 0, "getRate(smallIn/bigOUt) != 0");
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void testRounding ()
|
||||
{
|
||||
// VFALCO TODO There are no actual tests here, just printed output?
|
||||
// Change this to actually do something.
|
||||
|
||||
#if 0
|
||||
beginTestCase ("rounding ");
|
||||
|
||||
std::uint64_t value = 25000000000000000ull;
|
||||
int offset = -14;
|
||||
canonicalizeRound (false, value, offset, true);
|
||||
|
||||
STAmount one (noIssue(), 1);
|
||||
STAmount two (noIssue(), 2);
|
||||
STAmount three (noIssue(), 3);
|
||||
|
||||
STAmount oneThird1 = divRound (one, three, noIssue(), false);
|
||||
STAmount oneThird2 = divide (one, three, noIssue());
|
||||
STAmount oneThird3 = divRound (one, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << oneThird1;
|
||||
WriteLog (lsINFO, STAmount) << oneThird2;
|
||||
WriteLog (lsINFO, STAmount) << oneThird3;
|
||||
|
||||
STAmount twoThird1 = divRound (two, three, noIssue(), false);
|
||||
STAmount twoThird2 = divide (two, three, noIssue());
|
||||
STAmount twoThird3 = divRound (two, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << twoThird1;
|
||||
WriteLog (lsINFO, STAmount) << twoThird2;
|
||||
WriteLog (lsINFO, STAmount) << twoThird3;
|
||||
|
||||
STAmount oneA = mulRound (oneThird1, three, noIssue(), false);
|
||||
STAmount oneB = multiply (oneThird2, three, noIssue());
|
||||
STAmount oneC = mulRound (oneThird3, three, noIssue(), true);
|
||||
WriteLog (lsINFO, STAmount) << oneA;
|
||||
WriteLog (lsINFO, STAmount) << oneB;
|
||||
WriteLog (lsINFO, STAmount) << oneC;
|
||||
|
||||
STAmount fourThirdsA = addRound (twoThird2, twoThird2, false);
|
||||
STAmount fourThirdsB = twoThird2 + twoThird2;
|
||||
STAmount fourThirdsC = addRound (twoThird2, twoThird2, true);
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsA;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsB;
|
||||
WriteLog (lsINFO, STAmount) << fourThirdsC;
|
||||
|
||||
STAmount dripTest1 = mulRound (twoThird2, two, xrpIssue (), false);
|
||||
STAmount dripTest2 = multiply (twoThird2, two, xrpIssue ());
|
||||
STAmount dripTest3 = mulRound (twoThird2, two, xrpIssue (), true);
|
||||
WriteLog (lsINFO, STAmount) << dripTest1;
|
||||
WriteLog (lsINFO, STAmount) << dripTest2;
|
||||
WriteLog (lsINFO, STAmount) << dripTest3;
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run ()
|
||||
{
|
||||
testSetValue ();
|
||||
testNativeCurrency ();
|
||||
testCustomCurrency ();
|
||||
testArithmetic ();
|
||||
testUnderflow ();
|
||||
testRounding ();
|
||||
}
|
||||
};
|
||||
|
||||
BEAST_DEFINE_TESTSUITE(STAmount,ripple_data,ripple);
|
||||
|
||||
} // ripple
|
||||
150
src/ripple/data/protocol/STArray.cpp
Normal file
150
src/ripple/data/protocol/STArray.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/Log.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
std::unique_ptr<SerializedType>
|
||||
STArray::deserialize (SerializerIterator& sit, SField::ref field)
|
||||
{
|
||||
std::unique_ptr <STArray> ret (std::make_unique <STArray> (field));
|
||||
vector& value (ret->getValue ());
|
||||
|
||||
while (!sit.empty ())
|
||||
{
|
||||
int type, field;
|
||||
sit.getFieldID (type, field);
|
||||
|
||||
if ((type == STI_ARRAY) && (field == 1))
|
||||
break;
|
||||
|
||||
if ((type == STI_OBJECT) && (field == 1))
|
||||
{
|
||||
WriteLog (lsWARNING, STObject) <<
|
||||
"Encountered array with end of object marker";
|
||||
throw std::runtime_error ("Illegal terminator in array");
|
||||
}
|
||||
|
||||
SField::ref fn = SField::getField (type, field);
|
||||
|
||||
if (fn.isInvalid ())
|
||||
{
|
||||
WriteLog (lsTRACE, STObject) <<
|
||||
"Unknown field: " << type << "/" << field;
|
||||
throw std::runtime_error ("Unknown field");
|
||||
}
|
||||
|
||||
if (fn.fieldType != STI_OBJECT)
|
||||
{
|
||||
WriteLog (lsTRACE, STObject) << "Array contains non-object";
|
||||
throw std::runtime_error ("Non-object in array");
|
||||
}
|
||||
|
||||
value.push_back (new STObject (fn));
|
||||
value.rbegin ()->set (sit, 1);
|
||||
}
|
||||
return std::move (ret);
|
||||
}
|
||||
|
||||
std::string STArray::getFullText () const
|
||||
{
|
||||
std::string r = "[";
|
||||
|
||||
bool first = true;
|
||||
for (STObject const& o : value)
|
||||
{
|
||||
if (!first)
|
||||
r += ",";
|
||||
|
||||
r += o.getFullText ();
|
||||
first = false;
|
||||
}
|
||||
|
||||
r += "]";
|
||||
return r;
|
||||
}
|
||||
|
||||
std::string STArray::getText () const
|
||||
{
|
||||
std::string r = "[";
|
||||
|
||||
bool first = true;
|
||||
for (STObject const& o : value)
|
||||
{
|
||||
if (!first)
|
||||
r += ",";
|
||||
|
||||
r += o.getText ();
|
||||
first = false;
|
||||
}
|
||||
|
||||
r += "]";
|
||||
return r;
|
||||
}
|
||||
|
||||
Json::Value STArray::getJson (int p) const
|
||||
{
|
||||
Json::Value v = Json::arrayValue;
|
||||
int index = 1;
|
||||
for (auto const& object: value)
|
||||
{
|
||||
if (object.getSType () != STI_NOTPRESENT)
|
||||
{
|
||||
Json::Value inner = Json::objectValue;
|
||||
auto const& fname = object.getFName ();
|
||||
auto k = fname.hasName () ? fname.fieldName : std::to_string(index);
|
||||
inner[k] = object.getJson (p);
|
||||
v.append (inner);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void STArray::add (Serializer& s) const
|
||||
{
|
||||
for (STObject const& object : value)
|
||||
{
|
||||
object.addFieldID (s);
|
||||
object.add (s);
|
||||
s.addFieldID (STI_OBJECT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool STArray::isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STArray* v = dynamic_cast<const STArray*> (&t);
|
||||
|
||||
if (!v)
|
||||
{
|
||||
WriteLog (lsDEBUG, STObject) <<
|
||||
"notEquiv " << getFullText() << " not array";
|
||||
return false;
|
||||
}
|
||||
|
||||
return value == v->value;
|
||||
}
|
||||
|
||||
void STArray::sort (bool (*compare) (const STObject&, const STObject&))
|
||||
{
|
||||
value.sort (compare);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
212
src/ripple/data/protocol/STArray.h
Normal file
212
src/ripple/data/protocol/STArray.h
Normal file
@@ -0,0 +1,212 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_STARRAY_H
|
||||
#define RIPPLE_STARRAY_H
|
||||
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <ripple/data/protocol/STObject.h>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class STArray final
|
||||
: public SerializedType
|
||||
, public CountedObject <STArray>
|
||||
{
|
||||
public:
|
||||
static char const* getCountedObjectName () { return "STArray"; }
|
||||
|
||||
typedef boost::ptr_vector<STObject> vector;
|
||||
|
||||
typedef vector::iterator iterator;
|
||||
typedef vector::const_iterator const_iterator;
|
||||
typedef vector::reverse_iterator reverse_iterator;
|
||||
typedef vector::const_reverse_iterator const_reverse_iterator;
|
||||
typedef vector::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)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
virtual ~STArray () { }
|
||||
|
||||
static std::unique_ptr<SerializedType>
|
||||
deserialize (SerializerIterator & sit, SField::ref 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 override;
|
||||
virtual std::string getText () const override;
|
||||
|
||||
virtual Json::Value getJson (int index) const override;
|
||||
virtual void add (Serializer & s) const override;
|
||||
|
||||
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 override
|
||||
{
|
||||
return STI_ARRAY;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const override;
|
||||
virtual bool isDefault () const override
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual STArray* duplicate () const override
|
||||
{
|
||||
return new STArray (*this);
|
||||
}
|
||||
|
||||
private:
|
||||
vector value;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
137
src/ripple/data/protocol/STBitString.h
Normal file
137
src/ripple/data/protocol/STBitString.h
Normal 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_STBITS_H
|
||||
#define RIPPLE_STBITS_H
|
||||
|
||||
#include <ripple/data/protocol/SerializedType.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <std::size_t Bits>
|
||||
class STBitString : public SerializedType
|
||||
{
|
||||
public:
|
||||
typedef base_uint<Bits> BitString;
|
||||
|
||||
STBitString () {}
|
||||
STBitString (SField::ref n) : SerializedType (n) {}
|
||||
STBitString (const BitString& v) : bitString_ (v) {}
|
||||
|
||||
STBitString (SField::ref n, const BitString& v)
|
||||
: SerializedType (n), bitString_ (v)
|
||||
{
|
||||
}
|
||||
|
||||
STBitString (SField::ref n, const char* v) : SerializedType (n)
|
||||
{
|
||||
bitString_.SetHex (v);
|
||||
}
|
||||
|
||||
STBitString (SField::ref n, std::string const& v) : SerializedType (n)
|
||||
{
|
||||
bitString_.SetHex (v);
|
||||
}
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (
|
||||
SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const;
|
||||
|
||||
std::string getText () const
|
||||
{
|
||||
return to_string (bitString_);
|
||||
}
|
||||
|
||||
bool isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STBitString* v = dynamic_cast<const STBitString*> (&t);
|
||||
return v && (bitString_ == v->bitString_);
|
||||
}
|
||||
|
||||
void add (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
assert (fName->fieldType == getSType());
|
||||
s.addBitString<Bits> (bitString_);
|
||||
}
|
||||
|
||||
const BitString& getValue () const
|
||||
{
|
||||
return bitString_;
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
void setValue (base_uint<Bits, Tag> const& v)
|
||||
{
|
||||
bitString_.copyFrom(v);
|
||||
}
|
||||
|
||||
operator BitString () const
|
||||
{
|
||||
return bitString_;
|
||||
}
|
||||
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return bitString_ == zero;
|
||||
}
|
||||
|
||||
private:
|
||||
BitString bitString_;
|
||||
|
||||
STBitString* duplicate () const
|
||||
{
|
||||
return new STBitString (*this);
|
||||
}
|
||||
|
||||
static STBitString* construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STBitString (name, u.getBitString<Bits> ());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
inline SerializedTypeID STBitString<128>::getSType () const
|
||||
{
|
||||
return STI_HASH128;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline SerializedTypeID STBitString<160>::getSType () const
|
||||
{
|
||||
return STI_HASH160;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline SerializedTypeID STBitString<256>::getSType () const
|
||||
{
|
||||
return STI_HASH256;
|
||||
}
|
||||
|
||||
using STHash128 = STBitString<128>;
|
||||
using STHash160 = STBitString<160>;
|
||||
using STHash256 = STBitString<256>;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
181
src/ripple/data/protocol/STInteger.cpp
Normal file
181
src/ripple/data/protocol/STInteger.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/data/protocol/STInteger.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <>
|
||||
SerializedTypeID STUInt8::getSType () const
|
||||
{
|
||||
return STI_UINT8;
|
||||
}
|
||||
|
||||
template <>
|
||||
STUInt8* STUInt8::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt8 (name, u.get8 ());
|
||||
}
|
||||
|
||||
template <>
|
||||
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_);
|
||||
}
|
||||
|
||||
template <>
|
||||
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_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
SerializedTypeID STUInt16::getSType () const
|
||||
{
|
||||
return STI_UINT16;
|
||||
}
|
||||
|
||||
template <>
|
||||
STUInt16* STUInt16::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt16 (name, u.get16 ());
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string STUInt16::getText () const
|
||||
{
|
||||
if (getFName () == sfLedgerEntryType)
|
||||
{
|
||||
auto 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_);
|
||||
}
|
||||
|
||||
template <>
|
||||
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_;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template <>
|
||||
SerializedTypeID STUInt32::getSType () const
|
||||
{
|
||||
return STI_UINT32;
|
||||
}
|
||||
|
||||
template <>
|
||||
STUInt32* STUInt32::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt32 (name, u.get32 ());
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string STUInt32::getText () const
|
||||
{
|
||||
return beast::lexicalCastThrow <std::string> (value_);
|
||||
}
|
||||
|
||||
template <>
|
||||
Json::Value STUInt32::getJson (int) const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
template <>
|
||||
SerializedTypeID STUInt64::getSType () const
|
||||
{
|
||||
return STI_UINT64;
|
||||
}
|
||||
|
||||
template <>
|
||||
STUInt64* STUInt64::construct (SerializerIterator& u, SField::ref name)
|
||||
{
|
||||
return new STUInt64 (name, u.get64 ());
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string STUInt64::getText () const
|
||||
{
|
||||
return beast::lexicalCastThrow <std::string> (value_);
|
||||
}
|
||||
|
||||
template <>
|
||||
Json::Value STUInt64::getJson (int) const
|
||||
{
|
||||
return strHex (value_);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
101
src/ripple/data/protocol/STInteger.h
Normal file
101
src/ripple/data/protocol/STInteger.h
Normal file
@@ -0,0 +1,101 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_STINTEGER_H
|
||||
#define RIPPLE_STINTEGER_H
|
||||
|
||||
#include <ripple/data/protocol/SerializedType.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <typename Integer>
|
||||
class STInteger : public SerializedType
|
||||
{
|
||||
public:
|
||||
explicit STInteger (Integer v) : value_ (v)
|
||||
{
|
||||
}
|
||||
|
||||
STInteger (SField::ref n, Integer v = 0) : SerializedType (n), value_ (v)
|
||||
{
|
||||
}
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (
|
||||
SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_UINT8;
|
||||
}
|
||||
|
||||
Json::Value getJson (int) const;
|
||||
std::string getText () const;
|
||||
|
||||
void add (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
assert (fName->fieldType == getSType ());
|
||||
s.addInteger (value_);
|
||||
}
|
||||
|
||||
Integer getValue () const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
void setValue (Integer v)
|
||||
{
|
||||
value_ = v;
|
||||
}
|
||||
|
||||
operator Integer () const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return value_ == 0;
|
||||
}
|
||||
|
||||
bool isEquivalent (const SerializedType& t) const
|
||||
{
|
||||
const STInteger* v = dynamic_cast<const STInteger*> (&t);
|
||||
return v && (value_ == v->value_);
|
||||
}
|
||||
|
||||
private:
|
||||
Integer value_;
|
||||
|
||||
STInteger* duplicate () const
|
||||
{
|
||||
return new STInteger (*this);
|
||||
}
|
||||
static STInteger* construct (SerializerIterator&, SField::ref f);
|
||||
};
|
||||
|
||||
using STUInt8 = STInteger<unsigned char>;
|
||||
using STUInt16 = STInteger<std::uint16_t>;
|
||||
using STUInt32 = STInteger<std::uint32_t>;
|
||||
using STUInt64 = STInteger<std::uint64_t>;
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
1078
src/ripple/data/protocol/STObject.cpp
Normal file
1078
src/ripple/data/protocol/STObject.cpp
Normal file
File diff suppressed because it is too large
Load Diff
423
src/ripple/data/protocol/STObject.h
Normal file
423
src/ripple/data/protocol/STObject.h
Normal file
@@ -0,0 +1,423 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_STOBJECT_H
|
||||
#define RIPPLE_STOBJECT_H
|
||||
|
||||
#include <ripple/basics/CountedObject.h>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
||||
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::make_unique <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 override
|
||||
{
|
||||
return STI_OBJECT;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType & t) const override;
|
||||
virtual bool isDefault () const override
|
||||
{
|
||||
return mData.empty ();
|
||||
}
|
||||
|
||||
virtual void add (Serializer & s) const override
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
virtual std::string getFullText () const override;
|
||||
virtual std::string getText () const override;
|
||||
|
||||
// TODO(tom): options should be an enum.
|
||||
virtual Json::Value getJson (int options) const override;
|
||||
|
||||
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;
|
||||
Account getFieldAccount160 (SField::ref field) const;
|
||||
|
||||
Blob getFieldVL (SField::ref field) const;
|
||||
STAmount const& getFieldAmount (SField::ref field) const;
|
||||
STPathSet const& 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, uint128 const&);
|
||||
void setFieldH256 (SField::ref field, uint256 const& );
|
||||
void setFieldVL (SField::ref field, Blob const&);
|
||||
void setFieldAccount (SField::ref field, Account const&);
|
||||
void setFieldAccount (SField::ref field, RippleAddress const& addr)
|
||||
{
|
||||
setFieldAccount (field, addr.getAccountID ());
|
||||
}
|
||||
void setFieldAmount (SField::ref field, STAmount const&);
|
||||
void setFieldPathSet (SField::ref field, STPathSet const&);
|
||||
void setFieldV256 (SField::ref field, STVector256 const& v);
|
||||
void setFieldArray (SField::ref field, STArray const& v);
|
||||
|
||||
template <class Tag>
|
||||
void setFieldH160 (SField::ref field, base_uint<160, Tag> const& v)
|
||||
{
|
||||
SerializedType* rf = getPField (field, true);
|
||||
|
||||
if (!rf)
|
||||
throw std::runtime_error ("Field not found");
|
||||
|
||||
if (rf->getSType () == STI_NOTPRESENT)
|
||||
rf = makeFieldPresent (field);
|
||||
|
||||
using Bits = STBitString<160>;
|
||||
if (auto cf = dynamic_cast<Bits*> (rf))
|
||||
cf->setValue (v);
|
||||
else
|
||||
throw std::runtime_error ("Wrong field type");
|
||||
}
|
||||
|
||||
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:
|
||||
virtual STObject* duplicate () const override
|
||||
{
|
||||
return new STObject (*this);
|
||||
}
|
||||
|
||||
// Implementation for getting (most) fields that return by value.
|
||||
//
|
||||
// The remove_cv and remove_reference are necessitated by the STBitString
|
||||
// types. Their getValue returns by const ref. We return those types
|
||||
// by value.
|
||||
template <typename T, typename V =
|
||||
typename std::remove_cv < typename std::remove_reference <
|
||||
decltype (std::declval <T> ().getValue ())>::type >::type >
|
||||
V getFieldByValue (SField::ref field) const
|
||||
{
|
||||
const SerializedType* rf = peekAtPField (field);
|
||||
|
||||
if (!rf)
|
||||
throw std::runtime_error ("Field not found");
|
||||
|
||||
SerializedTypeID id = rf->getSType ();
|
||||
|
||||
if (id == STI_NOTPRESENT)
|
||||
return V (); // optional field not present
|
||||
|
||||
const T* cf = dynamic_cast<const T*> (rf);
|
||||
|
||||
if (!cf)
|
||||
throw std::runtime_error ("Wrong field type");
|
||||
|
||||
return cf->getValue ();
|
||||
}
|
||||
|
||||
// Implementations for getting (most) fields that return by const reference.
|
||||
//
|
||||
// If an absent optional field is deserialized we don't have anything
|
||||
// obvious to return. So we insist on having the call provide an
|
||||
// 'empty' value we return in that circumstance.
|
||||
template <typename T, typename V>
|
||||
V const& getFieldByConstRef (SField::ref field, V const& empty) const
|
||||
{
|
||||
const SerializedType* rf = peekAtPField (field);
|
||||
|
||||
if (!rf)
|
||||
throw std::runtime_error ("Field not found");
|
||||
|
||||
SerializedTypeID id = rf->getSType ();
|
||||
|
||||
if (id == STI_NOTPRESENT)
|
||||
return empty; // optional field not present
|
||||
|
||||
const T* cf = dynamic_cast<const T*> (rf);
|
||||
|
||||
if (!cf)
|
||||
throw std::runtime_error ("Wrong field type");
|
||||
|
||||
return *cf;
|
||||
}
|
||||
|
||||
// Implementation for setting most fields with a setValue() method.
|
||||
template <typename T, typename V>
|
||||
void setFieldUsingSetValue (SField::ref field, V value)
|
||||
{
|
||||
SerializedType* rf = getPField (field, true);
|
||||
|
||||
if (!rf)
|
||||
throw std::runtime_error ("Field not found");
|
||||
|
||||
if (rf->getSType () == STI_NOTPRESENT)
|
||||
rf = makeFieldPresent (field);
|
||||
|
||||
T* cf = dynamic_cast<T*> (rf);
|
||||
|
||||
if (!cf)
|
||||
throw std::runtime_error ("Wrong field type");
|
||||
|
||||
cf->setValue (value);
|
||||
}
|
||||
|
||||
// Implementation for setting fields using assignment
|
||||
template <typename T>
|
||||
void setFieldUsingAssignment (SField::ref field, T const& value)
|
||||
{
|
||||
SerializedType* rf = getPField (field, true);
|
||||
|
||||
if (!rf)
|
||||
throw std::runtime_error ("Field not found");
|
||||
|
||||
if (rf->getSType () == STI_NOTPRESENT)
|
||||
rf = makeFieldPresent (field);
|
||||
|
||||
T* cf = dynamic_cast<T*> (rf);
|
||||
|
||||
if (!cf)
|
||||
throw std::runtime_error ("Wrong field type");
|
||||
|
||||
(*cf) = value;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::ptr_vector<SerializedType> mData;
|
||||
const SOTemplate* mType;
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
744
src/ripple/data/protocol/STParsedJSON.cpp
Normal file
744
src/ripple/data/protocol/STParsedJSON.cpp
Normal file
@@ -0,0 +1,744 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/StringUtilities.h>
|
||||
#include <ripple/data/protocol/STInteger.h>
|
||||
#include <beast/module/core/text/LexicalCast.h>
|
||||
#include <cassert>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
template <typename T, typename U>
|
||||
static T range_check_cast (U value, T minimum, T maximum)
|
||||
{
|
||||
if ((value < minimum) || (value > maximum))
|
||||
throw std::runtime_error ("Value out of range");
|
||||
|
||||
return static_cast<T> (value);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
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 (amountFromJson (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;
|
||||
}
|
||||
|
||||
Json::Value const& account = pathEl["account"];
|
||||
Json::Value const& currency = pathEl["currency"];
|
||||
Json::Value const& issuer = pathEl["issuer"];
|
||||
bool hasCurrency = false;
|
||||
Account uAccount, uIssuer;
|
||||
Currency uCurrency;
|
||||
|
||||
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 (!to_currency (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
|
||||
{
|
||||
Account account;
|
||||
account.SetHex (strValue);
|
||||
data.push_back (new STAccount (field, account));
|
||||
}
|
||||
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 || (sub_object_->getFName().fieldType != STI_OBJECT))
|
||||
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
|
||||
84
src/ripple/data/protocol/STParsedJSON.h
Normal file
84
src/ripple/data/protocol/STParsedJSON.h
Normal 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
|
||||
64
src/ripple/data/protocol/SerializedObjectTemplate.cpp
Normal file
64
src/ripple/data/protocol/SerializedObjectTemplate.cpp
Normal 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
|
||||
94
src/ripple/data/protocol/SerializedObjectTemplate.h
Normal file
94
src/ripple/data/protocol/SerializedObjectTemplate.h
Normal 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
|
||||
236
src/ripple/data/protocol/SerializedType.h
Normal file
236
src/ripple/data/protocol/SerializedType.h
Normal 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.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_SERIALIZEDTYPE_H
|
||||
#define RIPPLE_SERIALIZEDTYPE_H
|
||||
|
||||
#include <ripple/data/protocol/SField.h>
|
||||
#include <ripple/data/protocol/Serializer.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
// VFALCO TODO fix this restriction on copy assignment.
|
||||
//
|
||||
// CAUTION: Do not create a vector (or similar container) of any object derived
|
||||
// from SerializedType. Use Boost ptr_* containers. The copy assignment operator
|
||||
// of SerializedType has semantics that will cause contained types to change
|
||||
// their names when an object is deleted because copy assignment is used to
|
||||
// "slide down" the remaining types and this will not copy the field
|
||||
// name. Changing the copy assignment operator to copy the field name breaks the
|
||||
// use of copy assignment just to copy values, which is used in the transaction
|
||||
// engine code.
|
||||
|
||||
// VFALCO TODO Remove this unused enum
|
||||
/*
|
||||
enum PathFlags
|
||||
{
|
||||
PF_END = 0x00, // End of current path & path list.
|
||||
PF_BOUNDARY = 0xFF, // End of current path & new path follows.
|
||||
|
||||
PF_ACCOUNT = 0x01,
|
||||
PF_OFFER = 0x02,
|
||||
|
||||
PF_WANTED_CURRENCY = 0x10,
|
||||
PF_WANTED_ISSUER = 0x20,
|
||||
PF_REDEEM = 0x40,
|
||||
PF_ISSUE = 0x80,
|
||||
};
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A type which can be exported to a well known binary format.
|
||||
|
||||
A SerializedType:
|
||||
- Always a field
|
||||
- Can always go inside an eligible enclosing SerializedType
|
||||
(such as STArray)
|
||||
- Has a field name
|
||||
|
||||
|
||||
Like JSON, a SerializedObject is a basket which has rules
|
||||
on what it can hold.
|
||||
*/
|
||||
// VFALCO TODO Document this as it looks like a central class.
|
||||
// STObject is derived from it
|
||||
//
|
||||
class SerializedType
|
||||
{
|
||||
public:
|
||||
SerializedType () : fName (&sfGeneric)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit SerializedType (SField::ref n) : fName (&n)
|
||||
{
|
||||
assert (fName);
|
||||
}
|
||||
|
||||
virtual ~SerializedType () = default;
|
||||
|
||||
//
|
||||
// overridables
|
||||
//
|
||||
|
||||
virtual
|
||||
SerializedTypeID
|
||||
getSType () const
|
||||
{
|
||||
return STI_NOTPRESENT;
|
||||
}
|
||||
|
||||
virtual
|
||||
std::string
|
||||
getFullText() const;
|
||||
|
||||
// just the value
|
||||
virtual
|
||||
std::string
|
||||
getText() const
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
virtual
|
||||
Json::Value getJson (int /*options*/) const
|
||||
{
|
||||
return getText();
|
||||
}
|
||||
|
||||
virtual
|
||||
void
|
||||
add (Serializer& s) const
|
||||
{
|
||||
// VFALCO Why not just make this pure virtual?
|
||||
assert (false);
|
||||
}
|
||||
|
||||
virtual
|
||||
bool
|
||||
isEquivalent (SerializedType const& t) const;
|
||||
|
||||
virtual
|
||||
bool
|
||||
isDefault () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
// VFALCO TODO Return std::unique_ptr <SerializedType>
|
||||
virtual
|
||||
SerializedType*
|
||||
duplicate () const
|
||||
{
|
||||
return new SerializedType (*fName);
|
||||
}
|
||||
|
||||
public:
|
||||
//
|
||||
// members
|
||||
//
|
||||
|
||||
static
|
||||
std::unique_ptr <SerializedType>
|
||||
deserialize (SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (new SerializedType (name));
|
||||
}
|
||||
|
||||
/** A SerializedType is a field.
|
||||
This sets the name.
|
||||
*/
|
||||
void setFName (SField::ref n)
|
||||
{
|
||||
fName = &n;
|
||||
assert (fName);
|
||||
}
|
||||
SField::ref getFName () const
|
||||
{
|
||||
return *fName;
|
||||
}
|
||||
std::unique_ptr<SerializedType> clone () const
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (duplicate ());
|
||||
}
|
||||
|
||||
|
||||
void addFieldID (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
s.addFieldID (fName->fieldType, fName->fieldValue);
|
||||
}
|
||||
|
||||
SerializedType& operator= (const SerializedType& t);
|
||||
|
||||
bool operator== (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () == t.getSType ()) && isEquivalent (t);
|
||||
}
|
||||
bool operator!= (const SerializedType& t) const
|
||||
{
|
||||
return (getSType () != t.getSType ()) || !isEquivalent (t);
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D& downcast()
|
||||
{
|
||||
D* ptr = dynamic_cast<D*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <class D>
|
||||
D const& downcast() const
|
||||
{
|
||||
D const * ptr = dynamic_cast<D const*> (this);
|
||||
if (ptr == nullptr)
|
||||
throw std::runtime_error ("type mismatch");
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
// VFALCO TODO make accessors for this
|
||||
SField::ptr fName;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline SerializedType* new_clone (const SerializedType& s)
|
||||
{
|
||||
SerializedType* const copy (s.clone ().release ());
|
||||
assert (typeid (*copy) == typeid (s));
|
||||
return copy;
|
||||
}
|
||||
|
||||
inline void delete_clone (const SerializedType* s)
|
||||
{
|
||||
boost::checked_delete (s);
|
||||
}
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& out, const SerializedType& t)
|
||||
{
|
||||
return out << t.getFullText ();
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
403
src/ripple/data/protocol/SerializedTypes.cpp
Normal file
403
src/ripple/data/protocol/SerializedTypes.cpp
Normal file
@@ -0,0 +1,403 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/Log.h>
|
||||
#include <ripple/basics/StringUtilities.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
const STAmount saZero (noIssue(), 0u);
|
||||
const STAmount saOne (noIssue(), 1u);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string SerializedType::getFullText () const
|
||||
{
|
||||
std::string ret;
|
||||
|
||||
if (getSType () != STI_NOTPRESENT)
|
||||
{
|
||||
if (fName->hasName ())
|
||||
{
|
||||
ret = fName->fieldName;
|
||||
ret += " = ";
|
||||
}
|
||||
|
||||
ret += getText ();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// STVariableLength
|
||||
//
|
||||
|
||||
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
|
||||
{
|
||||
Account 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
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
assert (fName->fieldType == STI_VECTOR256);
|
||||
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, Account const& v) : STVariableLength (n)
|
||||
{
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
}
|
||||
|
||||
bool STAccount::isValueH160 () const
|
||||
{
|
||||
return peekValue ().size () == (160 / 8);
|
||||
}
|
||||
|
||||
RippleAddress STAccount::getValueNCA () const
|
||||
{
|
||||
RippleAddress a;
|
||||
Account account;
|
||||
|
||||
if (getValueH160 (account))
|
||||
a.setAccountID (account);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
void STAccount::setValueNCA (RippleAddress const& nca)
|
||||
{
|
||||
setValueH160 (nca.getAccountID ());
|
||||
}
|
||||
|
||||
std::size_t
|
||||
STPathElement::get_hash (STPathElement const& element)
|
||||
{
|
||||
std::size_t hash_account = 2654435761;
|
||||
std::size_t hash_currency = 2654435761;
|
||||
std::size_t hash_issuer = 2654435761;
|
||||
|
||||
// NIKB NOTE: This doesn't have to be a secure hash as speed is more
|
||||
// important. We don't even really need to fully hash the whole
|
||||
// base_uint here, as a few bytes would do for our use.
|
||||
|
||||
for (auto const x : element.getAccountID ())
|
||||
hash_account += (hash_account * 257) ^ x;
|
||||
|
||||
for (auto const x : element.getCurrency ())
|
||||
hash_currency += (hash_currency * 509) ^ x;
|
||||
|
||||
for (auto const x : element.getIssuerID ())
|
||||
hash_issuer += (hash_issuer * 911) ^ x;
|
||||
|
||||
return (hash_account ^ hash_currency ^ hash_issuer);
|
||||
}
|
||||
|
||||
STPathSet* STPathSet::construct (SerializerIterator& s, SField::ref name)
|
||||
{
|
||||
std::vector<STPath> paths;
|
||||
std::vector<STPathElement> path;
|
||||
|
||||
do
|
||||
{
|
||||
int iType = s.get8 ();
|
||||
|
||||
if (iType == STPathElement::typeNone ||
|
||||
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::typeNone)
|
||||
{
|
||||
return new STPathSet (name, paths);
|
||||
}
|
||||
}
|
||||
else if (iType & ~STPathElement::typeAll)
|
||||
{
|
||||
WriteLog (lsINFO, SerializedType)
|
||||
<< "STPathSet: Bad path element: " << iType;
|
||||
|
||||
throw std::runtime_error ("bad path element");
|
||||
}
|
||||
else
|
||||
{
|
||||
auto hasAccount = iType & STPathElement::typeAccount;
|
||||
auto hasCurrency = iType & STPathElement::typeCurrency;
|
||||
auto hasIssuer = iType & STPathElement::typeIssuer;
|
||||
|
||||
Account account;
|
||||
Currency currency;
|
||||
Account issuer;
|
||||
|
||||
if (hasAccount)
|
||||
account.copyFrom (s.get160 ());
|
||||
|
||||
if (hasCurrency)
|
||||
currency.copyFrom (s.get160 ());
|
||||
|
||||
if (hasIssuer)
|
||||
issuer.copyFrom (s.get160 ());
|
||||
|
||||
path.emplace_back (account, currency, issuer, hasCurrency);
|
||||
}
|
||||
}
|
||||
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 (
|
||||
Account const& account, Currency const& currency,
|
||||
Account const& issuer) const
|
||||
{
|
||||
for (auto& p: mPath)
|
||||
{
|
||||
if (p.getAccountID () == account
|
||||
&& p.getCurrency () == currency
|
||||
&& p.getIssuerID () == issuer)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Json::Value STPath::getJson (int) const
|
||||
{
|
||||
Json::Value ret (Json::arrayValue);
|
||||
|
||||
for (auto 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] = to_string (it.getAccountID ());
|
||||
|
||||
if (iType & STPathElement::typeCurrency)
|
||||
elem[jss::currency] = to_string (it.getCurrency ());
|
||||
|
||||
if (iType & STPathElement::typeIssuer)
|
||||
elem[jss::issuer] = to_string (it.getIssuerID ());
|
||||
|
||||
ret.append (elem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value STPathSet::getJson (int options) const
|
||||
{
|
||||
Json::Value ret (Json::arrayValue);
|
||||
for (auto 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 += to_string (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
|
||||
|
||||
void STPathSet::add (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
assert (fName->fieldType == STI_PATHSET);
|
||||
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::typeNone);
|
||||
}
|
||||
|
||||
} // ripple
|
||||
614
src/ripple/data/protocol/SerializedTypes.h
Normal file
614
src/ripple/data/protocol/SerializedTypes.h
Normal file
@@ -0,0 +1,614 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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_SERIALIZEDTYPES_H
|
||||
#define RIPPLE_SERIALIZEDTYPES_H
|
||||
|
||||
#include <ripple/data/protocol/SField.h>
|
||||
#include <ripple/data/protocol/Serializer.h>
|
||||
#include <ripple/data/protocol/STBitString.h>
|
||||
#include <ripple/data/protocol/STInteger.h>
|
||||
#include <ripple/data/protocol/SerializedType.h>
|
||||
#include <ripple/data/protocol/STAmount.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// variable length byte string
|
||||
class STVariableLength : public SerializedType
|
||||
{
|
||||
public:
|
||||
STVariableLength (Blob const& v) : value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
STVariableLength (SField::ref n, Blob const& v) : SerializedType (n), value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
STVariableLength (SField::ref n) : SerializedType (n)
|
||||
{
|
||||
;
|
||||
}
|
||||
STVariableLength (SerializerIterator&, SField::ref name = sfGeneric);
|
||||
STVariableLength ()
|
||||
{
|
||||
;
|
||||
}
|
||||
static std::unique_ptr<SerializedType> deserialize (SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
virtual SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_VL;
|
||||
}
|
||||
virtual std::string getText () const;
|
||||
void add (Serializer& s) const
|
||||
{
|
||||
assert (fName->isBinary ());
|
||||
assert ((fName->fieldType == STI_VL) ||
|
||||
(fName->fieldType == STI_ACCOUNT));
|
||||
s.addVL (value);
|
||||
}
|
||||
|
||||
Blob const& peekValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
Blob& peekValue ()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
Blob getValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
void setValue (Blob const& v)
|
||||
{
|
||||
value = v;
|
||||
}
|
||||
|
||||
operator Blob () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
|
||||
private:
|
||||
Blob value;
|
||||
|
||||
virtual STVariableLength* duplicate () const
|
||||
{
|
||||
return new STVariableLength (*this);
|
||||
}
|
||||
static STVariableLength* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STAccount : public STVariableLength
|
||||
{
|
||||
public:
|
||||
STAccount (Blob const& v) : STVariableLength (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
STAccount (SField::ref n, Blob const& v) : STVariableLength (n, v)
|
||||
{
|
||||
;
|
||||
}
|
||||
STAccount (SField::ref n, Account const& v);
|
||||
STAccount (SField::ref n) : STVariableLength (n)
|
||||
{
|
||||
;
|
||||
}
|
||||
STAccount ()
|
||||
{
|
||||
;
|
||||
}
|
||||
static std::unique_ptr<SerializedType> deserialize (SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_ACCOUNT;
|
||||
}
|
||||
std::string getText () const;
|
||||
|
||||
RippleAddress getValueNCA () const;
|
||||
void setValueNCA (RippleAddress const& nca);
|
||||
|
||||
template <typename Tag>
|
||||
void setValueH160 (base_uint<160, Tag> const& v)
|
||||
{
|
||||
peekValue ().clear ();
|
||||
peekValue ().insert (peekValue ().end (), v.begin (), v.end ());
|
||||
assert (peekValue ().size () == (160 / 8));
|
||||
}
|
||||
|
||||
template <typename Tag>
|
||||
bool getValueH160 (base_uint<160, Tag>& v) const
|
||||
{
|
||||
auto success = isValueH160 ();
|
||||
if (success)
|
||||
memcpy (v.begin (), & (peekValue ().front ()), (160 / 8));
|
||||
return success;
|
||||
}
|
||||
|
||||
bool isValueH160 () const;
|
||||
|
||||
private:
|
||||
virtual STAccount* duplicate () const
|
||||
{
|
||||
return new STAccount (*this);
|
||||
}
|
||||
static STAccount* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STPathElement
|
||||
{
|
||||
private:
|
||||
// VFALCO Remove these friend declarations
|
||||
friend class STPathSet;
|
||||
friend class STPath;
|
||||
friend class Pathfinder;
|
||||
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
typeNone = 0x00,
|
||||
typeAccount = 0x01, // Rippling through an account (vs taking an offer).
|
||||
typeCurrency = 0x10, // Currency follows.
|
||||
typeIssuer = 0x20, // Issuer follows.
|
||||
typeBoundary = 0xFF, // Boundary between alternate paths.
|
||||
typeAll = typeAccount | typeCurrency | typeIssuer,
|
||||
// Combination of all types.
|
||||
};
|
||||
|
||||
private:
|
||||
static
|
||||
std::size_t
|
||||
get_hash (STPathElement const& element);
|
||||
|
||||
public:
|
||||
STPathElement (
|
||||
Account const& account, Currency const& currency,
|
||||
Account const& issuer, bool forceCurrency = false)
|
||||
: mType (typeNone), mAccountID (account), mCurrencyID (currency)
|
||||
, mIssuerID (issuer), is_offer_ (isXRP(mAccountID))
|
||||
{
|
||||
if (!is_offer_)
|
||||
mType |= typeAccount;
|
||||
|
||||
if (forceCurrency || !isXRP(currency))
|
||||
mType |= typeCurrency;
|
||||
|
||||
if (!isXRP(issuer))
|
||||
mType |= typeIssuer;
|
||||
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
STPathElement (
|
||||
unsigned int uType, Account const& account, Currency const& currency,
|
||||
Account const& issuer)
|
||||
: mType (uType), mAccountID (account), mCurrencyID (currency)
|
||||
, mIssuerID (issuer), is_offer_ (isXRP(mAccountID))
|
||||
{
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
STPathElement ()
|
||||
: mType (typeNone), is_offer_ (true)
|
||||
{
|
||||
hash_value_ = get_hash (*this);
|
||||
}
|
||||
|
||||
int getNodeType () const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
bool isOffer () const
|
||||
{
|
||||
return is_offer_;
|
||||
}
|
||||
bool isAccount () const
|
||||
{
|
||||
return !isOffer ();
|
||||
}
|
||||
|
||||
// Nodes are either an account ID or a offer prefix. Offer prefixs denote a
|
||||
// class of offers.
|
||||
Account const& getAccountID () const
|
||||
{
|
||||
return mAccountID;
|
||||
}
|
||||
Currency const& getCurrency () const
|
||||
{
|
||||
return mCurrencyID;
|
||||
}
|
||||
Account const& getIssuerID () const
|
||||
{
|
||||
return mIssuerID;
|
||||
}
|
||||
|
||||
bool operator== (const STPathElement& t) const
|
||||
{
|
||||
return (mType & typeAccount) == (t.mType & typeAccount) &&
|
||||
hash_value_ == t.hash_value_ &&
|
||||
mAccountID == t.mAccountID &&
|
||||
mCurrencyID == t.mCurrencyID &&
|
||||
mIssuerID == t.mIssuerID;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int mType;
|
||||
Account mAccountID;
|
||||
Currency mCurrencyID;
|
||||
Account mIssuerID;
|
||||
|
||||
bool is_offer_;
|
||||
std::size_t hash_value_;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STPath
|
||||
{
|
||||
public:
|
||||
STPath ()
|
||||
{
|
||||
;
|
||||
}
|
||||
STPath (const std::vector<STPathElement>& p) : mPath (p)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
int size () const
|
||||
{
|
||||
return mPath.size ();
|
||||
}
|
||||
void reserve (size_t n)
|
||||
{
|
||||
mPath.reserve(n);
|
||||
}
|
||||
bool isEmpty () const
|
||||
{
|
||||
return mPath.empty ();
|
||||
}
|
||||
bool empty() const
|
||||
{
|
||||
return mPath.empty ();
|
||||
}
|
||||
|
||||
const STPathElement& getElement (int offset) const
|
||||
{
|
||||
return mPath[offset];
|
||||
}
|
||||
const STPathElement& getElement (int offset)
|
||||
{
|
||||
return mPath[offset];
|
||||
}
|
||||
void addElement (const STPathElement& e)
|
||||
{
|
||||
mPath.push_back (e);
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
mPath.clear ();
|
||||
}
|
||||
bool hasSeen (Account const& account, Currency const& currency,
|
||||
Account const& issuer) const;
|
||||
Json::Value getJson (int) const;
|
||||
|
||||
std::vector<STPathElement>::iterator begin ()
|
||||
{
|
||||
return mPath.begin ();
|
||||
}
|
||||
std::vector<STPathElement>::iterator end ()
|
||||
{
|
||||
return mPath.end ();
|
||||
}
|
||||
std::vector<STPathElement>::const_iterator begin () const
|
||||
{
|
||||
return mPath.begin ();
|
||||
}
|
||||
std::vector<STPathElement>::const_iterator end () const
|
||||
{
|
||||
return mPath.end ();
|
||||
}
|
||||
|
||||
bool operator== (STPath const& t) const
|
||||
{
|
||||
return mPath == t.mPath;
|
||||
}
|
||||
|
||||
void setCanonical (STPath const& spExpanded);
|
||||
|
||||
private:
|
||||
friend class STPathSet;
|
||||
friend class Pathfinder;
|
||||
|
||||
std::vector<STPathElement> mPath;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// A set of zero or more payment paths
|
||||
class STPathSet : public SerializedType
|
||||
{
|
||||
public:
|
||||
STPathSet ()
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit STPathSet (SField::ref n) : SerializedType (n)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
explicit STPathSet (const std::vector<STPath>& v) : value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
STPathSet (SField::ref n, const std::vector<STPath>& v) : SerializedType (n), value (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
// std::string getText() const;
|
||||
void add (Serializer& s) const;
|
||||
virtual Json::Value getJson (int) const;
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_PATHSET;
|
||||
}
|
||||
int size () const
|
||||
{
|
||||
return value.size ();
|
||||
}
|
||||
void reserve (size_t n)
|
||||
{
|
||||
value.reserve(n);
|
||||
}
|
||||
STPath const& getPath (int off) const
|
||||
{
|
||||
return value[off];
|
||||
}
|
||||
STPath& peekPath (int off)
|
||||
{
|
||||
return value[off];
|
||||
}
|
||||
bool isEmpty () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
void clear ()
|
||||
{
|
||||
value.clear ();
|
||||
}
|
||||
void addPath (STPath const& e)
|
||||
{
|
||||
value.push_back (e);
|
||||
}
|
||||
void addUniquePath (STPath const& e)
|
||||
{
|
||||
for (auto const& p: value)
|
||||
{
|
||||
if (p == e)
|
||||
return;
|
||||
}
|
||||
value.push_back (e);
|
||||
}
|
||||
|
||||
bool assembleAdd(STPath const& base, STPathElement const& tail)
|
||||
{ // assemble base+tail and add it to the set if it's not a duplicate
|
||||
value.push_back (base);
|
||||
|
||||
std::vector<STPath>::reverse_iterator it = value.rbegin ();
|
||||
|
||||
STPath& newPath = *it;
|
||||
newPath.mPath.push_back (tail);
|
||||
|
||||
while (++it != value.rend ())
|
||||
{
|
||||
if (it->mPath == newPath.mPath)
|
||||
{
|
||||
value.pop_back ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return value.empty ();
|
||||
}
|
||||
|
||||
STPath& operator[](size_t n)
|
||||
{
|
||||
return value[n];
|
||||
}
|
||||
STPath const& operator[](size_t n) const
|
||||
{
|
||||
return value[n];
|
||||
}
|
||||
|
||||
std::vector<STPath>::iterator begin ()
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
std::vector<STPath>::iterator end ()
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
std::vector<STPath>::const_iterator begin () const
|
||||
{
|
||||
return value.begin ();
|
||||
}
|
||||
std::vector<STPath>::const_iterator end () const
|
||||
{
|
||||
return value.end ();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<STPath> value;
|
||||
|
||||
STPathSet* duplicate () const
|
||||
{
|
||||
return new STPathSet (*this);
|
||||
}
|
||||
static STPathSet* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class STVector256 : public SerializedType
|
||||
{
|
||||
public:
|
||||
STVector256 ()
|
||||
{
|
||||
;
|
||||
}
|
||||
STVector256 (SField::ref n) : SerializedType (n)
|
||||
{
|
||||
;
|
||||
}
|
||||
STVector256 (SField::ref n, const std::vector<uint256>& v) : SerializedType (n), mValue (v)
|
||||
{
|
||||
;
|
||||
}
|
||||
STVector256 (const std::vector<uint256>& vector) : mValue (vector)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
SerializedTypeID getSType () const
|
||||
{
|
||||
return STI_VECTOR256;
|
||||
}
|
||||
void add (Serializer& s) const;
|
||||
|
||||
static std::unique_ptr<SerializedType> deserialize (SerializerIterator& sit, SField::ref name)
|
||||
{
|
||||
return std::unique_ptr<SerializedType> (construct (sit, name));
|
||||
}
|
||||
|
||||
const std::vector<uint256>& peekValue () const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
std::vector<uint256>& peekValue ()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
virtual bool isEquivalent (const SerializedType& t) const;
|
||||
virtual bool isDefault () const
|
||||
{
|
||||
return mValue.empty ();
|
||||
}
|
||||
|
||||
std::vector<uint256> getValue () const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
int size () const
|
||||
{
|
||||
return mValue.size ();
|
||||
}
|
||||
bool isEmpty () const
|
||||
{
|
||||
return mValue.empty ();
|
||||
}
|
||||
|
||||
uint256 const& at (int i) const
|
||||
{
|
||||
assert ((i >= 0) && (i < size ()));
|
||||
return mValue.at (i);
|
||||
}
|
||||
uint256& at (int i)
|
||||
{
|
||||
assert ((i >= 0) && (i < size ()));
|
||||
return mValue.at (i);
|
||||
}
|
||||
|
||||
void setValue (const STVector256& v)
|
||||
{
|
||||
mValue = v.mValue;
|
||||
}
|
||||
void setValue (const std::vector<uint256>& v)
|
||||
{
|
||||
mValue = v;
|
||||
}
|
||||
void addValue (uint256 const& v)
|
||||
{
|
||||
mValue.push_back (v);
|
||||
}
|
||||
bool hasValue (uint256 const& v) const;
|
||||
void sort ()
|
||||
{
|
||||
std::sort (mValue.begin (), mValue.end ());
|
||||
}
|
||||
|
||||
Json::Value getJson (int) const;
|
||||
|
||||
std::vector<uint256>::const_iterator begin() const
|
||||
{
|
||||
return mValue.begin ();
|
||||
}
|
||||
std::vector<uint256>::const_iterator end() const
|
||||
{
|
||||
return mValue.end ();
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<uint256> mValue;
|
||||
|
||||
STVector256* duplicate () const
|
||||
{
|
||||
return new STVector256 (*this);
|
||||
}
|
||||
static STVector256* construct (SerializerIterator&, SField::ref);
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
669
src/ripple/data/protocol/Serializer.cpp
Normal file
669
src/ripple/data/protocol/Serializer.cpp
Normal file
@@ -0,0 +1,669 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/Log.h>
|
||||
#include <beast/unit_test/suite.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
template <> int Serializer::addInteger(unsigned char i) { return add8(i); }
|
||||
template <> int Serializer::addInteger(std::uint16_t i) { return add16(i); }
|
||||
template <> int Serializer::addInteger(std::uint32_t i) { return add32(i); }
|
||||
template <> int Serializer::addInteger(std::uint64_t i) { return add64(i); }
|
||||
|
||||
int Serializer::add128 (const uint128& 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::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 (std::string const& 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;
|
||||
}
|
||||
|
||||
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
|
||||
377
src/ripple/data/protocol/Serializer.h
Normal file
377
src/ripple/data/protocol/Serializer.h
Normal file
@@ -0,0 +1,377 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <iomanip>
|
||||
|
||||
#include <ripple/common/byte_view.h>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
class CKey; // forward declaration
|
||||
|
||||
class Serializer
|
||||
{
|
||||
public:
|
||||
typedef std::shared_ptr<Serializer> pointer;
|
||||
|
||||
protected:
|
||||
Blob mData;
|
||||
|
||||
public:
|
||||
Serializer (int n = 256)
|
||||
{
|
||||
mData.reserve (n);
|
||||
}
|
||||
Serializer (Blob const& data) : mData (data)
|
||||
{
|
||||
;
|
||||
}
|
||||
Serializer (std::string const& 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 add256 (uint256 const& ); // transaction and ledger hashes
|
||||
|
||||
template <typename Integer>
|
||||
int addInteger(Integer);
|
||||
|
||||
template <int Bits, class Tag>
|
||||
int addBitString(base_uint<Bits, Tag> const& v) {
|
||||
int ret = mData.size ();
|
||||
mData.insert (mData.end (), v.begin (), v.end ());
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO(tom): merge with add128 and add256.
|
||||
template <class Tag>
|
||||
int add160 (base_uint<160, Tag> const& i)
|
||||
{
|
||||
return addBitString<160, Tag>(i);
|
||||
}
|
||||
|
||||
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 (std::string const& 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 get256 (uint256&, int offset) const;
|
||||
|
||||
template <typename Integer>
|
||||
bool getInteger(Integer& number, int offset) {
|
||||
static const auto bytes = sizeof(Integer);
|
||||
if ((offset + bytes) > mData.size ())
|
||||
return false;
|
||||
number = 0;
|
||||
|
||||
auto ptr = &mData[offset];
|
||||
for (auto i = 0; i < bytes; ++i)
|
||||
{
|
||||
if (i)
|
||||
number <<= 8;
|
||||
number |= *ptr++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int Bits, typename Tag = void>
|
||||
bool getBitString(base_uint<Bits, Tag>& data, int offset) const {
|
||||
auto success = (offset + (Bits / 8)) <= mData.size ();
|
||||
if (success)
|
||||
memcpy (data.begin (), & (mData.front ()) + offset, (Bits / 8));
|
||||
return success;
|
||||
}
|
||||
|
||||
uint256 get256 (int offset) const;
|
||||
|
||||
// TODO(tom): merge with get128 and get256.
|
||||
template <class Tag>
|
||||
bool get160 (base_uint<160, Tag>& o, int offset) const
|
||||
{
|
||||
return getBitString<160, Tag>(o, offset);
|
||||
}
|
||||
|
||||
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, std::string const& 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 () { return getBitString<128>(); }
|
||||
uint160 get160 () { return getBitString<160>(); }
|
||||
uint256 get256 () { return getBitString<256>(); }
|
||||
|
||||
template <std::size_t Bits, typename Tag = void>
|
||||
void getBitString (base_uint<Bits, Tag>& bits) {
|
||||
if (!mSerializer.getBitString<Bits> (bits, mPos))
|
||||
throw std::runtime_error ("invalid serializer getBitString");
|
||||
|
||||
mPos += Bits / 8;
|
||||
}
|
||||
|
||||
template <std::size_t Bits, typename Tag = void>
|
||||
base_uint<Bits, Tag> getBitString () {
|
||||
base_uint<Bits, Tag> bits;
|
||||
getBitString(bits);
|
||||
return bits;
|
||||
}
|
||||
|
||||
void getFieldID (int& type, int& field);
|
||||
|
||||
Blob getRaw (int iLength);
|
||||
|
||||
Blob getVL ();
|
||||
};
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
159
src/ripple/data/protocol/TER.cpp
Normal file
159
src/ripple/data/protocol/TER.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 <ripple/basics/ArraySize.h>
|
||||
|
||||
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-existent 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." },
|
||||
{ tecINSUFF_FEE, "tecINSUFF_FEE", "Insufficient balance to pay fee." },
|
||||
{ tecFROZEN, "tecFROZEN", "Asset is frozen." },
|
||||
{ tecNO_TARGET, "tecNO_TARGET", "Target account does not exist." },
|
||||
{ tecNO_PERMISSION, "tecNO_PERMISSION", "No permission to perform requested operation." },
|
||||
{ tecNO_ENTRY, "tecNO_ENTRY", "No matching entry found." },
|
||||
{ tecINSUFFICIENT_RESERVE,"tecINSUFFICIENT_RESERVE", "Insufficient reserve to complete requested operation." },
|
||||
|
||||
{ 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_LEDGER, "tefBAD_LEDGER", "Ledger in unexpected state." },
|
||||
{ tefCREATED, "tefCREATED", "Can't add an already created account." },
|
||||
{ tefDST_TAG_NEEDED, "tefDST_TAG_NEEDED", "Destination tag required." },
|
||||
{ tefEXCEPTION, "tefEXCEPTION", "Unexpected program state." },
|
||||
{ tefFAILURE, "tefFAILURE", "Failed to apply." },
|
||||
{ tefINTERNAL, "tefINTERNAL", "Internal error." },
|
||||
{ tefMASTER_DISABLED, "tefMASTER_DISABLED", "Master key is disabled." },
|
||||
{ tefMAX_LEDGER, "tefMAX_LEDGER", "Ledger sequence too high." },
|
||||
{ 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." },
|
||||
|
||||
{ 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_EXPIRATION, "temBAD_EXPIRATION", "Malformed: Bad expiration." },
|
||||
{ temBAD_FEE, "temBAD_FEE", "Invalid fee, negative or not XRP." },
|
||||
{ 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_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." },
|
||||
{ temBAD_SEQUENCE, "temBAD_SEQUENCE", "Malformed: Sequence is not in the past." },
|
||||
{ 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" },
|
||||
{ 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
|
||||
231
src/ripple/data/protocol/TER.h
Normal file
231
src/ripple/data/protocol/TER.h
Normal file
@@ -0,0 +1,231 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 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,
|
||||
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_EXPIRATION,
|
||||
temBAD_FEE,
|
||||
temBAD_ISSUER,
|
||||
temBAD_LIMIT,
|
||||
temBAD_OFFER,
|
||||
temBAD_PATH,
|
||||
temBAD_PATH_LOOP,
|
||||
temBAD_SEND_XRP_LIMIT,
|
||||
temBAD_SEND_XRP_MAX,
|
||||
temBAD_SEND_XRP_NO_DIRECT,
|
||||
temBAD_SEND_XRP_PARTIAL,
|
||||
temBAD_SEND_XRP_PATHS,
|
||||
temBAD_SEQUENCE,
|
||||
temBAD_SIGNATURE,
|
||||
temBAD_SRC_ACCOUNT,
|
||||
temBAD_TRANSFER_RATE,
|
||||
temDST_IS_SRC,
|
||||
temDST_NEEDED,
|
||||
temINVALID,
|
||||
temINVALID_FLAG,
|
||||
temREDUNDANT,
|
||||
temREDUNDANT_SEND_MAX,
|
||||
temRIPPLE_EMPTY,
|
||||
|
||||
// An intermediate result used internally, should never be returned.
|
||||
temUNCERTAIN,
|
||||
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_LEDGER,
|
||||
tefCREATED,
|
||||
tefDST_TAG_NEEDED,
|
||||
tefEXCEPTION,
|
||||
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
|
||||
//
|
||||
// Cause:
|
||||
// Prior application of another, possibly non-existent, 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, so 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, so 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,
|
||||
tecINSUFF_FEE = 136,
|
||||
tecFROZEN = 137,
|
||||
tecNO_TARGET = 138,
|
||||
tecNO_PERMISSION = 139,
|
||||
tecNO_ENTRY = 140,
|
||||
tecINSUFFICIENT_RESERVE = 141,
|
||||
};
|
||||
|
||||
inline bool isTelLocal(TER x)
|
||||
{
|
||||
return ((x) >= telLOCAL_ERROR && (x) < temMALFORMED);
|
||||
}
|
||||
|
||||
inline bool isTemMalformed(TER x)
|
||||
{
|
||||
return ((x) >= temMALFORMED && (x) < tefFAILURE);
|
||||
}
|
||||
|
||||
inline bool isTefFailure(TER x)
|
||||
{
|
||||
return ((x) >= tefFAILURE && (x) < terRETRY);
|
||||
}
|
||||
|
||||
inline bool isTerRetry(TER x)
|
||||
{
|
||||
return ((x) >= terRETRY && (x) < tesSUCCESS);
|
||||
}
|
||||
|
||||
inline bool isTesSuccess(TER x)
|
||||
{
|
||||
return ((x) == tesSUCCESS);
|
||||
}
|
||||
|
||||
inline bool isTecClaim(TER x)
|
||||
{
|
||||
return ((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
|
||||
93
src/ripple/data/protocol/TxFlags.h
Normal file
93
src/ripple/data/protocol/TxFlags.h
Normal file
@@ -0,0 +1,93 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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;
|
||||
const std::uint32_t asfNoFreeze = 6;
|
||||
const std::uint32_t asfGlobalFreeze = 7;
|
||||
|
||||
// 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 tfSetFreeze = 0x00100000;
|
||||
const std::uint32_t tfClearFreeze = 0x00200000;
|
||||
const std::uint32_t tfTrustSetMask = ~ (tfUniversal | tfSetfAuth | tfSetNoRipple | tfClearNoRipple
|
||||
| tfSetFreeze | tfClearFreeze);
|
||||
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
112
src/ripple/data/protocol/TxFormats.cpp
Normal file
112
src/ripple/data/protocol/TxFormats.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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 ("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)
|
||||
;
|
||||
|
||||
add ("TicketCreate", ttTICKET_CREATE)
|
||||
<< SOElement (sfTarget, SOE_OPTIONAL)
|
||||
<< SOElement (sfExpiration, SOE_OPTIONAL)
|
||||
;
|
||||
|
||||
add ("TicketCancel", ttTICKET_CANCEL)
|
||||
<< SOElement (sfTicketID, 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
|
||||
72
src/ripple/data/protocol/TxFormats.h
Normal file
72
src/ripple/data/protocol/TxFormats.h
Normal file
@@ -0,0 +1,72 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
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,
|
||||
no_longer_used = 9,
|
||||
ttTICKET_CREATE = 10,
|
||||
ttTICKET_CANCEL = 11,
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user