Accessing Time From Cadence
Block Height と Block Timestamp はどちらも、Cadenceコード内からアクセス可能です。
つまり、将来のある時点までリソースをロックする必要がある場合や、ある期間の間の値を計算する必要がある場合、あるいは、時間の経過に対処する必要がある場合など、Flow上のスマートコントラクトで日付や期間を計算するために使用できるということです。
ブロックチェーン上で時間を測定する事を利用した一般的戦略が2つあります。
-
Block Timestampを使用して、攻撃が起きなくするために、直近のnブロックの平均生成時間がブロック目標生成時間に十分に近いことを、任意で確認します。
-
Block Heightを直接使用します。ブロック高さは直感的に扱うことが出来ます(100ブロック、1000ブロックのように)し、この記事で説明されている方法により、予測タイムスタンプと関連付け、それによってオフチェーンの時間に関連づけます。
Time On The Flow Blockchain
Flowのブロック生成目標時間は1秒ですが、プロトコルがまだ開発初期段階であり、それを達成する為にさらなる最適化を必要としています。2021年2月現在、メインネット上のブロック確定(block finalization)速度は0.5ブロック/秒以上であり、標準偏差は±0.1ブロック/秒です。したがって、新しいブロックは平均して2秒ごとに確定します。 ブロック確定速度は当然変動するため、ブロックの高さは時間と緩やかな相関関係しか持たないことに注意してください。
上述の自然なばらつきに加え、この関係をさらに歪める可能性があるブロック生成攻撃が理論上いくつか存在します。しかし、Flowではビザンチンノードが存在しないため、これらの攻撃が起きる可能性は低いでしょう。タイムスタンプは、前のブロックのタイムスタンプよりも前になることはできませんし、またあまりにも未来(現在は10秒に設定)になることも出来ません。
(補足: というチェック処理があるというだけで、タイムスタンプ自体はごく普通のUNIXタイムスタンプです。ブロック高さは揺らぎがあるので、それを敬遠したい場合はタイムスタンプを使用してください)
- これらの条件を満たさないブロック生成の提案は、Flowのコンセンサスアルゴリズムによって拒否されます。しかし、こうした攻撃の可能性があるので、ブロック高さやブロックのタイムスタンプを使用した、オンチェーンのプロトコルレベルのデータからオフチェーンの時間を決定することに、これら追加の信頼の限界があることをここに述べています。
ブロックタイムスタンプは、オフチェーンの時間経過の中でブロックを識別する唯一の方法ではありません。各ブロックは「height」によって連続的に番号付けされ、ブロック70000はブロック70001、70002、70003と続きます。Flowのコンセンサスアルゴリズムでは、連続していない高さのブロックは拒否されます。理論的には、ブロックのタイムスタンプは、Flowの創生ブロックのタイムスタンプとほぼ同等で、さらにブロックの高さに目標ブロック生成速度を掛けたものになるはずです。しかし、これまで見てきたように、目標とチェーン上のブロック生成速度は、時間とともに変動する可能性があります。そのため、このような計算はより難しくなります。
Using The Timestamp
Flowコンセンサスでは、前のブロックから10秒以上先のタイムスタンプを持つ新しいブロックは拒否されるため、10秒未満の精度が必要でない限り、ブロック目標生成速度に変更がない限り、数日間のイベントにはブロックタイムスタンプを使用しても問題ないでしょう。あるいは、より直感的に言えば、タイムスタンプは正しい時間である可能性が高く、正しい分である可能性も高く、正しい秒から10秒以内である可能性も高いでしょう。 これらのスケールのうち、どの程度まで許容できるかは、表現したいイベントがどの程度の期間にわたるかによります。 数日間にわたるオークションであれば、10秒以上の精度があれば十分でしょう。(補足: ブロックタイムスタンプ自体はごく普通のUNIXタイムスタンプです)
// To get the timestamp of the block that the code is being executed in
getCurrentBlock().timestamp
// To get the timestamp of a known previous block, if available
getBlock(at: 70001)?.timestamp
Using The Block Height
理論上、ブロック番号はタイムスタンプよりも信頼性が高い。なぜなら、フォークの各ブロックでブロック高がインクリメントされるからだ。しかし実際には、ブロック番号をオフチェーンの時間値に関連付ける必要があり、そのためには平均的なブロック生成時間が維持されると仮定する必要がある。これは攻撃以外の要因によって変動する可能性がある。ブロック生成時間の目標はFlowの開発が継続するにつれて変化するため、ブロック生成番号を暦時間に関連付けるために行うあらゆる計算に影響を与えることになる。
// To get the block number of the block that the code is being executed in
getCurrentBlock().height
// To get the block number of a known previous block, if available
getBlock(at: 70001)?.height
Recommendations
もし、スマートコントラクトのコードが上記の制限を許容できるのであれば、ブロックタイムスタンプを使用してください。そうでない場合は、より特殊なソリューション(time oracles, etc.)を検討する必要があるかもしれません。
いずれの方法を使用する場合でも、オンチェーン、オフチェーンに関わらず、ブロック生成速度を想定したコードを、後で更新できないやり方でハードコードしないように注意してください。
オンチェーンオークションや類似のメカニズムには、常に延長メカニズムが備わっているべきです。もし誰かが最後の瞬間に入札した場合(これはブロック生成攻撃により容易に行えます)、オークションの終了時間は(必要に応じて)最後の入札からN分間延長されるべきです(10分、30分、1時間)。Nが大きくなるにつれ、この安全性は高まります。N=5は十分すぎるほどです(Flowブロックチェーンの現在のパラメータでは)。
翻訳元->https://cadence-lang.org/docs/measuring-time
Previous << JSON-Cadence format
Flow BlockchainのCadence version1.0ドキュメント (Measuring Time In Cadence)