コンテンツにスキップ

ブロック報酬を照会する⚓︎

初級

NEM の各 ブロック は、1 つの ハーベスターアカウント によって生成されます。 ブロックのハーベスティングに対する報酬はすべて、そのブロックに含まれる トランザクション の手数料から生じ、これらの手数料はブロックを生成したハーベスターに全額支払われます。

このチュートリアルでは、任意のブロックを照会し、そのハーベスターを特定して、報酬を構成するトランザクション手数料を合計する方法を説明します。

前提条件⚓︎

始める前に、開発環境をセットアップ してください。

このチュートリアルではネットワークからデータを読み取るだけです。アカウントXEM の残高は必要ありません。

完全なコード⚓︎

import json
import os
import urllib.request

from symbolchain.CryptoTypes import PublicKey
from symbolchain.facade.NemFacade import NemFacade

NODE_URL = os.getenv('NODE_URL', 'http://libertalia.nemtest.net:7890')
print(f'Using node {NODE_URL}')

BLOCK_HEIGHT = os.getenv('BLOCK_HEIGHT', '661258')

facade = NemFacade('testnet')

try:
    # Fetch the block at the given height
    block_url = f'{NODE_URL}/block/at/public'
    request = urllib.request.Request(
        block_url,
        data=json.dumps({'height': int(BLOCK_HEIGHT)}).encode(),
        headers={'Content-Type': 'application/json'})
    with urllib.request.urlopen(request) as response:
        block = json.loads(response.read())
    transactions = block['transactions']
    print(f'Block height: {BLOCK_HEIGHT}')
    print(f'Transactions: {len(transactions)}')

    # Identify the harvester
    harvester = facade.network.public_key_to_address(
        PublicKey(block['signer']))
    print(f'Harvester: {harvester}')

    # Sum the transaction fees
    total_reward = 0
    print('\nTransaction fees:')
    for transaction in transactions:
        fee = int(transaction['fee'])
        total_reward += fee
        print(f'  Fee: {fee / 1e6:,.6f} XEM')

    # Total reward
    print(f'\nTotal block reward: {total_reward / 1e6:,.6f} XEM')

except Exception as error:
    print(error)

Download source

import { PublicKey } from 'symbol-sdk';
import { NemFacade } from 'symbol-sdk/nem';

const fmt = v => (Number(v) / 1e6).toLocaleString(
    'en-US', { minimumFractionDigits: 6 });

const NODE_URL = process.env.NODE_URL ||
    'http://libertalia.nemtest.net:7890';
console.log(`Using node ${NODE_URL}`);

const BLOCK_HEIGHT = process.env.BLOCK_HEIGHT || '661258';

const facade = new NemFacade('testnet');

try {
    // Fetch the block at the given height
    const blockUrl = `${NODE_URL}/block/at/public`;
    const response = await fetch(blockUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ height: parseInt(BLOCK_HEIGHT, 10) })
    });
    if (!response.ok)
        throw new Error(`HTTP error! status: ${response.status}`);
    const block = await response.json();
    const transactions = block.transactions;
    console.log(`Block height: ${BLOCK_HEIGHT}`);
    console.log(`Transactions: ${transactions.length}`);

    // Identify the harvester
    const harvester = facade.network.publicKeyToAddress(
        new PublicKey(block.signer));
    console.log(`Harvester: ${harvester}`);

    // Sum the transaction fees
    let totalReward = 0n;
    console.log('\nTransaction fees:');
    for (const transaction of transactions) {
        const fee = BigInt(transaction.fee);
        totalReward += fee;
        console.log(`  Fee: ${fmt(fee)} XEM`);
    }

    // Total reward
    console.log(`\nTotal block reward: ${fmt(totalReward)} XEM`);

} catch (error) {
    console.log(error);
}

Download source

スニペットでは、NODE_URL 環境変数を使って NEM API ノードを指定します。 値が指定されていない場合は、デフォルトの テストネット ノードを使用します。

BLOCK_HEIGHT 環境変数で照会するブロックを選択します。 設定されていない場合は、テストネットでハーベスティングされたブロック 661258 をデフォルト値として使用します。

コードの説明⚓︎

コードはブロック高を指定してブロックを取得し、ブロックの署名者公開鍵からハーベスターのアドレスを導出します。 次に、ブロック内のすべてのトランザクションの手数料を合計して、合計報酬を求めます。

ブロック情報を取得する⚓︎

    # Fetch the block at the given height
    block_url = f'{NODE_URL}/block/at/public'
    request = urllib.request.Request(
        block_url,
        data=json.dumps({'height': int(BLOCK_HEIGHT)}).encode(),
        headers={'Content-Type': 'application/json'})
    with urllib.request.urlopen(request) as response:
        block = json.loads(response.read())
    transactions = block['transactions']
    print(f'Block height: {BLOCK_HEIGHT}')
    print(f'Transactions: {len(transactions)}')
    // Fetch the block at the given height
    const blockUrl = `${NODE_URL}/block/at/public`;
    const response = await fetch(blockUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ height: parseInt(BLOCK_HEIGHT, 10) })
    });
    if (!response.ok)
        throw new Error(`HTTP error! status: ${response.status}`);
    const block = await response.json();
    const transactions = block.transactions;
    console.log(`Block height: ${BLOCK_HEIGHT}`);
    console.log(`Transactions: ${transactions.length}`);

/block/at/public POST エンドポイントは、指定した高さのブロックに関する情報を返します。 これには、ブロックに含まれるトランザクションの一覧も含まれます。

ハーベスターを特定する⚓︎

    # Identify the harvester
    harvester = facade.network.public_key_to_address(
        PublicKey(block['signer']))
    print(f'Harvester: {harvester}')
    // Identify the harvester
    const harvester = facade.network.publicKeyToAddress(
        new PublicKey(block.signer));
    console.log(`Harvester: ${harvester}`);

signer フィールドには、ブロックをハーベスティングしたアカウントの 公開鍵 が格納されています。 メソッドは、この公開鍵を対応するテストネットの アドレス に変換します。

署名者が常に報酬を得るアカウントとは限りません

ローカルハーベスティング では、signerハーベスターアカウント であり、報酬を受け取ります。

リモートハーベスティング または 委任ハーベスティング では、signerリモートアカウント ですが、報酬は メインアカウント に支払われます。

トランザクション手数料を合計する⚓︎

    # Sum the transaction fees
    total_reward = 0
    print('\nTransaction fees:')
    for transaction in transactions:
        fee = int(transaction['fee'])
        total_reward += fee
        print(f'  Fee: {fee / 1e6:,.6f} XEM')
    // Sum the transaction fees
    let totalReward = 0n;
    console.log('\nTransaction fees:');
    for (const transaction of transactions) {
        const fee = BigInt(transaction.fee);
        totalReward += fee;
        console.log(`  Fee: ${fmt(fee)} XEM`);
    }

ブロック内の各トランザクションには、原子単位で表された fee フィールドがあります。 XEM の 可分性 は 6 なので、350000 原子単位は 0.350000 XEM を表します。

すべてのトランザクションの手数料を加算すると、ブロックの合計報酬になります。

合計報酬を計算する⚓︎

    # Total reward
    print(f'\nTotal block reward: {total_reward / 1e6:,.6f} XEM')
    // Total reward
    console.log(`\nTotal block reward: ${fmt(totalReward)} XEM`);

ブロックの合計報酬は、すべてのトランザクション手数料の合計であり、ハーベスターに全額支払われます。 空のブロックには手数料がないため、報酬もありません。

別の方法: アカウントごとに報酬を照会する

このチュートリアルでは、特定のブロックに含まれるトランザクション手数料を合計して、そのブロックの報酬を計算します。

特定のアカウントが得た報酬に関心がある場合は、/account/harvests GET エンドポイントを使用してください。 ハーベスティングされたブロックごとに 1 件のエントリを返し、そのブロックで得た報酬を示す totalFee フィールドも含みます。

このエンドポイントは、報酬を得るアカウントである ハーベスターアカウント のアドレスを受け取ります。 リモートハーベスティング または 委任ハーベスティング の場合、署名したリモートアカウントではなくメインアカウントです。

リモートアカウントのアドレスを指定しても、メインアカウントに代わって署名したブロックが返されます。

出力⚓︎

以下の出力は、ブロック 661,258 の報酬を照会した場合の実行例です。

Using node http://libertalia.nemtest.net:7890
Block height: 661258
Transactions: 2
Harvester: TCJLCZSOQ6RGWHTPSV2DW467WZSHK4NBSITND4OF

Transaction fees:
  Fee: 0.350000 XEM
  Fee: 0.050000 XEM

Total block reward: 0.400000 XEM

出力の要点は次のとおりです。

  • ハーベスター(4 行目): ブロックの signer 公開鍵から導出されたアドレス。
  • トランザクション手数料(7~8 行目): ブロックに含まれる各トランザクションが支払った手数料。
  • ブロックの合計報酬(10 行目): すべてのトランザクション手数料の合計で、ハーベスターに全額支払われる金額。

まとめ⚓︎

このチュートリアルでは、次の方法を説明しました。

手順 関連ドキュメント
ブロック情報を取得する /block/at/public POST