ブロック 4129631 の生成後に、NEMネットワークにおけるブロック生成は鈍化し、遅延しました。この状況は、予期せぬトランザクションがUnconfirmed Transactionsキャッシュに入ったことをきっかけに発生いたしました。その後、このトランザクションが期限切れになると、ブロックの生成は通常どおりへと戻りました。
確認された予期せぬトランザクションの構成と、Unconfirmed Transactionsキャッシュに入った経緯は次の通りです。
1-of-2マルチシグで設定されたマルチシグアカウントが、2つの矛盾するトランザクションを送信しました。ここでは、その連署者をA、Bとし、マルチシグアカウントをMとします。
発生の流れは次の通りです:
アカウントMが、 署名者Aによって署名された内部トランザクション- X -を内包するマルチシグトランザクションMTを送信
そのマルチシグトランザクションはチェーンにコミットされ、(BlockTransactionFactoryの一部として実行される)TransactionHashesObserverが、H(MT)と H(X) をHashTransactionsCacheに追加
重要な点は、TransactionsHashesNotification
が作成された時、 streamDefault
が使用され、 内部及び外部トランザクションに拡張されたことです:
アカウントMは、連署者Bが署名した同じ内部トランザクションXを持つマルチシグトランザクションMT'を送信します
BatchUniqueHashTransactionValidator
は、H(MT')がHashTransactionsCacheにないことをチェックするので、それはUnconfirmedTransactionsCacheに追加されます ✅
重要な点は、 pair.getTransactions()
が 外部トランザクションしか含まれていない Collection<Transaction>
を返すことです。 結果として、 H(MT') != H(MT) はチェックされますが、 H(X) はチェックされません。
MT' はハーベスターによってブロックに選択されます。BlockUniqueHashTransactionValidator
は、BatchUniqueHashTransactionValidator
と同じロジックを持つため、外部トランザクション MT'のハッシュのみがチェックされます。 その結果、トランザクションはハーベストされたブロックに含まれます。 ✅
MT'を含む新しくハーベストされたブロックが処理される時、TransactionHashesObserver
は、状態の変更を行うブロック処理の一部で、H(MT') H(X)の両方をHashTransactionsCache
に登録しようとします。ですが既に H(X) は UnconfirmedTransactionsCache
に存在するために失敗し、ハーベストされたブロックは拒否されます。 🛑
H(MT') が失効するまで、UnconfirmedTransactionsCache
ステップ5へ進みます。
修正につきましては、一意のハッシュトランザクションバリデーターのどちらもを、外部トランザクションと内部トランザクションの両方をチェックするようにすることです。このことは、単にTransactionExtensions.streamDefault()
を用いることで解決されます。
TransactionExtensions.streamDefault
を追加することで、MT' (または類似のもの) が `UnconfirmedTransactionsCache への追加を防ぐことができます。
TransactionExtensions.streamDefault
を追加することで、MT' (または類似のもの) が新たにハーベストされるブロックへの追加を防ぐことができます。