block_header_state.cpp 10.5 KB
Newer Older
D
Daniel Larimer 已提交
1 2
#include <eosio/chain/block_header_state.hpp>
#include <eosio/chain/exceptions.hpp>
3
#include <limits>
D
Daniel Larimer 已提交
4 5 6

namespace eosio { namespace chain {

7
   /*
D
Daniel Larimer 已提交
8
  uint32_t block_header_state::calc_dpos_last_irreversible()const {
9
    if( producer_to_last_produced.size() == 0 )
D
Daniel Larimer 已提交
10 11 12 13
       return 0;

    vector<uint32_t> irb;
    irb.reserve( producer_to_last_produced.size() );
14
    for( const auto& item : producer_to_last_produced )
D
Daniel Larimer 已提交
15 16 17 18 19 20 21
       irb.push_back(item.second);

    size_t offset = EOS_PERCENT(irb.size(), config::percent_100- config::irreversible_threshold_percent);
    std::nth_element( irb.begin(), irb.begin() + offset, irb.end() );

    return irb[offset];
  }
22
  */
D
Daniel Larimer 已提交
23

24 25 26
   bool block_header_state::is_active_producer( account_name n )const {
      return producer_to_last_produced.find(n) != producer_to_last_produced.end();
   }
D
Daniel Larimer 已提交
27

28
   /*
29 30 31 32 33 34
   block_timestamp_type block_header_state::get_slot_time( uint32_t slot_num )const {
      auto t = header.timestamp;
      FC_ASSERT( std::numeric_limits<decltype(t.slot)>::max() - t.slot >= slot_num, "block timestamp overflow" );
      t.slot += slot_num;
      return t;
   }
D
Daniel Larimer 已提交
35

36 37 38 39 40 41 42 43
   uint32_t block_header_state::get_slot_at_time( block_timestamp_type t )const {
      auto first_slot_time = get_slot_time(1);
      if( t < first_slot_time )
         return 0;
      return (t.slot - first_slot_time.slot + 1);
   }

   producer_key block_header_state::get_scheduled_producer( uint32_t slot_num )const {
A
arhag 已提交
44 45
      return get_scheduled_producer( get_slot_time(slot_num) );
   }
46
   */
A
arhag 已提交
47 48 49

   producer_key block_header_state::get_scheduled_producer( block_timestamp_type t )const {
      auto index = t.slot % (active_schedule.producers.size() * config::producer_repetitions);
50 51 52 53
      index /= config::producer_repetitions;
      return active_schedule.producers[index];
   }

54
   /*
55 56 57 58
   uint32_t block_header_state::producer_participation_rate()const
   {
      return static_cast<uint32_t>(config::percent_100); // Ignore participation rate for now until we construct a better metric.
   }
59
   */
D
Daniel Larimer 已提交
60 61 62 63 64 65 66 67


  /**
   *  Generate a template block header state for a given block time, it will not
   *  contain a transaction mroot, action mroot, or new_producers as those components
   *  are derived from chain state.
   */
  block_header_state block_header_state::generate_next( block_timestamp_type when )const {
68
    block_header_state result;
D
Daniel Larimer 已提交
69

70 71 72 73 74 75 76 77
    if( when != block_timestamp_type() ) {
       FC_ASSERT( when > header.timestamp, "next block must be in the future" );
    } else {
       (when = header.timestamp).slot++;
    }
    result.header.timestamp                      = when;
    result.header.previous                       = id;
    result.header.schedule_version               = active_schedule.version;
D
Daniel Larimer 已提交
78

A
arhag 已提交
79
    auto prokey                                  = get_scheduled_producer(when);
D
Daniel Larimer 已提交
80 81
    result.block_signing_key                     = prokey.block_signing_key;
    result.header.producer                       = prokey.producer_name;
82

83
    result.pending_schedule_lib_num              = pending_schedule_lib_num;
D
Daniel Larimer 已提交
84 85 86
    result.pending_schedule_hash                 = pending_schedule_hash;
    result.block_num                             = block_num + 1;
    result.producer_to_last_produced             = producer_to_last_produced;
D
Daniel Larimer 已提交
87
    result.producer_to_last_produced[prokey.producer_name] = result.block_num;
D
Daniel Larimer 已提交
88 89
    result.blockroot_merkle = blockroot_merkle;
    result.blockroot_merkle.append( id );
90 91

    auto block_mroot = result.blockroot_merkle.get_root();
D
Daniel Larimer 已提交
92

93 94 95 96
    result.active_schedule                   = active_schedule;
    result.pending_schedule                  = pending_schedule;
    result.dpos_irreversible_blocknum        = dpos_irreversible_blocknum;
    result.bft_irreversible_blocknum         = bft_irreversible_blocknum;
97

98
    if( result.pending_schedule.producers.size() &&
99
        result.dpos_irreversible_blocknum >= pending_schedule_lib_num ) {
100
      result.active_schedule = move( result.pending_schedule );
D
Daniel Larimer 已提交
101 102 103 104 105 106 107

      flat_map<account_name,uint32_t> new_producer_to_last_produced;
      for( const auto& pro : result.active_schedule.producers ) {
        auto existing = producer_to_last_produced.find( pro.producer_name );
        if( existing != producer_to_last_produced.end() ) {
          new_producer_to_last_produced[pro.producer_name] = existing->second;
        } else {
108
          new_producer_to_last_produced[pro.producer_name] = result.dpos_irreversible_blocknum;
D
Daniel Larimer 已提交
109 110 111 112
        }
      }
      result.producer_to_last_produced = move( new_producer_to_last_produced );
      result.producer_to_last_produced[prokey.producer_name] = result.block_num;
113
    }
D
Daniel Larimer 已提交
114

115
    /// grow the confirmed count
B
Bart Wyatt 已提交
116 117 118 119 120
    static_assert(std::numeric_limits<uint8_t>::max() >= (config::max_producers * 2 / 3) + 1, "8bit confirmations may not be able to hold all of the needed confirmations");
    auto num_active_producers = result.active_schedule.producers.size();
    uint32_t required_confs = (uint32_t)(num_active_producers * 2 / 3) + 1;

    if( confirm_count.size() < config::maximum_tracked_dpos_confirmations ) {
121 122 123
       result.confirm_count.reserve( confirm_count.size() + 1 );
       result.confirm_count  = confirm_count;
       result.confirm_count.resize( confirm_count.size() + 1 );
B
Bart Wyatt 已提交
124
       result.confirm_count.back() = (uint8_t)required_confs;
125 126 127
    } else {
       result.confirm_count.resize( confirm_count.size() );
       memcpy( &result.confirm_count[0], &confirm_count[1], confirm_count.size() - 1 );
B
Bart Wyatt 已提交
128
       result.confirm_count.back() = (uint8_t)required_confs;
129 130
    }

D
Daniel Larimer 已提交
131 132 133 134
    return result;
  } /// generate_next


D
Daniel Larimer 已提交
135 136
  void block_header_state::set_new_producers( producer_schedule_type pending ) {
      FC_ASSERT( pending.version == active_schedule.version + 1, "wrong producer schedule version specified" );
137
      FC_ASSERT( pending_schedule.producers.size() == 0,
D
Daniel Larimer 已提交
138 139 140 141 142 143 144
                 "cannot set new pending producers until last pending is confirmed" );
      header.new_producers     = move(pending);
      pending_schedule_hash    = digest_type::hash( *header.new_producers );
      pending_schedule         = *header.new_producers;
      pending_schedule_lib_num = block_num;
  }

D
Daniel Larimer 已提交
145 146 147 148 149

  /**
   *  Transitions the current header state into the next header state given the supplied signed block header.
   *
   *  Given a signed block header, generate the expected template based upon the header time,
150
   *  then validate that the provided header matches the template.
D
Daniel Larimer 已提交
151
   *
152
   *  If the header specifies new_producers then apply them accordingly.
D
Daniel Larimer 已提交
153 154
   */
  block_header_state block_header_state::next( const signed_block_header& h )const {
D
Daniel Larimer 已提交
155
    FC_ASSERT( h.timestamp != block_timestamp_type(), "", ("h",h) );
D
Daniel Larimer 已提交
156 157

    FC_ASSERT( h.timestamp > header.timestamp, "block must be later in time" );
A
arhag 已提交
158 159 160 161
    FC_ASSERT( h.previous == id, "block must link to current state" );
    auto result = generate_next( h.timestamp );
    FC_ASSERT( result.header.producer == h.producer, "wrong producer specified" );
    FC_ASSERT( result.header.schedule_version == h.schedule_version, "schedule_version in signed block is corrupted" );
162

163 164 165 166 167 168
    //idump((h.producer)(h.block_num()-h.confirmed)(h.block_num()));
    auto itr = producer_to_last_produced.find(h.producer);
    if( itr != producer_to_last_produced.end() ) {
       FC_ASSERT( itr->second <= result.block_num - h.confirmed, "producer double-confirming known range" );
    }

169
    // FC_ASSERT( result.header.block_mroot == h.block_mroot, "mistmatch block merkle root" );
D
Daniel Larimer 已提交
170

171
     /// below this point is state changes that cannot be validated with headers alone, but never-the-less,
D
Daniel Larimer 已提交
172
     /// must result in header state changes
D
Daniel Larimer 已提交
173
    if( h.new_producers ) {
D
Daniel Larimer 已提交
174
       result.set_new_producers( *h.new_producers );
175
    }
D
Daniel Larimer 已提交
176

177 178 179 180
    result.set_confirmed( h.confirmed );

   // idump( (result.confirm_count.size()) );

D
Daniel Larimer 已提交
181 182 183
    result.header.action_mroot       = h.action_mroot;
    result.header.transaction_mroot  = h.transaction_mroot;
    result.header.producer_signature = h.producer_signature;
184
    //idump((result.header));
A
arhag 已提交
185
    result.id                        = result.header.id();
D
Daniel Larimer 已提交
186

187 188 189
    FC_ASSERT( result.block_signing_key == result.signee(), "block not signed by expected key",
               ("result.block_signing_key", result.block_signing_key)("signee", result.signee() ) );

D
Daniel Larimer 已提交
190 191 192
    return result;
  } /// next

193 194 195 196 197 198 199 200 201 202
  void block_header_state::set_confirmed( uint16_t num_prev_blocks ) {
     /*
     idump((num_prev_blocks)(confirm_count.size()));

     for( uint32_t i = 0; i < confirm_count.size(); ++i ) {
        std::cerr << "confirm_count["<<i<<"] = " << int(confirm_count[i]) << "\n";
     }
     */
     header.confirmed = num_prev_blocks;

203
     int32_t i = (int32_t)(confirm_count.size() - 1);
204 205
     uint32_t blocks_to_confirm = num_prev_blocks + 1; /// confirm the head block too
     while( i >= 0 && blocks_to_confirm ) {
206
        --confirm_count[i];
207
        //idump((confirm_count[i]));
208
        if( confirm_count[i] == 0 )
209
        {
210 211 212 213 214 215 216 217 218 219
           uint32_t block_num_for_i = block_num - (uint32_t)(confirm_count.size() - 1 - i);
           dpos_irreversible_blocknum = block_num_for_i;
           //idump((dpos2_lib)(block_num)(dpos_irreversible_blocknum));

           if (i == confirm_count.size() - 1) {
              confirm_count.resize(0);
           } else {
              memmove( &confirm_count[0], &confirm_count[i + 1], confirm_count.size() - i  - 1);
              confirm_count.resize( confirm_count.size() - i - 1 );
           }
220 221 222 223

           return;
        }
        --i;
224
        --blocks_to_confirm;
225 226 227
     }
  }

228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
  digest_type   block_header_state::sig_digest()const {
     auto header_bmroot = digest_type::hash( std::make_pair( header.digest(), blockroot_merkle.get_root() ) );
     return digest_type::hash( std::make_pair(header_bmroot, pending_schedule_hash) );
  }

  void block_header_state::sign( const std::function<signature_type(const digest_type&)>& signer ) {
     auto d = sig_digest();
     header.producer_signature = signer( d );
     FC_ASSERT( block_signing_key == fc::crypto::public_key( header.producer_signature, d ) );
  }

  public_key_type block_header_state::signee()const {
    return fc::crypto::public_key( header.producer_signature, sig_digest(), true );
  }

243 244 245 246 247 248 249 250 251 252 253
  void block_header_state::add_confirmation( const header_confirmation& conf ) {
     for( const auto& c : confirmations )
        FC_ASSERT( c.producer == conf.producer, "block already confirmed by this producer" );

     auto key = active_schedule.get_producer_key( conf.producer );
     FC_ASSERT( key != public_key_type(), "producer not in current schedule" );
     auto signer = fc::crypto::public_key( conf.producer_signature, sig_digest(), true );
     FC_ASSERT( signer == key, "confirmation not signed by expected key" );

     confirmations.emplace_back( conf );
  }
254 255


D
Daniel Larimer 已提交
256
} } /// namespace eosio::chain