Files
rippled/include/xrpl/conditions/Fulfillment.h
2026-02-20 12:15:30 -05:00

124 lines
3.4 KiB
C++

#pragma once
#include <xrpl/basics/Buffer.h>
#include <xrpl/basics/Slice.h>
#include <xrpl/conditions/Condition.h>
namespace xrpl {
namespace cryptoconditions {
struct Fulfillment
{
public:
/** The largest binary fulfillment we support.
@note This value will be increased in the future, but it
must never decrease, as that could cause fulfillments
that were previously considered valid to no longer
be allowed.
*/
static constexpr std::size_t maxSerializedFulfillment = 256;
/** Load a fulfillment from its binary form
@param s The buffer containing the fulfillment to load.
@param ec Set to the error, if any occurred.
The binary format for a fulfillment is specified in the
cryptoconditions RFC. See:
https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-7.3
*/
static std::unique_ptr<Fulfillment>
deserialize(Slice s, std::error_code& ec);
public:
virtual ~Fulfillment() = default;
/** Returns the fulfillment's fingerprint:
The fingerprint is an octet string uniquely
representing this fulfillment's condition
with respect to other conditions of the
same type.
*/
virtual Buffer
fingerprint() const = 0;
/** Returns the type of this condition. */
virtual Type
type() const = 0;
/** Validates a fulfillment. */
virtual bool
validate(Slice data) const = 0;
/** Calculates the cost associated with this fulfillment. *
The cost function is deterministic and depends on the
type and properties of the condition and the fulfillment
that the condition is generated from.
*/
virtual std::uint32_t
cost() const = 0;
/** Returns the condition associated with the given fulfillment.
This process is completely deterministic. All implementations
will, if compliant, produce the identical condition for the
same fulfillment.
*/
virtual Condition
condition() const = 0;
};
inline bool
operator==(Fulfillment const& lhs, Fulfillment const& rhs)
{
// FIXME: for compound conditions, need to also check subtypes
return lhs.type() == rhs.type() && lhs.cost() == rhs.cost() &&
lhs.fingerprint() == rhs.fingerprint();
}
inline bool
operator!=(Fulfillment const& lhs, Fulfillment const& rhs)
{
return !(lhs == rhs);
}
/** Determine whether the given fulfillment and condition match */
bool
match(Fulfillment const& f, Condition const& c);
/** Verify if the given message satisfies the fulfillment.
@param f The fulfillment
@param c The condition
@param m The message
@note the message is not relevant for some conditions
and a fulfillment will successfully satisfy its
condition for any given message.
*/
bool
validate(Fulfillment const& f, Condition const& c, Slice m);
/** Verify a cryptoconditional trigger.
A cryptoconditional trigger is a cryptocondition with
an empty message.
When using such triggers, it is recommended that the
trigger be of type preimage, prefix or threshold. If
a signature type is used (i.e. Ed25519 or RSA-SHA256)
then the Ed25519 or RSA keys should be single-use keys.
@param f The fulfillment
@param c The condition
*/
bool
validate(Fulfillment const& f, Condition const& c);
} // namespace cryptoconditions
} // namespace xrpl