Develop with pleasure!

福岡でCloudとかBlockchainとか。

ロックタイムの比較の際に使われるMedian time-past(BIP-113)

BIP-68のRelative lock-time等である一定期間ロックされたトランザクションをブロックに入れていいか判断する際の考え方を再定義するのがBIP-113になる。

https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki

動機

現状、現在の時刻もしくはブロック高が指定されたロックタイム以下の場合、そのトランザクションはブロックに含める対象にはならない。ただコンセンサスルールではブロックのタイムスタンプの順序を強制していない。そのためマイナーがブロックのタイムスタンプを偽造し、本来であればまだブロックに含めてはならないトランザクションをブロックに含めることでより多くの手数料を得るという誤ったインセンティブをマイナーに与えてしまう。

このBIPではロックタイムの比較を行うのに、トランザクションが含まれているブロックのタイムスタンプではなく、過去11ブロックのタイムスタンプの中央値を使うことを提案する。既存のコンセンサスルールでは単純にブロックのタイムスタンプを使っているが、このBIPによりマイナーがブロックのタイムスタンプをごまかしてより多くの手数料をかせぐようなことができないようにする。

この提案は、BIP-65 (CHECKLOCKTIMEVERIFY)で必要とされるロックタイムの計算で信頼性の高い動作を保証し、 BIP-68 (sequence numbers) や BIP-112 (CHECKSEQUENCEVERIFY)の挙動に一致することを目指している。

仕様

トランザクションのロックタイムの値は変更されないため、違いが出るのはトランザクションをブロックに入れることができるかどうかを決定する計算になる。信頼できない(ブロックの)タイムスタンプの代わりに、ロックタイムの制約をチェックする際に以下の関数が現在のブロックの時間を計算するのに使われる。

int64_t GetMedianTimePast(const CBlockIndex* pindex)
{
    int64_t pmedian[nMedianTimeSpan];
    int64_t* pbegin = &pmedian[nMedianTimeSpan];
    int64_t* pend = &pmedian[nMedianTimeSpan];
    for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
         *(--pbegin) = pindex->GetBlockTime();
    std::sort(pbegin, pend);
    return pbegin[(pend - pbegin)/2];
}

ロックタイムの制約は、IsFinalTx()メソッドによってチェックされる。このメソッドは引数の1つにブロックタイムを取るが、このBIPではIsFinalTx()が呼ばれる際に渡すブロックタイムGetMedianTimePast(pindexPrev)の戻り値を使用するよう提案している。

この提案の参照実装は↓

github.com

まとめ

  • ブロックのタイムスタンプの順序は特に強制されるものではないので、マイナーによって実際の時刻とは異なる時刻が設定されている可能性もある。
  • ロックタイムの比較には今までトランザクションが含まれているブロックのタイムスタンプを使用していたが、このBIPの提案では過去11ブロックのタイムスタンプの中央値を使用する。