mirror of
https://github.com/XRPLF/rippled.git
synced 2026-06-02 16:26:48 +00:00
139 lines
3.1 KiB
C++
139 lines
3.1 KiB
C++
#include <xrpl/conditions/Fulfillment.h>
|
|
|
|
#include <xrpl/basics/Slice.h>
|
|
#include <xrpl/basics/safe_cast.h>
|
|
#include <xrpl/conditions/Condition.h>
|
|
#include <xrpl/conditions/detail/PreimageSha256.h>
|
|
#include <xrpl/conditions/detail/error.h>
|
|
#include <xrpl/conditions/detail/utils.h>
|
|
|
|
#include <memory>
|
|
#include <system_error>
|
|
|
|
namespace xrpl {
|
|
namespace cryptoconditions {
|
|
|
|
bool
|
|
match(Fulfillment const& f, Condition const& c)
|
|
{
|
|
// Fast check: the fulfillment's type must match the
|
|
// conditions's type:
|
|
if (f.type() != c.type)
|
|
return false;
|
|
|
|
// Derive the condition from the given fulfillment
|
|
// and ensure that it matches the given condition.
|
|
return c == f.condition();
|
|
}
|
|
|
|
bool
|
|
validate(Fulfillment const& f, Condition const& c, Slice m)
|
|
{
|
|
return match(f, c) && f.validate(m);
|
|
}
|
|
|
|
bool
|
|
validate(Fulfillment const& f, Condition const& c)
|
|
{
|
|
return validate(f, c, {});
|
|
}
|
|
|
|
std::unique_ptr<Fulfillment>
|
|
Fulfillment::deserialize(Slice s, std::error_code& ec)
|
|
{
|
|
// Per the RFC, in a fulfillment we choose a type based
|
|
// on the tag of the item we contain:
|
|
//
|
|
// Fulfillment ::= CHOICE {
|
|
// preimageSha256 [0] PreimageFulfillment ,
|
|
// prefixSha256 [1] PrefixFulfillment,
|
|
// thresholdSha256 [2] ThresholdFulfillment,
|
|
// rsaSha256 [3] RsaSha256Fulfillment,
|
|
// ed25519Sha256 [4] Ed25519Sha512Fulfillment
|
|
// }
|
|
|
|
if (s.empty())
|
|
{
|
|
ec = error::buffer_empty;
|
|
return nullptr;
|
|
}
|
|
|
|
using namespace der;
|
|
|
|
auto const p = parsePreamble(s, ec);
|
|
if (ec)
|
|
return nullptr;
|
|
|
|
// All fulfillments are context-specific, constructed types
|
|
if (!isConstructed(p) || !isContextSpecific(p))
|
|
{
|
|
ec = error::malformed_encoding;
|
|
return nullptr;
|
|
}
|
|
|
|
if (p.length > s.size())
|
|
{
|
|
ec = error::buffer_underfull;
|
|
return {};
|
|
}
|
|
|
|
if (p.length < s.size())
|
|
{
|
|
ec = error::buffer_overfull;
|
|
return {};
|
|
}
|
|
|
|
if (p.length > maxSerializedFulfillment)
|
|
{
|
|
ec = error::large_size;
|
|
return {};
|
|
}
|
|
|
|
std::unique_ptr<Fulfillment> f;
|
|
|
|
using TagType = decltype(p.tag);
|
|
switch (p.tag)
|
|
{
|
|
case safe_cast<TagType>(Type::preimageSha256):
|
|
f = PreimageSha256::deserialize(Slice(s.data(), p.length), ec);
|
|
if (ec)
|
|
return {};
|
|
s += p.length;
|
|
break;
|
|
|
|
case safe_cast<TagType>(Type::prefixSha256):
|
|
ec = error::unsupported_type;
|
|
return {};
|
|
break;
|
|
|
|
case safe_cast<TagType>(Type::thresholdSha256):
|
|
ec = error::unsupported_type;
|
|
return {};
|
|
break;
|
|
|
|
case safe_cast<TagType>(Type::rsaSha256):
|
|
ec = error::unsupported_type;
|
|
return {};
|
|
break;
|
|
|
|
case safe_cast<TagType>(Type::ed25519Sha256):
|
|
ec = error::unsupported_type;
|
|
return {};
|
|
|
|
default:
|
|
ec = error::unknown_type;
|
|
return {};
|
|
}
|
|
|
|
if (!s.empty())
|
|
{
|
|
ec = error::trailing_garbage;
|
|
return {};
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
} // namespace cryptoconditions
|
|
} // namespace xrpl
|