diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj
index bab6ec822b..ed138af427 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj
+++ b/Builds/VisualStudio2013/RippleD.vcxproj
@@ -1780,6 +1780,8 @@
+
+
@@ -1852,6 +1854,8 @@
+
+
@@ -2302,6 +2306,10 @@
True
+
+
+
+
@@ -2310,6 +2318,12 @@
+
+ True
+
+
+ True
+
True
@@ -2426,6 +2440,8 @@
+
+
diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters
index f0bd610bd7..501f0309e5 100644
--- a/Builds/VisualStudio2013/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters
@@ -2667,6 +2667,9 @@
ripple\basics
+
+ ripple\basics
+
ripple\basics
@@ -2754,6 +2757,9 @@
ripple\basics
+
+ ripple\basics
+
ripple\basics
@@ -3315,6 +3321,12 @@
ripple\peerfinder\tests
+
+ ripple\protocol
+
+
+ ripple\protocol
+
ripple\protocol
@@ -3327,6 +3339,12 @@
ripple\protocol
+
+ ripple\protocol\impl
+
+
+ ripple\protocol\impl
+
ripple\protocol\impl
@@ -3462,6 +3480,9 @@
ripple\protocol
+
+ ripple\protocol
+
ripple\protocol
diff --git a/src/ripple/basics/Buffer.h b/src/ripple/basics/Buffer.h
new file mode 100644
index 0000000000..374a6ed377
--- /dev/null
+++ b/src/ripple/basics/Buffer.h
@@ -0,0 +1,149 @@
+//------------------------------------------------------------------------------
+/*
+ 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_BASICS_BUFFER_H_INCLUDED
+#define RIPPLE_BASICS_BUFFER_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+/** Like std::vector but better.
+ Meets the requirements of BufferFactory.
+*/
+class Buffer
+{
+private:
+ std::unique_ptr<
+ std::uint8_t[]> p_;
+ std::size_t size_ = 0;
+
+public:
+ Buffer() = default;
+ Buffer (Buffer const&) = delete;
+ Buffer& operator= (Buffer const&) = delete;
+
+ /** Move-construct.
+ The other buffer is reset.
+ */
+ Buffer (Buffer&& other)
+ : p_ (std::move(other.p_))
+ , size_ (other.size_)
+ {
+ other.size_ = 0;
+ }
+
+ /** Move-assign.
+ The other buffer is reset.
+ */
+ Buffer& operator= (Buffer&& other)
+ {
+ p_ = std::move(other.p_);
+ size_ = other.size_;
+ other.size_ = 0;
+ return *this;
+ }
+
+ /** Create an uninitialized buffer with the given size. */
+ explicit
+ Buffer (std::size_t size)
+ : p_ (size ?
+ new std::uint8_t[size] : nullptr)
+ , size_ (size)
+ {
+ }
+
+ /** Create a buffer as a copy of existing memory. */
+ Buffer (void const* data, std::size_t size)
+ : p_ (size ?
+ new std::uint8_t[size] : nullptr)
+ , size_ (size)
+ {
+ std::memcpy(p_.get(), data, size);
+ }
+
+ /** Returns the number of bytes in the buffer. */
+ std::size_t
+ size() const noexcept
+ {
+ return size_;
+ }
+
+ /** Return a pointer to beginning of the storage.
+ @note The return type is guaranteed to be a pointer
+ to a single byte, to facilitate pointer arithmetic.
+ */
+ /** @{ */
+ std::uint8_t const*
+ data() const noexcept
+ {
+ return p_.get();
+ }
+
+ std::uint8_t*
+ data() noexcept
+ {
+ return p_.get();
+ }
+ /** @} */
+
+ /** Reset the buffer.
+ All memory is deallocated. The resulting size is 0.
+ */
+ void
+ clear() noexcept
+ {
+ p_.reset();
+ size_ = 0;
+ }
+
+ /** Reallocate the storage.
+ Existing data, if any, is discarded.
+ */
+ std::uint8_t*
+ alloc (std::size_t n)
+ {
+ if (n == 0)
+ {
+ clear();
+ return nullptr;
+ }
+ if (n != size_)
+ {
+ p_.reset(new std::uint8_t[n]);
+ size_ = n;
+ }
+ return p_.get();
+ }
+
+ // Meet the requirements of BufferFactory
+ void*
+ operator()(std::size_t n)
+ {
+ return alloc(n);
+ }
+};
+
+} // ripple
+
+#endif
diff --git a/src/ripple/basics/Slice.h b/src/ripple/basics/Slice.h
new file mode 100644
index 0000000000..83ab9a7a0b
--- /dev/null
+++ b/src/ripple/basics/Slice.h
@@ -0,0 +1,110 @@
+//------------------------------------------------------------------------------
+/*
+ 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_BASICS_SLICE_H_INCLUDED
+#define RIPPLE_BASICS_SLICE_H_INCLUDED
+
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+/** An immutable linear range of bytes.
+
+ A fully constructed Slice is guaranteed to be in a valid state.
+ Default construction, construction from nullptr, and zero-byte
+ ranges are disallowed. A Slice is lightweight and copyable, it
+ retains no ownership of the underlying memory.
+*/
+class Slice
+{
+private:
+ std::uint8_t const* data_;
+ std::size_t size_;
+
+public:
+ // Disallowed
+ Slice() = delete;
+
+ Slice (Slice const&) = default;
+
+ Slice& operator= (Slice const&) = default;
+
+ /** Create a slice pointing to existing memory. */
+ Slice (void const* data, std::size_t size)
+ : data_ (reinterpret_cast<
+ std::uint8_t const*>(data))
+ , size_ (size)
+ {
+ assert(data_ != nullptr);
+ assert(size_ > 0);
+ }
+
+ /** Returns the number of bytes in the storage.
+
+ This will never be zero.
+ */
+ std::size_t
+ size() const noexcept
+ {
+ return size_;
+ }
+
+ /** Return a pointer to beginning of the storage.
+ @note The return type is guaranteed to be a pointer
+ to a single byte, to facilitate pointer arithmetic.
+ */
+ std::uint8_t const*
+ data() const noexcept
+ {
+ return data_;
+ }
+};
+
+template
+inline
+void
+hash_append (Hasher& h, Slice const& v)
+{
+ h.append(v.data(), v.size());
+}
+
+inline
+bool
+operator== (Slice const& lhs, Slice const& rhs) noexcept
+{
+ return lhs.size() == rhs.size() &&
+ std::memcmp(
+ lhs.data(), rhs.data(), lhs.size()) == 0;
+}
+
+inline
+bool
+operator< (Slice const& lhs, Slice const& rhs) noexcept
+{
+ return std::lexicographical_compare(
+ lhs.data(), lhs.data() + lhs.size(),
+ rhs.data(), rhs.data() + rhs.size());
+}
+
+} // ripple
+
+#endif
diff --git a/src/ripple/protocol/AnyPublicKey.h b/src/ripple/protocol/AnyPublicKey.h
new file mode 100644
index 0000000000..059e5ebc6f
--- /dev/null
+++ b/src/ripple/protocol/AnyPublicKey.h
@@ -0,0 +1,185 @@
+//------------------------------------------------------------------------------
+/*
+ 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_ANYPUBLICKEY_H_INCLUDED
+#define RIPPLE_PROTOCOL_ANYPUBLICKEY_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+enum class KeyType
+{
+ unknown,
+ secp256k1,
+ ed25519
+};
+
+//------------------------------------------------------------------------------
+
+/** Variant container for all public keys. */
+class AnyPublicKeySlice
+ : public Slice
+{
+public:
+#ifdef _MSC_VER
+ AnyPublicKeySlice (
+ void const* data, std::size_t size)
+ : Slice (data, size)
+ {
+ }
+#else
+ using Slice::Slice;
+#endif
+
+ AnyPublicKeySlice() = delete;
+
+ AnyPublicKeySlice (
+ AnyPublicKeySlice const&) = default;
+
+ AnyPublicKeySlice& operator= (
+ AnyPublicKeySlice const&) = default;
+
+ /** Returns the type of key stored. */
+ KeyType
+ type() const noexcept;
+
+ /** Verify a signature using this public key. */
+ bool
+ verify (void const* msg, std::size_t msg_size,
+ void const* sig, std::size_t sig_size) const;
+};
+
+template <>
+struct STExchange
+{
+ using value_type = AnyPublicKeySlice;
+
+ static
+ void
+ get (boost::optional& t,
+ STBlob const& u)
+ {
+ t = boost::in_place(u.data(), u.size());
+ }
+
+ static
+ std::unique_ptr
+ set (SField const& f, AnyPublicKeySlice const& t)
+ {
+ return std::make_unique(
+ f, t.data(), t.size());
+ }
+};
+
+//------------------------------------------------------------------------------
+
+/** Variant container for all public keys, with ownership. */
+class AnyPublicKey
+ : private boost::base_from_member
+ , public AnyPublicKeySlice
+{
+private:
+ using buffer_type = boost::base_from_member;
+
+public:
+ AnyPublicKey() = delete;
+ AnyPublicKey (AnyPublicKey const&) = delete;
+ AnyPublicKey& operator= (AnyPublicKey const&) = delete;
+
+#ifdef _MSC_VER
+ AnyPublicKey (AnyPublicKey&& other)
+ : buffer_type(std::move(other.buffer_type::member))
+ , AnyPublicKeySlice (buffer_type::member.data(),
+ buffer_type::member.size())
+ {
+ }
+
+ AnyPublicKey& operator= (AnyPublicKey&& other)
+ {
+ buffer_type::member =
+ std::move(other.buffer_type::member);
+ return *this;
+ }
+#else
+ AnyPublicKey (AnyPublicKey&&) = default;
+ AnyPublicKey& operator= (AnyPublicKey&&) = default;
+#endif
+
+ AnyPublicKey (void const* data_, std::size_t size_)
+ : buffer_type (data_, size_)
+ , AnyPublicKeySlice (
+ member.data(), member.size())
+ {
+ }
+
+ /** Returns ownership of the underlying Buffer.
+ After calling this function, only the destructor
+ or the move assignment operator may be called.
+ */
+ Buffer
+ releaseBuffer() noexcept
+ {
+ return std::move(buffer_type::member);
+ }
+};
+
+template <>
+struct STExchange
+{
+ using value_type = AnyPublicKey;
+
+ static
+ void
+ get (boost::optional& t,
+ STBlob const& u)
+ {
+ t = boost::in_place(u.data(), u.size());
+ }
+
+ static
+ std::unique_ptr
+ set (SField const& f, AnyPublicKey const& t)
+ {
+ return std::make_unique(
+ f, t.data(), t.size());
+ }
+
+ static
+ std::unique_ptr
+ set (SField const& f, AnyPublicKey&& t)
+ {
+ return std::make_unique(
+ f, t.releaseBuffer());
+ }
+};
+
+} // ripple
+
+#endif
diff --git a/src/ripple/protocol/AnySecretKey.h b/src/ripple/protocol/AnySecretKey.h
new file mode 100644
index 0000000000..a92cc82812
--- /dev/null
+++ b/src/ripple/protocol/AnySecretKey.h
@@ -0,0 +1,85 @@
+//------------------------------------------------------------------------------
+/*
+ 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_ANYSECRETKEY_H_INCLUDED
+#define RIPPLE_PROTOCOL_ANYSECRETKEY_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+/** Variant container for secret key, with ownership. */
+class AnySecretKey
+{
+private:
+ Buffer p_;
+ KeyType type_;
+
+public:
+ AnySecretKey() = delete;
+ AnySecretKey (AnySecretKey const&) = delete;
+ AnySecretKey& operator= (AnySecretKey const&) = delete;
+
+ /** Destroy the key.
+ The memory area is secure erased.
+ */
+ ~AnySecretKey();
+
+ AnySecretKey (AnySecretKey&& other);
+
+ AnySecretKey& operator= (AnySecretKey&& other);
+
+ AnySecretKey (KeyType type,
+ void const* data, std::size_t size);
+
+ /** Returns the type of secret key. */
+ KeyType
+ type() const noexcept
+ {
+ return type_;
+ }
+
+ /** Returns the corresponding public key. */
+ AnyPublicKey
+ publicKey() const;
+
+ /** Create a signature for the given message. */
+ Buffer
+ sign (void const* msg, std::size_t msg_len) const;
+
+ /** Securely generate a new ed25519 secret key. */
+ static
+ AnySecretKey
+ make_ed25519();
+
+ /** Securely generate a new secp256k1 key pair. */
+ static
+ std::pair
+ make_secp256k1_pair();
+};
+
+} // ripple
+
+#endif
diff --git a/src/ripple/protocol/RippleAddress.h b/src/ripple/protocol/RippleAddress.h
index 259c32e61a..dfb66cbafa 100644
--- a/src/ripple/protocol/RippleAddress.h
+++ b/src/ripple/protocol/RippleAddress.h
@@ -25,6 +25,7 @@
#include
#include
#include
+#include
namespace ripple {
@@ -53,6 +54,18 @@ private:
public:
RippleAddress ();
+ void const*
+ data() const noexcept
+ {
+ return vchData.data();
+ }
+
+ std::size_t
+ size() const noexcept
+ {
+ return vchData.size();
+ }
+
// For public and private key, checks if they are legal.
bool isValid () const
{
diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h
index 8dcf0337b5..1265ba8832 100644
--- a/src/ripple/protocol/SField.h
+++ b/src/ripple/protocol/SField.h
@@ -22,9 +22,16 @@
#include
#include
+#include
+#include
namespace ripple {
+// Forwards
+class STBlob;
+template
+class STInteger;
+
enum SerializedTypeID
{
// special types
@@ -139,7 +146,7 @@ public:
{}
#endif
-private:
+protected:
// These constructors can only be called from FieldNames.cpp
SField (SerializedTypeID tid, int fv, const char* fn,
int meta = sMD_Default, bool signing = true);
@@ -253,6 +260,25 @@ private:
static int num;
};
+/** A field with a type known at compile time. */
+template
+struct TypedField : SField
+{
+ using type = T;
+
+ template
+ explicit
+ TypedField (Args&&... args)
+ : SField(std::forward(args)...)
+ {
+ }
+
+ TypedField (TypedField&& u)
+ : SField(std::move(u))
+ {
+ }
+};
+
extern SField const sfInvalid;
extern SField const sfGeneric;
extern SField const sfLedgerEntry;
@@ -272,7 +298,7 @@ extern SField const sfTransactionType;
// 32-bit integers (common)
extern SField const sfFlags;
extern SField const sfSourceTag;
-extern SField const sfSequence;
+extern TypedField> const sfSequence;
extern SField const sfPreviousTxnLgrSeq;
extern SField const sfLedgerSequence;
extern SField const sfCloseTime;
@@ -359,12 +385,12 @@ extern SField const sfRippleEscrow;
extern SField const sfDeliveredAmount;
// variable length
-extern SField const sfPublicKey;
+extern TypedField const sfPublicKey;
extern SField const sfMessageKey;
-extern SField const sfSigningPubKey;
+extern TypedField const sfSigningPubKey;
extern SField const sfTxnSignature;
extern SField const sfGenerator;
-extern SField const sfSignature;
+extern TypedField const sfSignature;
extern SField const sfDomain;
extern SField const sfFundCode;
extern SField const sfRemoveCode;
@@ -413,6 +439,8 @@ extern SField const sfSufficient;
extern SField const sfAffectedNodes;
extern SField const sfMemos;
+//------------------------------------------------------------------------------
+
} // ripple
#endif
diff --git a/src/ripple/protocol/STBlob.h b/src/ripple/protocol/STBlob.h
index 9f262fb7d3..6952b8be83 100644
--- a/src/ripple/protocol/STBlob.h
+++ b/src/ripple/protocol/STBlob.h
@@ -20,7 +20,10 @@
#ifndef RIPPLE_PROTOCOL_STBLOB_H_INCLUDED
#define RIPPLE_PROTOCOL_STBLOB_H_INCLUDED
+#include
+#include
#include
+#include
#include
namespace ripple {
@@ -30,19 +33,58 @@ class STBlob
: public STBase
{
public:
+ using value_type = Slice;
+
STBlob () = default;
+ /** Construct with size and initializer.
+ Init will be called as:
+ void(void* data, std::size_t size)
+ */
+ template
+ STBlob (SField::ref f, std::size_t size,
+ Init&& init)
+ : STBase(f)
+ {
+ value.resize(size);
+ init(value.data(), value.size());
+ }
+
+ STBlob (SField::ref f,
+ void const* data, std::size_t size)
+ : STBase(f)
+ {
+ value.resize(size);
+ std::memcpy(value.data(), data, size);
+ }
+
+ STBlob (SField const& f, Buffer&& b)
+ : STBase(f)
+ {
+ // VFALCO TODO Really move the buffer
+ value.resize(b.size());
+ std::memcpy(value.data(),
+ b.data(), b.size());
+ auto tmp = std::move(b);
+ }
+
+ // VFALCO DEPRECATED
STBlob (Blob const& v)
: value (v)
- { }
+ {
+ }
+ // VFALCO DEPRECATED
STBlob (SField::ref n, Blob const& v)
- : STBase (n), value (v)
- { }
+ : STBase (n)
+ , value (v)
+ {
+ }
STBlob (SField::ref n)
: STBase (n)
- { }
+ {
+ }
STBlob (SerialIter&, SField::ref name = sfGeneric);
@@ -53,6 +95,19 @@ public:
return std::make_unique (name, sit.getVL ());
}
+ std::size_t
+ size() const
+ {
+ return value.size();
+ }
+
+ std::uint8_t const*
+ data() const
+ {
+ return reinterpret_cast<
+ std::uint8_t const*>(value.data());
+ }
+
SerializedTypeID
getSType () const override
{
@@ -95,6 +150,13 @@ public:
value = v;
}
+ void
+ setValue (void const* data, std::size_t size)
+ {
+ value.resize(size);
+ std::memcpy(value.data(), data, size);
+ }
+
explicit
operator Blob () const
{
diff --git a/src/ripple/protocol/STExchange.h b/src/ripple/protocol/STExchange.h
new file mode 100644
index 0000000000..c2be05b297
--- /dev/null
+++ b/src/ripple/protocol/STExchange.h
@@ -0,0 +1,202 @@
+//------------------------------------------------------------------------------
+/*
+ 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_STEXCHANGE_H_INCLUDED
+#define RIPPLE_PROTOCOL_STEXCHANGE_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include //
+#include
+#include
+#include
+
+namespace ripple {
+
+/** Convert between serialized type U and C++ type T. */
+template
+struct STExchange;
+
+
+template
+struct STExchange, T>
+{
+ using value_type = U;
+
+ static
+ void
+ get (boost::optional& t,
+ STInteger const& u)
+ {
+ t = u.getValue();
+ }
+
+ static
+ std::unique_ptr>
+ set (SField const& f, T const& t)
+ {
+ return std::make_unique<
+ STInteger>(f, t);
+ }
+};
+
+template <>
+struct STExchange
+{
+ using value_type = Slice;
+
+ static
+ void
+ get (boost::optional& t,
+ STBlob const& u)
+ {
+ t = boost::in_place(u.data(), u.size());
+ }
+
+ static
+ std::unique_ptr
+ set (TypedField const& f,
+ Slice const& t)
+ {
+ return std::make_unique(
+ f, t.data(), t.size());
+ }
+};
+
+template <>
+struct STExchange
+{
+ using value_type = Buffer;
+
+ static
+ void
+ get (boost::optional& t,
+ STBlob const& u)
+ {
+ t = boost::in_place(
+ u.data(), u.size());
+ }
+
+ static
+ std::unique_ptr
+ set (TypedField const& f,
+ Buffer const& t)
+ {
+ return std::make_unique(
+ f, t.data(), t.size());
+ }
+
+ static
+ std::unique_ptr
+ set (TypedField const& f,
+ Buffer&& t)
+ {
+ return std::make_unique(
+ f, std::move(t));
+ }
+};
+
+//------------------------------------------------------------------------------
+
+/** Return the value of a field in an STObject as a given type. */
+/** @{ */
+template
+boost::optional
+get (STObject const& st,
+ TypedField const& f)
+{
+ boost::optional t;
+ STBase const* const b =
+ st.peekAtPField(f);
+ if (! b)
+ return t;
+ auto const id = b->getSType();
+ if (id == STI_NOTPRESENT)
+ return t;
+ auto const u =
+ dynamic_cast(b);
+ // This should never happen
+ if (! u)
+ throw std::runtime_error (
+ "Wrong field type");
+ STExchange::get(t, *u);
+ return t;
+}
+
+template
+boost::optional::value_type>
+get (STObject const& st,
+ TypedField const& f)
+{
+ return get(st, f);
+}
+/** @} */
+
+/** Set a field value in an STObject. */
+template
+void
+set (STObject& st,
+ TypedField const& f, T&& t)
+{
+ st.set(STExchange::type>::set(
+ f, std::forward(t)));
+}
+
+/** Set a blob field using an init function. */
+template
+void
+set (STObject& st,
+ TypedField const& f,
+ std::size_t size, Init&& init)
+{
+ st.set(std::make_unique(
+ f, size, init));
+}
+
+/** Set a blob field from data. */
+template
+void
+set (STObject& st,
+ TypedField const& f,
+ void const* data, std::size_t size)
+{
+ st.set(std::make_unique(
+ f, data, size));
+}
+
+/** Remove a field in an STObject. */
+template
+void
+erase (STObject& st,
+ TypedField const& f)
+{
+ st.makeFieldAbsent(f);
+}
+
+} // ripple
+
+#endif
diff --git a/src/ripple/protocol/STInteger.h b/src/ripple/protocol/STInteger.h
index e135829589..d6874a0f6d 100644
--- a/src/ripple/protocol/STInteger.h
+++ b/src/ripple/protocol/STInteger.h
@@ -29,6 +29,8 @@ class STInteger
: public STBase
{
public:
+ using value_type = Integer;
+
explicit
STInteger (Integer v)
: value_ (v)
diff --git a/src/ripple/protocol/STObject.h b/src/ripple/protocol/STObject.h
index 37f076a41a..1851a1e043 100644
--- a/src/ripple/protocol/STObject.h
+++ b/src/ripple/protocol/STObject.h
@@ -221,6 +221,12 @@ public:
const STVector256& getFieldV256 (SField::ref field) const;
const STArray& getFieldArray (SField::ref field) const;
+ /** Set a field.
+ if the field already exists, it is replaced.
+ */
+ void
+ set (std::unique_ptr v);
+
void setFieldU8 (SField::ref field, unsigned char);
void setFieldU16 (SField::ref field, std::uint16_t);
void setFieldU32 (SField::ref field, std::uint32_t);
@@ -419,8 +425,8 @@ private:
}
private:
- boost::ptr_vector mData;
- const SOTemplate* mType;
+ boost::ptr_vector mData;
+ const SOTemplate* mType;
};
} // ripple
diff --git a/src/ripple/protocol/Serializer.h b/src/ripple/protocol/Serializer.h
index c48c9f53fc..c3e9b0b21a 100644
--- a/src/ripple/protocol/Serializer.h
+++ b/src/ripple/protocol/Serializer.h
@@ -63,6 +63,18 @@ public:
;
}
+ std::size_t
+ size() const noexcept
+ {
+ return mData.size();
+ }
+
+ void const*
+ data() const noexcept
+ {
+ return mData.data();
+ }
+
// assemble functions
int add8 (unsigned char byte);
int add16 (std::uint16_t);
@@ -239,10 +251,6 @@ public:
{
return mData.end ();
}
- Blob ::size_type size () const
- {
- return mData.size ();
- }
void reserve (size_t n)
{
mData.reserve (n);
diff --git a/src/ripple/protocol/Sign.h b/src/ripple/protocol/Sign.h
new file mode 100644
index 0000000000..292aca5612
--- /dev/null
+++ b/src/ripple/protocol/Sign.h
@@ -0,0 +1,50 @@
+//------------------------------------------------------------------------------
+/*
+ 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_SIGN_H_INCLUDED
+#define RIPPLE_PROTOCOL_SIGN_H_INCLUDED
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+/** Sign a STObject using any secret key.
+ The signature is placed in sfSignature. If
+ a signature already exists, it is overwritten.
+*/
+void
+sign (STObject& st,
+ HashPrefix const& prefix,
+ AnySecretKey const& sk);
+
+/** Verify the signature on a STObject.
+ The signature must be contained in sfSignature.
+*/
+bool
+verify (STObject const& st,
+ HashPrefix const& prefix,
+ AnyPublicKeySlice const& pk);
+
+} // ripple
+
+#endif
diff --git a/src/ripple/protocol/impl/AnyPublicKey.cpp b/src/ripple/protocol/impl/AnyPublicKey.cpp
new file mode 100644
index 0000000000..0ce3b75764
--- /dev/null
+++ b/src/ripple/protocol/impl/AnyPublicKey.cpp
@@ -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.
+*/
+//==============================================================================
+
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+/** Verify a secp256k1 signature. */
+bool
+verify_secp256k1 (void const* pk,
+ void const* msg, std::size_t msg_size,
+ void const* sig, std::size_t sig_size)
+{
+ return false;
+}
+
+bool
+verify_ed25519 (void const* pk,
+ void const* msg, std::size_t msg_size,
+ void const* sig, std::size_t sig_size)
+{
+ if (sig_size != 64)
+ return false;
+ ed25519_public_key epk;
+ ed25519_signature es;
+ std::memcpy(epk, pk, 32);
+ std::memcpy(es, sig, sig_size);
+ return ed25519_sign_open(
+ reinterpret_cast(msg),
+ msg_size, epk, es) == 0;
+}
+
+//------------------------------------------------------------------------------
+
+KeyType
+AnyPublicKeySlice::type() const noexcept
+{
+ auto const pk = data();
+ auto const pk_size = size();
+
+ if (pk_size < 1)
+ return KeyType::unknown;
+ auto const len = pk_size - 1;
+ if (len == 32 &&
+ pk[0] == 0xED)
+ return KeyType::ed25519;
+ if (len == 33 &&
+ (pk[0] == 0x02 || pk[0] == 0x03))
+ return KeyType::secp256k1;
+ return KeyType::unknown;
+}
+
+bool
+AnyPublicKeySlice::verify (
+ void const* msg, std::size_t msg_size,
+ void const* sig, std::size_t sig_size) const
+{
+ switch(type())
+ {
+ case KeyType::ed25519:
+ return verify_ed25519(data() + 1,
+ msg, msg_size, sig, sig_size);
+ case KeyType::secp256k1:
+ return verify_secp256k1(data() + 1,
+ msg, msg_size, sig, sig_size);
+ default:
+ break;
+ }
+ // throw?
+ return false;
+}
+
+} // ripple
diff --git a/src/ripple/protocol/impl/AnySecretKey.cpp b/src/ripple/protocol/impl/AnySecretKey.cpp
new file mode 100644
index 0000000000..702d5a7f48
--- /dev/null
+++ b/src/ripple/protocol/impl/AnySecretKey.cpp
@@ -0,0 +1,143 @@
+//------------------------------------------------------------------------------
+/*
+ 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
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ripple {
+
+AnySecretKey::~AnySecretKey()
+{
+ // secure erase
+ std::fill(p_.data(), p_.data() + p_.size(), 0);
+}
+
+AnySecretKey::AnySecretKey (AnySecretKey&& other)
+ : p_ (std::move(other.p_))
+ , type_ (other.type_)
+{
+ other.type_ = KeyType::unknown;
+}
+
+AnySecretKey&
+AnySecretKey::operator= (AnySecretKey&& other)
+{
+ p_ = std::move(other.p_);
+ type_ = other.type_;
+ other.type_ = KeyType::unknown;
+ return *this;
+}
+
+AnySecretKey::AnySecretKey (KeyType type,
+ void const* data, std::size_t size)
+ : p_ (data, size)
+ , type_ (type)
+{
+ if (type_ == KeyType::unknown)
+ throw std::runtime_error(
+ "AnySecretKey: unknown type");
+ if (type_ == KeyType::ed25519 &&
+ size != 32)
+ throw std::runtime_error(
+ "AnySecretKey: wrong ed25519 size");
+ if (type_ == KeyType::secp256k1 &&
+ size != 32)
+ throw std::runtime_error(
+ "AnySecretKey: wrong secp256k1 size");
+}
+
+AnyPublicKey
+AnySecretKey::publicKey() const
+{
+ switch (type())
+ {
+ case KeyType::ed25519:
+ {
+ unsigned char buf[33];
+ buf[0] = 0xED;
+ ed25519_publickey(p_.data() + 1, &buf[1]);
+ return AnyPublicKey(buf, sizeof(buf));
+ }
+ default:
+ throw std::runtime_error(
+ "AnySecretKey: unknown type");
+ };
+}
+
+Buffer
+AnySecretKey::sign (
+ void const* msg, std::size_t msg_len) const
+{
+ switch(type_)
+ {
+ case KeyType::ed25519:
+ {
+ auto const sk = p_.data() + 1;
+ ed25519_public_key pk;
+ ed25519_publickey(sk, pk);
+ Buffer b(64);
+ ed25519_sign(reinterpret_cast<
+ unsigned char const*>(msg), msg_len,
+ sk, pk, b.data());
+ return b;
+ }
+ default:
+ break;
+ }
+ throw std::runtime_error(
+ "AnySecretKey: unknown type");
+}
+
+AnySecretKey
+AnySecretKey::make_ed25519()
+{
+ std::uint8_t buf[32];
+ random_fill(&buf[0], sizeof(buf));
+ AnySecretKey ask(KeyType::ed25519,
+ buf, sizeof(buf));
+ // secure erase
+ std::fill(buf, buf + sizeof(buf), 0);
+ return ask;
+}
+
+std::pair
+AnySecretKey::make_secp256k1_pair()
+{
+ // VFALCO What a pile
+ RippleAddress s;
+ s.setSeedRandom();
+ RippleAddress const g =
+ RippleAddress::createGeneratorPublic(s);
+ RippleAddress sk;
+ sk.setAccountPrivate (g, s, 0);
+ RippleAddress pk;
+ pk.setAccountPublic (g, 0);
+ return std::pair(
+ std::piecewise_construct, std::make_tuple(
+ KeyType::secp256k1, sk.data(), sk.size()),
+ std::make_tuple(pk.data(), pk.size()));
+}
+
+} // ripple
diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp
index 7eb2b2bac3..d6c7a3151a 100644
--- a/src/ripple/protocol/impl/SField.cpp
+++ b/src/ripple/protocol/impl/SField.cpp
@@ -41,7 +41,6 @@ typedef std::lock_guard StaticScopedLockType;
// Give this translation unit only, permission to construct SFields
struct SField::make
{
-#ifndef _MSC_VER
template
static SField one(SField const* p, Args&& ...args)
{
@@ -49,45 +48,14 @@ struct SField::make
knownCodeToField[result.fieldCode] = p;
return result;
}
-#else // remove this when VS gets variadic templates
- template
- static SField one(SField const* p, A0&& arg0)
- {
- SField result(std::forward(arg0));
- knownCodeToField[result.fieldCode] = p;
- return result;
- }
- template
- static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2)
+ template
+ static TypedField one(SField const* p, Args&& ...args)
{
- SField result(std::forward(arg0), std::forward(arg1),
- std::forward(arg2));
+ TypedField result(std::forward(args)...);
knownCodeToField[result.fieldCode] = p;
return result;
}
-
- template
- static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2,
- A3&& arg3)
- {
- SField result(std::forward(arg0), std::forward(arg1),
- std::forward(arg2), std::forward(arg3));
- knownCodeToField[result.fieldCode] = p;
- return result;
- }
-
- template
- static SField one(SField const* p, A0&& arg0, A1&& arg1, A2&& arg2,
- A3&& arg3, A4&& arg4)
- {
- SField result(std::forward(arg0), std::forward(arg1),
- std::forward(arg2), std::forward(arg3),
- std::forward(arg4));
- knownCodeToField[result.fieldCode] = p;
- return result;
- }
-#endif
};
using make = SField::make;
@@ -116,7 +84,7 @@ SField const sfTransactionType = make::one(&sfTransactionType, STI_UINT16, 2, "T
// 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");
+TypedField> 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");
@@ -203,20 +171,20 @@ SField const sfRippleEscrow = make::one(&sfRippleEscrow, STI_AMOUNT, 17, "
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");
+TypedField const sfPublicKey = make::one(&sfPublicKey, STI_VL, 1, "PublicKey");
+TypedField const sfSigningPubKey = make::one(&sfSigningPubKey, STI_VL, 3, "SigningPubKey");
+TypedField const sfSignature = make::one(&sfSignature, STI_VL, 6, "Signature", SField::sMD_Default, false);
+SField const sfMessageKey = make::one(&sfMessageKey, STI_VL, 2, "MessageKey");
+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 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");
diff --git a/src/ripple/protocol/impl/STObject.cpp b/src/ripple/protocol/impl/STObject.cpp
index ef58f247fb..0e92a25fe4 100644
--- a/src/ripple/protocol/impl/STObject.cpp
+++ b/src/ripple/protocol/impl/STObject.cpp
@@ -762,6 +762,24 @@ const STVector256& STObject::getFieldV256 (SField::ref field) const
return getFieldByConstRef (field, empty);
}
+void
+STObject::set (std::unique_ptr v)
+{
+ auto const i =
+ getFieldIndex(v->getFName());
+ if (i != -1)
+ {
+ mData.replace(i, v.release());
+ }
+ else
+ {
+ if (! isFree())
+ throw std::runtime_error(
+ "missing field in templated STObject");
+ mData.push_back(v.release());
+ }
+}
+
void STObject::setFieldU8 (SField::ref field, unsigned char v)
{
setFieldUsingSetValue (field, v);
diff --git a/src/ripple/protocol/impl/Sign.cpp b/src/ripple/protocol/impl/Sign.cpp
new file mode 100644
index 0000000000..f64c3a16c5
--- /dev/null
+++ b/src/ripple/protocol/impl/Sign.cpp
@@ -0,0 +1,51 @@
+//------------------------------------------------------------------------------
+/*
+ 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
+
+namespace ripple {
+
+void
+sign (STObject& st, HashPrefix const& prefix,
+ AnySecretKey const& sk)
+{
+ Serializer ss;
+ ss.add32(prefix);
+ st.add(ss, false);
+ set(st, sfSignature,
+ sk.sign(ss.data(), ss.size()));
+}
+
+bool
+verify (STObject const& st,
+ HashPrefix const& prefix,
+ AnyPublicKeySlice const& pk)
+{
+ auto const sig = get(st, sfSignature);
+ if (! sig)
+ return false;
+ Serializer ss;
+ ss.add32(prefix);
+ st.add(ss, false);
+ return pk.verify(
+ ss.data(), ss.size(),
+ sig->data(), sig->size());
+}
+
+} // ripple
diff --git a/src/ripple/unity/protocol.cpp b/src/ripple/unity/protocol.cpp
index c7693f6ded..0ba50c8d8c 100644
--- a/src/ripple/unity/protocol.cpp
+++ b/src/ripple/unity/protocol.cpp
@@ -19,6 +19,8 @@
#include
+#include
+#include
#include
#include
#include