Skip to content

total_missed does not correctly increment in a corner case #2469

@theoreticalbts

Description

@theoreticalbts

This code skips updating total_missed in case witness_missed.owner == b.owner. To fix the bug, transform from:

if( witness_missed.owner != b.witness )
{
   modify(witness_missed, [&](witness_object& w)
   {
      w.total_missed++;
      if( has_hf_14 ) { if( last_old_enough ) { shutdown_witness } }
   }
}

to:

modify(witness_missed, [&](witness_object& w)
{
   w.total_missed++;
   if( witness_missed.owner != b.witness )
   {
      if( has_hf_14 ) { if( last_old_enough ) { shutdown_witness } }
   }
}

We can collapse these three checks to a single if statement with a conjunction (AND) of these three conditions, reordered any we like, and I like this ordering:

modify(witness_missed, [&](witness_object& w)
{
   w.total_missed++;
   if( last_old_enough
     && witness_missed.owner != b.witness
     && has_hf_14 )
   { shutdown_witness }
}

The idea behind this reordering is that, by deferring the hardfork check (involving an object lookup) until the last, we might well avoid it entirely if one of the other checks fails (the other two checks are both only integer arithmetic and reading fields from objects already available).

I'd really like to get rid of the witness_missed.owner != b.owner check, but I realized we cannot remove it, otherwise the network might be bricked if all of the witnesses miss enough blocks to get shut down, then start producing again.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions