Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RNG API #364

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
58 changes: 58 additions & 0 deletions libraries/app/database_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class database_api_impl : public std::enable_shared_from_this<database_api_impl>
vector<offer_history_object> get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const;
vector<offer_history_object> get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const;

// rng
vector<uint64_t> get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const;
uint64_t get_random_number(uint64_t bound) const;

//private:
const account_object* get_account_from_string( const std::string& name_or_id,
bool throw_if_not_found = true ) const;
Expand Down Expand Up @@ -2888,6 +2892,60 @@ vector<offer_history_object> database_api_impl::get_offer_history_by_bidder(cons

return result;
}

//////////////////////////////////////////////////////////////////////
// //
// Random numbers //
// //
//////////////////////////////////////////////////////////////////////

vector<uint64_t> database_api::get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const
{
return my->get_random_number_ex(minimum, maximum, selections, duplicates);
}

vector<uint64_t> database_api_impl::get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const
{
FC_ASSERT( selections <= 100000 );
if (duplicates == false) {
FC_ASSERT( maximum - minimum >= selections );
}

vector<uint64_t> v;
v.reserve(selections);

if (duplicates) {
for (uint64_t i = 0; i < selections; i++) {
int64_t rnd = _db.get_random_bits(maximum - minimum) + minimum;
v.push_back(rnd);
}
} else {
vector<uint64_t> tmpv;
tmpv.reserve(selections);
for (uint64_t i = minimum; i < maximum; i++) {
tmpv.push_back(i);
}

for (uint64_t i = 0; (i < selections) && (tmpv.size() > 0); i++) {
uint64_t idx = _db.get_random_bits(tmpv.size());
v.push_back(tmpv.at(idx));
tmpv.erase(tmpv.begin() + idx);
}
}

return v;
}

uint64_t database_api::get_random_number(uint64_t bound) const
{
return my->get_random_number(bound);
}

uint64_t database_api_impl::get_random_number(uint64_t bound) const {
vector<uint64_t> v = get_random_number_ex(0, bound, 1, false);
return v.at(0);
}

//////////////////////////////////////////////////////////////////////
// //
// Private methods //
Expand Down
27 changes: 26 additions & 1 deletion libraries/app/include/graphene/app/database_api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,28 @@ class database_api
vector<offer_history_object> get_offer_history_by_issuer(const offer_history_id_type lower_id, const account_id_type issuer_account_id, uint32_t limit) const;
vector<offer_history_object> get_offer_history_by_item(const offer_history_id_type lower_id, const nft_id_type item, uint32_t limit) const;
vector<offer_history_object> get_offer_history_by_bidder(const offer_history_id_type lower_id, const account_id_type bidder_account_id, uint32_t limit) const;
private:

/////////////////////////////
// Random number generator //
/////////////////////////////
/**
* @brief Returns the random number
* @param minimum Lower bound of segment containing random number
* @param maximum Upper bound of segment containing random number
* @param selections Number of random numbers to return
* @param duplicates Allow duplicated numbers
* @return Vector containing random numbers from segment [minimum, maximum)
*/
vector<uint64_t> get_random_number_ex(uint64_t minimum, uint64_t maximum, uint64_t selections, bool duplicates) const;

/**
* @brief Returns the random number
* @param bound Upper bound of segment containing random number
* @return Random number from segment [0, bound)
*/
uint64_t get_random_number(uint64_t bound) const;

private:
std::shared_ptr< database_api_impl > my;
};

Expand Down Expand Up @@ -999,4 +1020,8 @@ FC_API(graphene::app::database_api,
(get_offer_history_by_issuer)
(get_offer_history_by_item)
(get_offer_history_by_bidder)

// rngs
(get_random_number_ex)
(get_random_number)
)
2 changes: 2 additions & 0 deletions libraries/chain/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ add_library( graphene_chain
nft_evaluator.cpp
protocol/nft.cpp

random_number_evaluator.cpp

${HEADERS}
${PROTOCOL_HEADERS}
"${CMAKE_CURRENT_BINARY_DIR}/include/graphene/chain/hardfork.hpp"
Expand Down
7 changes: 7 additions & 0 deletions libraries/chain/db_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <graphene/chain/custom_permission_object.hpp>
#include <graphene/chain/custom_account_authority_object.hpp>
#include <graphene/chain/offer_object.hpp>
#include <graphene/chain/random_number_object.hpp>

#include <graphene/chain/nft_object.hpp>

Expand Down Expand Up @@ -85,6 +86,7 @@
#include <graphene/chain/custom_account_authority_evaluator.hpp>
#include <graphene/chain/offer_evaluator.hpp>
#include <graphene/chain/nft_evaluator.hpp>
#include <graphene/chain/random_number_evaluator.hpp>

#include <graphene/chain/protocol/fee_schedule.hpp>

Expand Down Expand Up @@ -186,6 +188,9 @@ const uint8_t offer_object::type_id;
const uint8_t offer_history_object::space_id;
const uint8_t offer_history_object::type_id;

const uint8_t random_number_object::space_id;
const uint8_t random_number_object::type_id;

void database::initialize_evaluators()
{
_operation_evaluators.resize(255);
Expand Down Expand Up @@ -275,6 +280,7 @@ void database::initialize_evaluators()
register_evaluator<nft_safe_transfer_from_evaluator>();
register_evaluator<nft_approve_evaluator>();
register_evaluator<nft_set_approval_for_all_evaluator>();
register_evaluator<random_number_store_evaluator>();
}

void database::initialize_indexes()
Expand Down Expand Up @@ -353,6 +359,7 @@ void database::initialize_indexes()
add_index< primary_index<lottery_balance_index > >();
add_index< primary_index<sweeps_vesting_balance_index > >();
add_index< primary_index<offer_history_index > >();
add_index< primary_index<random_number_index > >();

}

Expand Down
3 changes: 3 additions & 0 deletions libraries/chain/db_notify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,9 @@ struct get_impacted_account_visitor
void operator()( const finalize_offer_operation& op ) {
_impacted.insert( op.fee_paying_account );
}
void operator()( const random_number_store_operation& op ) {
_impacted.insert( op.account );
}
};

void graphene::chain::operation_get_impacted_accounts( const operation& op, flat_set<account_id_type>& result )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <graphene/chain/protocol/custom_account_authority.hpp>
#include <graphene/chain/protocol/offer.hpp>
#include <graphene/chain/protocol/nft_ops.hpp>
#include <graphene/chain/protocol/random_number.hpp>

namespace graphene { namespace chain {

Expand Down Expand Up @@ -155,7 +156,8 @@ namespace graphene { namespace chain {
nft_mint_operation,
nft_safe_transfer_from_operation,
nft_approve_operation,
nft_set_approval_for_all_operation
nft_set_approval_for_all_operation,
random_number_store_operation
> operation;

/// @} // operations group
Expand Down
25 changes: 25 additions & 0 deletions libraries/chain/include/graphene/chain/protocol/random_number.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

namespace graphene { namespace chain {

struct random_number_store_operation : public base_operation
{
struct fee_parameters_type { uint64_t fee = 5000 * GRAPHENE_BLOCKCHAIN_PRECISION; };

asset fee;

account_id_type account;
vector<uint64_t> random_number;
std::string data;

account_id_type fee_payer()const { return account; }
};

} } // graphene::chain

FC_REFLECT( graphene::chain::random_number_store_operation::fee_parameters_type, (fee) )
FC_REFLECT( graphene::chain::random_number_store_operation, (fee)
(account)
(random_number)
(data) )

5 changes: 5 additions & 0 deletions libraries/chain/include/graphene/chain/protocol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ namespace graphene { namespace chain {
offer_object_type,
nft_metadata_type,
nft_object_type,
random_number_object_type,
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
};

Expand Down Expand Up @@ -241,6 +242,7 @@ namespace graphene { namespace chain {
class offer_object;
class nft_metadata_object;
class nft_object;
class random_number_object;

typedef object_id< protocol_ids, account_object_type, account_object> account_id_type;
typedef object_id< protocol_ids, asset_object_type, asset_object> asset_id_type;
Expand Down Expand Up @@ -272,6 +274,7 @@ namespace graphene { namespace chain {
typedef object_id< protocol_ids, offer_object_type, offer_object> offer_id_type;
typedef object_id< protocol_ids, nft_metadata_type, nft_metadata_object> nft_metadata_id_type;
typedef object_id< protocol_ids, nft_object_type, nft_object> nft_id_type;
typedef object_id< protocol_ids, random_number_object_type, random_number_object> random_number_id_type;

// implementation types
class global_property_object;
Expand Down Expand Up @@ -459,6 +462,7 @@ FC_REFLECT_ENUM( graphene::chain::object_type,
(offer_object_type)
(nft_metadata_type)
(nft_object_type)
(random_number_object_type)
(OBJECT_TYPE_COUNT)
)
FC_REFLECT_ENUM( graphene::chain::impl_object_type,
Expand Down Expand Up @@ -535,6 +539,7 @@ FC_REFLECT_TYPENAME( graphene::chain::custom_account_authority_id_type )
FC_REFLECT_TYPENAME( graphene::chain::offer_history_id_type )
FC_REFLECT_TYPENAME( graphene::chain::nft_metadata_id_type )
FC_REFLECT_TYPENAME( graphene::chain::nft_id_type )
FC_REFLECT_TYPENAME( graphene::chain::random_number_id_type )

FC_REFLECT( graphene::chain::void_t, )

Expand Down
19 changes: 19 additions & 0 deletions libraries/chain/include/graphene/chain/random_number_evaluator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include <graphene/chain/database.hpp>
#include <graphene/chain/evaluator.hpp>
#include <graphene/chain/protocol/operations.hpp>
#include <graphene/chain/protocol/types.hpp>

namespace graphene { namespace chain {

class random_number_store_evaluator : public evaluator<random_number_store_evaluator>
{
public:
typedef random_number_store_operation operation_type;

void_result do_evaluate( const random_number_store_operation& o );
object_id_type do_apply( const random_number_store_operation& o );
};

} } // graphene::chain

41 changes: 41 additions & 0 deletions libraries/chain/include/graphene/chain/random_number_object.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

namespace graphene { namespace chain {
using namespace graphene::db;

class random_number_object : public abstract_object<random_number_object>
{
public:
static const uint8_t space_id = protocol_ids;
static const uint8_t type_id = random_number_object_type;

account_id_type account; /* account who requested random number */
time_point_sec timestamp; /* date and time when the number is read */
vector<uint64_t> random_number; /* random number(s) */
std::string data; /* custom data in json format */
};

struct by_account;
struct by_timestamp;
using random_number_multi_index_type = multi_index_container<
random_number_object,
indexed_by<
ordered_unique< tag<by_id>,
member<object, object_id_type, &object::id>
>,
ordered_non_unique< tag<by_account>,
member<random_number_object, account_id_type, &random_number_object::account>
>,
ordered_non_unique< tag<by_timestamp>,
member<random_number_object, time_point_sec, &random_number_object::timestamp>
>
>
>;
using random_number_index = generic_index<random_number_object, random_number_multi_index_type>;

} } // graphene::chain

FC_REFLECT_DERIVED( graphene::chain::random_number_object, (graphene::db::object),
(account) (timestamp)
(random_number) (data) )

24 changes: 24 additions & 0 deletions libraries/chain/random_number_evaluator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <graphene/chain/random_number_evaluator.hpp>
#include <graphene/chain/random_number_object.hpp>

namespace graphene { namespace chain {

void_result random_number_store_evaluator::do_evaluate( const random_number_store_operation& op )
{ try {

return void_result();
} FC_CAPTURE_AND_RETHROW( (op) ) }

object_id_type random_number_store_evaluator::do_apply( const random_number_store_operation& op )
{ try {
const auto& new_random_number_object = db().create<random_number_object>( [&]( random_number_object& obj ) {
obj.account = op.account;
obj.timestamp = db().head_block_time();
obj.random_number = op.random_number;
obj.data = op.data;
});
return new_random_number_object.id;
} FC_CAPTURE_AND_RETHROW( (op) ) }

} } // graphene::chain

Loading