Skip to content

Commit

Permalink
Convert target -> difficulty #256
Browse files Browse the repository at this point in the history
  • Loading branch information
theoreticalbts committed Aug 10, 2016
1 parent 8885009 commit 581317f
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 40 deletions.
19 changes: 19 additions & 0 deletions libraries/chain/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,12 @@ fc::sha256 database::get_pow_target()const
return target;
}

uint32_t database::get_difficulty_target()const
{
const dynamic_global_property_object& dgp = get_dynamic_global_properties();
return ((dgp.num_pow_witnesses/4)+4);
}

void database::update_witness_schedule4()
{
vector<string> active_witnesses;
Expand Down Expand Up @@ -2648,6 +2654,7 @@ void database::_apply_block( const signed_block& next_block )
create_block_summary(next_block);
clear_expired_transactions();
clear_expired_orders();
clear_work_nonces();
update_witness_schedule();

update_median_feed();
Expand Down Expand Up @@ -3243,6 +3250,18 @@ void database::clear_expired_orders()
}
}

void database::clear_work_nonces()
{
auto& idx = get_index_type<work_nonce_index>().indices().get<by_id>();
while( true )
{
auto it = idx.begin();
if( it == idx.end() )
break;
remove(*it);
}
}

void database::adjust_balance( const account_object& a, const asset& delta )
{
modify( a, [&]( account_object& acnt )
Expand Down
2 changes: 2 additions & 0 deletions libraries/chain/include/steemit/chain/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ namespace steemit { namespace chain {
bool is_known_block( const block_id_type& id )const;
bool is_known_transaction( const transaction_id_type& id )const;
fc::sha256 get_pow_target()const;
uint32_t get_difficulty_target()const;
block_id_type get_block_id_for_num( uint32_t block_num )const;
optional<signed_block> fetch_block_by_id( const block_id_type& id )const;
optional<signed_block> fetch_block_by_number( uint32_t num )const;
Expand Down Expand Up @@ -396,6 +397,7 @@ namespace steemit { namespace chain {
void update_last_irreversible_block();
void clear_expired_transactions();
void clear_expired_orders();
void clear_work_nonces();
void process_header_extensions( const signed_block& next_block );

void reset_virtual_schedule_time();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@ namespace steemit { namespace chain {
string worker_account;
block_id_type prev_block;
uint64_t nonce = 0;
fc::sha256 work;
uint8_t difficulty = 0;

void create( const block_id_type& prev_block, const string& account_name, uint64_t nonce );
void validate()const;
Expand All @@ -606,11 +606,10 @@ namespace steemit { namespace chain {
struct pow2_operation : public base_operation
{
static_variant<pow2> work;
optional<public_key_type> new_owner_key;
optional<public_key_type> new_owner_key;
chain_properties props;

void validate()const;
const string& get_worker_account()const { return work.get<pow2>().worker_account; }

/** there is no need to verify authority, the proof of work is sufficient */
void get_required_active_authorities( flat_set<string>& a )const {
Expand Down Expand Up @@ -778,7 +777,7 @@ FC_REFLECT( steemit::chain::report_over_production_operation, (reporter)(first_b
FC_REFLECT( steemit::chain::convert_operation, (owner)(requestid)(amount) )
FC_REFLECT( steemit::chain::feed_publish_operation, (publisher)(exchange_rate) )
FC_REFLECT( steemit::chain::pow, (worker)(input)(signature)(work) )
FC_REFLECT( steemit::chain::pow2, (worker_account)(prev_block)(nonce)(work) )
FC_REFLECT( steemit::chain::pow2, (worker_account)(prev_block)(nonce)(difficulty) )
FC_REFLECT( steemit::chain::chain_properties, (account_creation_fee)(maximum_block_size)(sbd_interest_rate) );

FC_REFLECT( steemit::chain::pow_operation, (worker_account)(block_id)(nonce)(work)(props) )
Expand Down
4 changes: 3 additions & 1 deletion libraries/chain/include/steemit/chain/protocol/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ namespace steemit { namespace chain {
impl_owner_authority_history_object_type,
impl_account_recovery_request_object_type,
impl_change_recovery_account_request_object_type,
impl_escrow_object_type
impl_escrow_object_type,
impl_work_nonce_object_type
};

class operation_object;
Expand Down Expand Up @@ -302,6 +303,7 @@ FC_REFLECT_ENUM( steemit::chain::impl_object_type,
(impl_account_recovery_request_object_type)
(impl_change_recovery_account_request_object_type)
(impl_escrow_object_type)
(impl_work_nonce_object_type)
)

FC_REFLECT_TYPENAME( steemit::chain::share_type )
Expand Down
27 changes: 23 additions & 4 deletions libraries/chain/include/steemit/chain/witness_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ namespace steemit { namespace chain {
fc::uint128 virtual_scheduled_time = fc::uint128::max_value();
///@}

digest_type last_work;

/**
* This field represents the Steem blockchain version the witness is running.
*/
Expand Down Expand Up @@ -122,6 +120,14 @@ namespace steemit { namespace chain {
version majority_version;
};

class work_nonce_object : public graphene::db::abstract_object<work_nonce_object>
{
public:
static const uint8_t space_id = implementation_ids;
static const uint8_t type_id = impl_work_nonce_object_type;

uint64_t nonce = 0;
};

struct by_vote_name;
struct by_name;
Expand All @@ -135,7 +141,6 @@ namespace steemit { namespace chain {
witness_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_non_unique< tag<by_work>, member<witness_object, digest_type, &witness_object::last_work> >,
ordered_unique< tag<by_name>, member<witness_object, string, &witness_object::owner> >,
ordered_non_unique< tag<by_pow>, member<witness_object, uint64_t, &witness_object::pow_worker> >,
ordered_unique< tag<by_vote_name>,
Expand Down Expand Up @@ -177,9 +182,18 @@ namespace steemit { namespace chain {
> // indexed_by
> witness_vote_multi_index_type;

struct by_nonce;
typedef multi_index_container<
work_nonce_object,
indexed_by<
ordered_unique< tag<by_id>, member< object, object_id_type, &object::id > >,
ordered_unique< tag<by_nonce>, member< work_nonce_object, uint64_t, &work_nonce_object::nonce > >
>
> work_nonce_multi_index_type;

typedef generic_index< witness_object, witness_multi_index_type> witness_index;
typedef generic_index< witness_vote_object, witness_vote_multi_index_type > witness_vote_index;
typedef generic_index< work_nonce_object, work_nonce_multi_index_type > work_nonce_index;
} }

FC_REFLECT_DERIVED( steemit::chain::witness_object, (graphene::db::object),
Expand All @@ -189,7 +203,6 @@ FC_REFLECT_DERIVED( steemit::chain::witness_object, (graphene::db::object),
(last_aslot)(last_confirmed_block_num)(pow_worker)(signing_key)
(props)
(sbd_exchange_rate)(last_sbd_exchange_update)
(last_work)
(running_version)
(hardfork_version_vote)(hardfork_time_vote)
)
Expand All @@ -201,3 +214,9 @@ FC_REFLECT_DERIVED(
(current_virtual_time)(next_shuffle_block_num)(current_shuffled_witnesses)(median_props)
(majority_version)
)

FC_REFLECT_DERIVED(
steemit::chain::work_nonce_object,
(graphene::db::object),
(nonce)
)
41 changes: 38 additions & 3 deletions libraries/chain/protocol/steem_operations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,39 @@ namespace steemit { namespace chain {
work.get<pow2>().validate();
}

uint16_t clz_sha256( const fc::sha256& x )
{
const char* data = x.data();
size_t size = x.data_size();
size_t lzbits = 0;
static const uint8_t char2lzbits[] = {
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

size_t i = 0;

while( true )
{
uint8_t c = uint8_t( data[i] );
lzbits += char2lzbits[c];
if( c != 0 )
break;
++i;
if( i >= size )
return 0x100;
}

return lzbits;
}

void pow::create( const fc::ecc::private_key& w, const digest_type& i )
{
input = i;
Expand All @@ -205,7 +238,6 @@ namespace steemit { namespace chain {
worker_account = account_name;
prev_block = prev;
nonce = n;
work = fc::sha256();

auto prv_key = fc::sha256::hash( *this );
auto input = fc::sha256::hash( prv_key );
Expand All @@ -214,7 +246,10 @@ namespace steemit { namespace chain {
auto sig_hash = fc::sha256::hash( signature );
public_key_type recover = fc::ecc::public_key( signature, sig_hash );

work = fc::sha256::hash(std::make_pair(input,recover));
fc::sha256 work = fc::sha256::hash(std::make_pair(input,recover));
uint16_t lzbits = clz_sha256( work );
lzbits = (lzbits >= 0x100) ? 0xFF : lzbits;
difficulty = uint8_t( lzbits );
}

void pow::validate()const
Expand All @@ -230,7 +265,7 @@ namespace steemit { namespace chain {
{
FC_ASSERT( is_valid_account_name( worker_account ) );
pow2 tmp; tmp.create( prev_block, worker_account, nonce );
FC_ASSERT( work == tmp.work );
FC_ASSERT( difficulty <= tmp.difficulty );
}

void feed_publish_operation::validate()const
Expand Down
42 changes: 20 additions & 22 deletions libraries/chain/steem_evaluator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <steemit/chain/generic_json_evaluator_registry.hpp>
#include <steemit/chain/steem_evaluator.hpp>
#include <steemit/chain/steem_objects.hpp>
#include <steemit/chain/witness_objects.hpp>

#ifndef IS_LOW_MEM
#include <diff_match_patch.h>
Expand Down Expand Up @@ -1171,17 +1172,14 @@ void pow_apply( database& db, Operation o ) {

FC_ASSERT( db.head_block_time() > STEEMIT_MINING_TIME, "Mining cannot start until ${t}", ("t",STEEMIT_MINING_TIME) );

if( db.is_producing() || db.has_hardfork( STEEMIT_HARDFORK_0_5__59 ) ) {
const auto& witness_by_work = db.get_index_type<witness_index>().indices().get<by_work>();
auto work_itr = witness_by_work.find( o.work.work );
if( work_itr != witness_by_work.end() ) {
FC_ASSERT( !"DUPLICATE WORK DISCOVERED", "${w} ${witness}",("w",o)("wit",*work_itr) );
}
}

if( !db.has_hardfork( STEEMIT_HARDFORK_0_12__179 ) )
FC_ASSERT( o.props.maximum_block_size >= STEEMIT_MIN_BLOCK_SIZE_LIMIT * 2 );

db.create< work_nonce_object >( [&]( work_nonce_object& wno )
{
wno.nonce = o.nonce;
} );

const auto& accounts_by_name = db.get_index_type<account_index>().indices().get<by_name>();
auto itr = accounts_by_name.find(o.get_worker_account());
if(itr == accounts_by_name.end()) {
Expand Down Expand Up @@ -1227,7 +1225,6 @@ void pow_apply( database& db, Operation o ) {
db.modify(*cur_witness, [&]( witness_object& w ){
w.props = o.props;
w.pow_worker = dgp.total_pow;
w.last_work = o.work.work;
});
} else {
db.create<witness_object>( [&]( witness_object& w )
Expand All @@ -1236,7 +1233,6 @@ void pow_apply( database& db, Operation o ) {
w.props = o.props;
w.signing_key = o.work.worker;
w.pow_worker = dgp.total_pow;
w.last_work = o.work.work;
});
}
/// POW reward depends upon whether we are before or after MINER_VOTING kicks in
Expand Down Expand Up @@ -1265,26 +1261,30 @@ void pow2_evaluator::do_apply( const pow2_operation& o ) {

database& db = this->db();

fc::sha256 target = db.get_pow_target();
FC_ASSERT( work.work < target, "work lacks sufficient difficulty" );
uint32_t target = db.get_difficulty_target();
FC_ASSERT( work.prev_block == db.head_block_id() );
FC_ASSERT( work.difficulty == target, "incorrect work difficulty" );

FC_ASSERT( o.props.maximum_block_size >= STEEMIT_MIN_BLOCK_SIZE_LIMIT * 2 );

const auto& witness_by_work = db.get_index_type<witness_index>().indices().get<by_work>();
auto work_itr = witness_by_work.find( work.work );
if( work_itr != witness_by_work.end() ) {
FC_ASSERT( !"DUPLICATE WORK DISCOVERED", "${w} ${witness}",("w",o)("wit",*work_itr) );
}
// We discard duplicate PoW by enforcing uniqueness of nonce through a unique index,
// which we clear on every block (older work cannot be re-used because it will fail block_id check).
// If two workers are unlucky enough to discover work with the same nonce on the same block,
// one of them will be rejected -- too bad, it's an extremely rare unlucky situation.
db.create< work_nonce_object >( [&]( work_nonce_object& wno )
{
wno.nonce = work.nonce;
} );

const auto& dgp = db.get_dynamic_global_properties();

const auto& accounts_by_name = db.get_index_type<account_index>().indices().get<by_name>();
auto itr = accounts_by_name.find(o.get_worker_account());
auto itr = accounts_by_name.find( work.worker_account );
if(itr == accounts_by_name.end()) {
FC_ASSERT( o.new_owner_key.valid() );
db.create< account_object >( [&]( account_object& acc )
{
acc.name = o.get_worker_account();
acc.name = work.worker_account;
acc.owner = authority( 1, *o.new_owner_key, 1);
acc.active = acc.owner;
acc.posting = acc.owner;
Expand All @@ -1311,16 +1311,14 @@ void pow2_evaluator::do_apply( const pow2_operation& o ) {
db.modify(*cur_witness, [&]( witness_object& w ){
w.props = o.props;
w.pow_worker = dgp.total_pow;
w.last_work = work.work;
});
} else {
db.create<witness_object>( [&]( witness_object& w )
{
w.owner = o.get_worker_account();
w.owner = work.worker_account;
w.props = o.props;
w.signing_key = *o.new_owner_key;
w.pow_worker = dgp.total_pow;
w.last_work = work.work;
});
}
/// POW reward depends upon whether we are before or after MINER_VOTING kicks in
Expand Down
Loading

0 comments on commit 581317f

Please sign in to comment.