src/cryptonote_core/master_node_list.cpp
// NOTE: Verify queued master node coinbase or POS block producer rewards
Verify queued master node coinbase or POS block producer rewards
Verify queued master node coinbase or POS block producer rewards
static bool verify_coinbase_tx_output(cryptonote::transaction const &miner_tx,
                                        uint64_t height,
                                        size_t output_index,
                                        cryptonote::account_public_address const &receiver,
                                        uint64_t reward)
  {
    if (output_index >= miner_tx.vout.size())
    {
      MGINFO_RED("Output Index: " << output_index << ", indexes out of bounds in vout array with size: " << miner_tx.vout.size());
      return false;
    }
    cryptonote::tx_out const &output = miner_tx.vout[output_index];
    if (!within_one(output.amount, reward))
    {
      MGINFO_RED("Master node reward amount incorrect. Should be " << cryptonote::print_money(reward) << ", is: " << cryptonote::print_money(output.amount));
      return false;
    }
    if (!std::holds_alternative<cryptonote::txout_to_key>(output.target))
    {
      MGINFO_RED("Master node output target type should be txout_to_key");
      return false;
    }
    crypto::key_derivation derivation{};
    crypto::public_key out_eph_public_key{};
    cryptonote::keypair gov_key = cryptonote::get_deterministic_keypair_from_height(height);
    bool r = crypto::generate_key_derivation(receiver.m_view_public_key, gov_key.sec, derivation);
    CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << receiver.m_view_public_key << ", " << gov_key.sec << ")");
    r = crypto::derive_public_key(derivation, output_index, receiver.m_spend_public_key, out_eph_public_key);
    CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< receiver.m_spend_public_key << ")");
    if (var::get<cryptonote::txout_to_key>(output.target).key != out_eph_public_key)
    {
      MGINFO_RED("Invalid master node reward at output: " << output_index << ", output key, specifies wrong key");
      return false;
    }
    return true;
  }
static bool verify_coinbase_tx_output ( cryptonote :: transaction const & miner_tx , uint64_t height , size_t output_index , cryptonote :: account_public_address const & receiver , uint64_t reward ) { if ( output_index >= miner_tx . vout . size ( ) ) { MGINFO_RED ( " " << output_index << " " << miner_tx . vout . size ( ) ) ; return false ; } cryptonote :: tx_out const & output = miner_tx . vout [ output_index ] ; if ( ! within_one ( output . amount , reward ) ) { MGINFO_RED ( " " << cryptonote :: print_money ( reward ) << " " << cryptonote :: print_money ( output . amount ) ) ; return false ; } if ( ! std :: holds_alternative < cryptonote :: txout_to_key > ( output . target ) ) { MGINFO_RED ( " " ) ; return false ; } crypto :: key_derivation derivation { } ; crypto :: public_key out_eph_public_key { } ; cryptonote :: keypair gov_key = cryptonote :: get_deterministic_keypair_from_height ( height ) ; bool r = crypto :: generate_key_derivation ( receiver . m_view_public_key , gov_key . sec , derivation ) ; CHECK_AND_ASSERT_MES ( r , false , " " << receiver . m_view_public_key << " " << gov_key . sec << " " ) ; r = crypto :: derive_public_key ( derivation , output_index , receiver . m_spend_public_key , out_eph_public_key ) ; CHECK_AND_ASSERT_MES ( r , false , " " << derivation << " " << output_index << " " << receiver . m_spend_public_key << " " ) ; if ( var :: get < cryptonote :: txout_to_key > ( output . target ) . key != out_eph_public_key ) { MGINFO_RED ( " " << output_index << " " ) ; return false ; } return true ; }
NOTE: Verify queued master node coinbase or POS block producer rewards
NOTE : Verify queued master node coinbase or POS block producer rewards
// Because FP math is involved in reward calculations (and compounded by CPUs, compilers, // expression contraction, and RandomX fiddling with the rounding modes) we can end up with a // 1 ULP difference in the reward calculations. // TODO(beldex): eliminate all FP math from reward calculations // NOTE: Beldex uses the governance key in the one-time ephemeral key // derivation for both POS Block Producer/Queued Master Node Winner rewards