monero XMR 的发行

2018-03-28  本文已影响0人  路之遥_其漫漫_

理论公式

BR_nom = max( 0.6, floor( (M - A) / 219 ) / 1012 )

  • 注意:M, A 都是uint64 类型。

如果区块大于 60kB时,实际的块奖励将低于BR_nom。这种情况下,块奖励如下计算:
中位块: M100 = max(Median_100, 60kB); // Median_100: 前100个块的中位块大小。
实际块奖励: BR_actual = BR_nom * (1 - (max(CurrentBlickSize, M100)/M100 -1)2)

  • 注意:CurrentBlickSize 不允许大于 Median_100 *2;但是允许CurrentBlickSize不管 Median_100多大,都可以在任何块大于60kB; 即此处总共有两种限制措施。

代码实现

 //获取块的奖励;median_size(in):中位数块大小;current_block_size(in):当前块大小;already_generated_coins(in):已经生成的币;
  // reward(out):当前块的奖励; version(in):块的版本
  bool get_block_reward(size_t median_size, size_t current_block_size, uint64_t already_generated_coins, uint64_t &reward, uint8_t version) {
    //难度目标必须是60的整数倍
    static_assert(DIFFICULTY_TARGET_V2%60==0&&DIFFICULTY_TARGET_V1%60==0,"difficulty targets must be a multiple of 60");
    //依据版本号选择不同的难度目标间隔
    const int target = version < 2 ? DIFFICULTY_TARGET_V1 : DIFFICULTY_TARGET_V2;
    const int target_minutes = target / 60;   //出块的间隔,以分钟标识
    //根据出块的时间间隔,获取偏移系数;1分钟间隔时,系数为向左偏移20位,发币更小;2分钟出块时,系数为向左偏移19位,每个块的发币量增大。
    const int emission_speed_factor = EMISSION_SPEED_FACTOR_PER_MINUTE - (target_minutes-1);

    //获取基础的块奖励; 主曲线
    uint64_t base_reward = (MONEY_SUPPLY - already_generated_coins) >> emission_speed_factor;
    //
    if (base_reward < FINAL_SUBSIDY_PER_MINUTE*target_minutes)
    {
      base_reward = FINAL_SUBSIDY_PER_MINUTE*target_minutes;
    }
    //获取块的另一个基础限制;不管前中位数的块大小为多少,下个块都可以大于这个字节。
    uint64_t full_reward_zone = get_min_block_size(version);

    //make it soft
    if (median_size < full_reward_zone) {
      median_size = full_reward_zone;
    }

    // 当前的块小于中位数的块时,获取全部的块奖励
    if (current_block_size <= median_size) {
      reward = base_reward;
      return true;
    }
    // 当前块大于中位数的两倍时,共识出错。直接报错。
    if(current_block_size > 2 * median_size) {
      MERROR("Block cumulative size is too big: " << current_block_size << ", expected less than " << 2 * median_size);
      return false;
    }

    //最大块的限制;为2**32 - 1
    assert(median_size < std::numeric_limits<uint32_t>::max());
    assert(current_block_size < std::numeric_limits<uint32_t>::max());

    uint64_t product_hi;
    // BUGFIX: 32-bit saturation bug (e.g. ARM7), the result was being
    // treated as 32-bit by default.
    // bug修复;32位的饱和bug,结果默认为32位。
    // 获取当前最大块剩余空间的大小
    uint64_t multiplicand = 2 * median_size - current_block_size;
    multiplicand *= current_block_size;
    uint64_t product_lo = mul128(base_reward, multiplicand, &product_hi);

    uint64_t reward_hi;
    uint64_t reward_lo;
    div128_32(product_hi, product_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo);
    div128_32(reward_hi, reward_lo, static_cast<uint32_t>(median_size), &reward_hi, &reward_lo);
    assert(0 == reward_hi);
    assert(reward_lo < base_reward);    //此时由于惩罚措施,导致实际块奖励 小于理论块奖励

    reward = reward_lo;
    return true;
  }

本文由 Copernicus团队 姚永芯写作,转载无需授权。

上一篇下一篇

猜你喜欢

热点阅读