anchor.diff:                             struct = Tree,                 stats = Stats,
                              dest_recon_pid = DestReconPid,
                              misc = [{signature_size, {SigSizeI, SigSizeL}},
  -                                   {p0e, P0E}]}) ->
  +                                   {p1e, P1ETotal}]}) ->
       % current node can make a mistake or any of its BranchFactor children
       % => current node's probability of 0 errors = P0E(child)^(BranchFactor+1)
  -    % TODO: since P0E is near 1, its floating point representation is sub-optimal!
  -    NextP0E = math:pow(P0E, 1 / (BranchFactor + 1)),
  +    % however, we cannot use P0E=(1-P1E) since it is near 1 and its floating
  +    % point representation is sub-optimal!
  +    % => use Taylor expansion of P1E_next = 1 - (1-P1E)^(1/BranchFactor)
  +    BF = BranchFactor + 1,
  +    P1E = P1ETotal / BF +
  +              (BF - 1) * P1ETotal * P1ETotal / (2 * BF * BF), % +O[p^3]
       case process_tree_cmp_result(FlagsBin, Tree, SigSizeI, SigSizeL, MerkleSync, Stats) of
           {[] = RTree, [] = MerkleSyncNew, NStats, _MyMaxLeafCount, _MyMaxItemsCount} ->
               NStage = reconciliation,
  
positive.code:             NStage = reconciliation,
              OtherMaxItemsCount = OtherMaxLeafCount * BucketSize - MaxLeafItemsCountDiff,
              % note: we need to use the same P1E for this level's signature
              %       comparison as a children's tree has in total! 
              P1E = 1 - NextP0E,
              NextSigSizeI =
                  min_max(
                    util:ceil(
                      util:log2(erlang:min(1, MyMaxItemsCount + OtherMaxItemsCount)
                                    / P1E)), 1, 160),
              NextSigSizeL =
                  min_max(
                    util:ceil(
                      util:log2(
                        % note: see TODO above for P0E precision!
                        1 / (1 - math:pow(1 - P1E / (2 * BucketSize), 1 / erlang:max(MyMaxLeafCount, OtherMaxLeafCount)))
                      )), 1, 160),
              ?DBG_ASSERT(NextSigSizeL >= NextSigSizeI),
  %%             log:pal("P1E: ~p, \tP0E: ~p, \tSigSizeI: ~B, \tSigSizeL: ~B~n"
  %%                     "Buckets: ~B, \tMyMI: ~B, \tOtMI: ~B, \tMyML: ~B, \tOtML: ~B",
  %%                     [P1E, P0E, NextSigSizeL, NextSigSizeI,
  %%                      BucketSize, MyMaxItemsCount, OtherMaxItemsCount, MyMaxLeafCount, OtherMaxLeafCount]),
              Req = merkle_compress_hashlist(RTree, <<>>, NextSigSizeI, NextSigSizeL),
              send(DestReconPid, {?check_nodes, Req, NextSigSizeI, NextSigSizeL - NextSigSizeI})
      end,
      NewState = State#rr_recon_state{stats = NStats, struct = RTree,
                                      misc = [{signature_size, {NextSigSizeI, NextSigSizeL}},
                                              {p0e, NextP0E}],
                                      merkle_sync = MerkleSyncNew, stage = NStage},
      if RTree =:= [] andalso MerkleSyncNew =:= [] ->
             %send(DestReconPid, {shutdown, sync_finished_remote}),
  
negative.code:             send(DestReconPid, {?check_nodes, comm:this(), Req, SigSize, 0}),
              State#rr_recon_state{stats = Stats1,
                                   misc = [{signature_size, {SigSize, SigSize}},
                                           {p1e, get_p1e()}],
                                   kv_list = []};
          false ->
              MerkleI = merkle_tree:get_interval(MySyncStruct),
  