31 namespace graphene {
namespace protocol {
42 template<
typename> constexpr
static bool is_safe =
false;
43 template<
typename I> constexpr
static bool is_safe<fc::safe<I>> =
true;
51 template<
typename T> constexpr
static bool is_integral = !std::is_same<T, bool>::value &&
52 !std::is_same<T, safe<bool>>::value &&
53 (is_safe<T> || std::is_integral<T>::value);
56 template<
typename T,
typename U>
57 constexpr
static bool comparable_types = !std::is_same<T, void_t>::value &&
58 (std::is_same<T, U>::value || (is_integral<T> && is_integral<U>));
61 template<
typename,
typename =
void>
68 template<
typename Field>
72 template<typename I, typename=std::enable_if_t<std::is_integral<I>::value>>
73 const auto&
to_num(
const I& i) {
return i; }
125 force_settlement_id_type, committee_member_id_type, witness_id_type,
126 limit_order_id_type, call_order_id_type, custom_id_type,
127 proposal_id_type, withdraw_permission_id_type,
128 vesting_balance_id_type, worker_id_type, balance_id_type>;
144 template<
typename A,
typename B>
146 constexpr
static bool valid =
false;
152 template<
typename Field,
typename Argument>
153 struct predicate_eq<Field, Argument,
std::enable_if_t<std::is_same<Field, Argument>::value>> {
155 constexpr
static bool valid =
true;
156 constexpr
bool operator()(
const Field& f,
const Argument& a)
const {
return f == a; }
158 template<
typename Field,
typename Argument>
159 struct predicate_eq<Field, Argument,
std::enable_if_t<is_integral<Field> && is_integral<Argument> &&
160 !std::is_same<Field, Argument>::value>> {
162 constexpr
static bool valid =
true;
165 template<
typename Field,
typename Argument>
166 struct predicate_eq<Field, Argument,
std::enable_if_t<is_container<Field> && is_integral<Argument>>> {
168 constexpr
static bool valid =
true;
169 bool operator()(
const Field& f,
const Argument& a)
const {
return safenum::equal(f.size(),
to_num(a)); }
171 template<
typename Field,
typename Argument>
178 return (*
this)(*f, a);
181 template<
typename Field>
184 constexpr
static bool valid =
true;
190 bool operator()(
const Field& f,
const Argument& a)
const {
return !equal::operator()(f, a); }
195 template<
typename Field,
typename Argument>
198 constexpr
static bool valid =
true;
199 constexpr int8_t
operator()(
const Field& f,
const Argument& a)
const {
200 return f<a? -1 : (f>a? 1 : 0);
203 template<
typename Field,
typename Argument>
205 !std::is_same<Field, Argument>::value>> {
207 constexpr
static bool valid =
true;
208 constexpr int8_t
operator()(
const Field& f,
const Argument& a)
const {
211 return safenum::less_than(nf, na)? -1 : (safenum::greater_than(nf, na)? 1 : 0);
214 template<
typename Field,
typename Argument>
217 constexpr
static bool valid =
true;
220 return (*
this)(*f, a);
226 constexpr
bool operator()(
const Field& f,
const Argument& a)
const {
return base::operator()(f, a) < 0; }
230 constexpr
bool operator()(
const Field& f,
const Argument& a)
const {
return base::operator()(f, a) <= 0; }
234 constexpr
bool operator()(
const Field& f,
const Argument& a)
const {
return base::operator()(f, a) > 0; }
238 constexpr
bool operator()(
const Field& f,
const Argument& a)
const {
return base::operator()(f, a) >= 0; }
243 template<
typename Field,
typename Element>
244 struct predicate_in<Field, flat_set<Element>,
std::enable_if_t<comparable_types<Field, Element> && !is_safe<Field>>> {
246 constexpr
static bool valid =
true;
247 bool operator()(
const Field& f,
const flat_set<Element>& c)
const {
return c.count(f) != 0; }
249 template<
typename Field,
typename Element>
250 struct predicate_in<
fc::
safe<Field>, flat_set<Element>, std::enable_if_t<comparable_types<Field, Element>>> {
252 constexpr
static bool valid =
true;
255 template<
typename Field,
typename Element>
258 constexpr
static bool valid =
true;
261 return c.count(*f) != 0;
264 template<
typename Container,
typename Element>
266 std::enable_if_t<is_container<Container> &&
267 comparable_types<typename Container::value_type, Element>>> {
269 constexpr
static bool valid =
true;
271 template<
typename C = Container, std::enable_if_t<!is_flat_set<C>,
bool> = true>
272 bool operator()(
const Container& c,
const flat_set<Element>& a)
const {
273 return std::all_of(c.begin(), c.end(), [&a](
const auto& ce) {
return a.count(ce) > 0; });
276 template<
typename C = Container, std::enable_if_t<is_flat_set<C>,
bool> = true>
277 bool operator()(
const Container& c,
const flat_set<Element>& a)
const {
278 return std::includes(a.begin(), a.end(), c.begin(), c.end());
284 bool operator()(
const Field& f,
const Container& c)
const {
return !base::operator()(f, c); }
287 template<
typename Container,
typename Element>
289 std::enable_if_t<is_container<Container> &&
290 comparable_types<typename Container::value_type, Element>>> {
291 constexpr
static bool valid =
true;
293 template<
typename C = Container, std::enable_if_t<!is_flat_set<C>,
bool> = true>
294 bool operator()(
const Container& c,
const flat_set<Element>& a)
const {
295 return std::none_of(c.begin(), c.end(), [&a](
const auto& ce) {
return a.count(ce) > 0; });
298 template<
typename C = Container, std::enable_if_t<is_flat_set<C>,
bool> = true>
299 bool operator()(
const Container& c,
const flat_set<Element>& a)
const {
300 flat_set<typename Container::value_type> intersection;
301 std::set_intersection(c.begin(), c.end(), a.begin(), a.end(),
302 std::inserter(intersection, intersection.begin()));
303 return intersection.empty();
309 template<
typename FieldElement,
typename ArgumentElement>
311 std::enable_if_t<comparable_types<FieldElement, ArgumentElement>>> {
313 constexpr
static bool valid =
true;
314 bool operator()(
const flat_set<FieldElement>& f,
const flat_set<ArgumentElement>& a)
const {
315 if (f.size() < a.size())
return false;
316 return std::includes(f.begin(), f.end(), a.begin(), a.end());
319 template<
typename FieldContainer,
typename ArgumentElement>
321 std::enable_if_t<is_container<FieldContainer> && !is_flat_set<FieldContainer> &&
322 comparable_types<typename FieldContainer::value_type, ArgumentElement>>> {
324 constexpr
static bool valid =
true;
325 bool operator()(
const FieldContainer& f,
const flat_set<ArgumentElement>& a)
const {
326 if (f.size() < a.size())
return false;
327 std::set<typename FieldContainer::value_type> fs(f.begin(), f.end());
328 return std::includes(fs.begin(), fs.end(), a.begin(), a.end());
331 template<
typename OptionalType,
typename Argument>
336 return (*
this)(*f, a);
342 template<
typename FieldElement,
typename ArgumentElement>
344 std::enable_if_t<comparable_types<FieldElement, ArgumentElement>>> {
346 constexpr
static bool valid =
true;
347 bool operator()(
const flat_set<FieldElement>& f,
const flat_set<ArgumentElement>& a)
const {
348 flat_set<FieldElement> intersection;
349 std::set_intersection(f.begin(), f.end(), a.begin(), a.end(),
350 std::inserter(intersection, intersection.begin()));
351 return intersection.empty();
354 template<
typename FieldContainer,
typename ArgumentElement>
356 std::enable_if_t<is_container<FieldContainer> && !is_flat_set<FieldContainer> &&
357 comparable_types<typename FieldContainer::value_type, ArgumentElement>>> {
359 constexpr
static bool valid =
true;
360 bool operator()(
const FieldContainer& f,
const flat_set<ArgumentElement>& a)
const {
361 return !std::any_of(f.begin(), f.end(), [&a](
const auto& fe) {
return a.count(fe) > 0; });
364 template<
typename OptionalType,
typename Argument>
369 return (*
this)(*f, a);
377 template<
typename Field>
380 return restrictions_to_predicate<Field>(std::move(rs),
false);
383 template<
typename Field>
386 return [p=restrictions_to_predicate<Field>(std::move(rs),
false)](
const fc::optional<Field>& f) {
392 template<
typename Extension>
395 return [p=restrictions_to_predicate<Extension>(std::move(rs),
false)](
const extension<Extension>& x) {
401 template<
typename Variant>
404 FC_THROW_EXCEPTION(fc::assert_exception,
"Invalid variant assertion on non-variant field",
408 template<
typename... Types>
412 template<
typename Value>
414 return [p=restrictions_to_predicate<Value>(std::move(rs),
true)](
const Variant& v) {
415 if (v.
which() == Variant::template tag<Value>::value)
416 return p(v.template get<Value>());
423 using Value = typename decltype(t)::type;
424 return variant_assertion::make_predicate<Value>(std::move(arg.second));
428 template<
typename... Types>
435 using Value = typename decltype(t)::type;
436 auto pred = variant_assertion<Variant>::template make_predicate<Value>(std::move(arg.second));
437 return [p=std::move(pred)](const Optional& opt) {
438 if (!opt.valid()) return predicate_result::Rejection(predicate_result::null_optional);
446 template<
typename F,
typename P,
typename A,
typename = std::enable_if_t<P::val
id>>
448 return [p=std::move(p), a=std::move(a)](
const F& f) {
453 template<
typename F,
typename P,
typename A>
459 template<
template<
typename...>
class Predicate,
typename Field,
typename ArgVariant>
463 using Arg =
typename decltype(t)::type;
464 return embed_argument<Field>(Predicate<Field, Arg>(), std::move(arg.template get<Arg>()),
short());
468 template<
typename Field>
500 FC_ASSERT(arg.
which() == restriction_argument::tag<vector<restriction>>::value,
501 "Argument type for attribute assertion must be restriction list");
504 FC_ASSERT(arg.
which() == restriction_argument::tag<restriction::variant_assert_argument_type>::value,
505 "Argument type for attribute assertion must be pair of variant tag and restriction list");
524 template<
typename Object,
525 typename = std::enable_if_t<typelist::length<typename fc::reflector<Object>::native_members>() != 0>>
528 FC_ASSERT( r.member_index < static_cast<uint64_t>(typelist::length<member_list>()),
529 "Invalid member index ${I} for object ${O}",
532 using FieldReflection =
typename decltype(t)::type;
533 using Field =
typename FieldReflection::type;
535 return [p=std::move(p)](
const Object& o) {
return p(FieldReflection::get(o)); };
539 template<
typename Object>
541 FC_THROW_EXCEPTION(fc::assert_exception,
"Invalid restriction references member of non-object type: ${O}",
545 template<
typename Object>
547 FC_ASSERT(rs.size() > 1,
"Logical OR must have at least two branches");
548 auto to_predicate = std::bind(restrictions_to_predicate<Object>, std::placeholders::_1,
false);
550 vector<object_restriction_predicate<Object>> predicates;
551 std::transform(std::make_move_iterator(rs.begin()), std::make_move_iterator(rs.end()),
552 std::back_inserter(predicates), to_predicate);
554 return [predicates=std::move(predicates)](
const Object& obj) {
555 vector<predicate_result> rejections;
556 bool success = std::any_of(predicates.begin(), predicates.end(),
557 [o=std::cref(obj), &rejections](
const auto& p) {
559 if (!result) rejections.push_back(std::move(result));
567 template<
typename Object>
570 FC_ASSERT(!rs.empty(),
"Empty attribute assertions and logical OR branches are not permitted");
572 vector<object_restriction_predicate<Object>> predicates;
573 std::transform(std::make_move_iterator(rs.begin()), std::make_move_iterator(rs.end()),
574 std::back_inserter(predicates), [](
restriction&& r) {
576 FC_ASSERT(r.argument.which() == restriction_argument::tag<vector<vector<restriction>>>::value,
577 "Restriction argument for logical OR function type must be list of restriction lists.");
578 return create_logical_or_predicate<Object>(std::move(r.argument.get<vector<vector<restriction>>>()));
580 return create_field_predicate<Object>(std::move(r), short());
583 return [predicates=std::move(predicates)](
const Object& obj) {
584 for (
size_t i = 0; i < predicates.size(); ++i) {
585 auto result = predicates[i](obj);
587 result.rejection_path.push_back(i);
constexpr bool operator()(const Field &f, const Argument &a) const
static object_restriction_predicate< Variant > create(restriction::variant_assert_argument_type &&)
object_restriction_predicate< F > embed_argument(P p, A a, short)
bool operator()(const Container &c, const flat_set< Element > &a) const
static static_variant import_from(const static_variant< Other... > &other)
bool operator()(const flat_set< FieldElement > &f, const flat_set< ArgumentElement > &a) const
object_restriction_predicate< Object > create_logical_or_predicate(vector< vector< restriction >> rs)
constexpr int8_t operator()(const fc::optional< Field > &f, const Argument &a) const
bool operator()(const Field &f, const Argument &a) const
bool operator()(const flat_set< FieldElement > &f, const flat_set< ArgumentElement > &a) const
static object_restriction_predicate< extension< Extension > > create(vector< restriction > &&rs)
constexpr bool operator()(const Field &f, const Argument &a) const
static object_restriction_predicate< Variant > create(restriction::variant_assert_argument_type &&arg)
constexpr bool operator()(const Field &f, const Argument &a) const
bool operator()(const Field &f, const flat_set< Element > &c) const
static predicate_result Rejection(rejection_reason reason)
bool operator()(const FieldContainer &f, const flat_set< ArgumentElement > &a) const
constexpr bool operator()(const Field &f, const Argument &a) const
constexpr bool operator()(const Field &f, const Argument &a) const
provides stack-based nullable value similar to boost::optional
bool operator()(const A &, const B &) const
bool operator()(const fc::optional< Field > &f, const flat_set< Element > &c) const
static object_restriction_predicate< Optional > create(restriction::variant_assert_argument_type &&arg)
bool operator()(const fc::optional< Field > &f, const Argument &a) const
constexpr int8_t operator()(const Field &f, const Argument &a) const
const auto & to_num(const I &i)
constexpr bool operator()(const Field &f, const Argument &a) const
pair< int64_t, vector< restriction > > variant_assert_argument_type
bool operator()(const FieldContainer &f, const flat_set< ArgumentElement > &a) const
bool operator()(const Container &c, const flat_set< Element > &a) const
bool operator()(const Field &f, const Container &c) const
static predicate_result Success()
static auto make_predicate(vector< restriction > &&rs)
This namespace contains the list type, and all of the operations and queries which can be performed u...
#define FC_CAPTURE_AND_RETHROW(...)
object_restriction_predicate< Field > make_predicate(ArgVariant arg)
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
object_restriction_predicate< Object > restrictions_to_predicate(vector< restriction >, bool)
static object_restriction_predicate< Field > create(vector< restriction > &&rs)
fc::static_variant< GRAPHENE_OP_RESTRICTION_ARGUMENTS_VARIADIC > argument_type
template object_restriction_predicate< share_type > create_predicate_function(restriction_function func, restriction_argument arg)
#define FC_THROW_EXCEPTION(EXCEPTION, FORMAT,...)
typelist::list< int64_t, string, time_point_sec, account_id_type, asset_id_type, force_settlement_id_type, committee_member_id_type, witness_id_type, limit_order_id_type, call_order_id_type, custom_id_type, proposal_id_type, withdraw_permission_id_type, vesting_balance_id_type, worker_id_type, balance_id_type > comparable_types_list
typelist::transform< typelist::concat< typelist::list< bool, public_key_type, fc::sha256 >, comparable_types_list >, make_flat_set > list_types_list
Defines exception's used by fc.
bool operator()(const fc::optional< OptionalType > &f, const Argument &a) const
static object_restriction_predicate< fc::optional< Field > > create(vector< restriction > &&rs)
std::function< predicate_result(const Field &)> object_restriction_predicate
typename impl::transform< List, Transformer >::type transform
Transform elements of a typelist.
bool operator()(const fc::optional< OptionalType > &f, const Argument &a) const
typename impl::concat< Lists... >::type concat
Concatenate two or more typelists together.
bool operator()(const Field &f, const Argument &a) const
uint32_t sec_since_epoch() const
constexpr int8_t operator()(const Field &f, const Argument &a) const
object_restriction_predicate< Object > create_field_predicate(restriction &&r, short)
Create a predicate asserting on the field of the object a restriction is referencing.
bool operator()(const fc::safe< Field > &f, const flat_set< Element > &c) const
typename typelist::concat< typelist::list< void_t, bool, public_key_type, fc::sha256 >, comparable_types_list, list_types_list > equality_types_list
Return dispatch(list< Types... >, std::size_t index, Callable c)
Index into the typelist for a type T, and invoke the callable with an argument wrapper<T>() ...
bool operator()(const fc::optional< Field > &f, const void_t &) const