操作はノードに注入されましたが、ブロックチェーンには追加されていません|ウォレットカウンターエラー
1 回答
- 投票
-
- 2020-01-02
TLDR :ノードに注入した最初の操作は有効ですが、料金が低すぎるため、他のノード/ベイカーによって注入されることはありません.次に、それはmempoolでスタックし、偽造しようとしている次の操作を無効にします.これは、使用する次の有効なカウンターが、低すぎる料金の操作によってすでに使用されているためです.ノードを再起動するか、60ブロックが経過するのを待って状況のロックを解除できます.
ここで起こると私が信じているのは、あなたが注入した最初の操作が他のピアによって無効であると見なされるということです.あなたが言ったように、それは複数の理由で拒否される可能性があります(最も一般的なケースは十分な料金ではありません).
つまり、プロトコルに関して有効であり、したがってmempoolで有効な操作を偽造しました.一部のパン屋が0手数料の操作を受け入れて含めている可能性があるため、ノードは操作の注入を受け入れました.ただし、デフォルトでは、これは当てはまりません.したがって、ノードに注入した操作は、パン屋がブロックに含めるのを待っているmempoolに住んでいます.
では、技術的な部分があります.ノードに操作を偽造するように要求すると、クライアント(または使用しているAPI)は、アカウントに関連付けられたカウンターをノードから要求します(補足:カウンターはリプレイ攻撃を防ぐためにここにあります).この情報を取得するために、ノードはチェーンの現在の状態(つまり、最後に受信したブロックの適用から生じる状態)を使用してデータをクエリし、たとえば
を返します. 1000
.偽造している操作が有効であるためには、そのカウンターが1001
である必要があります.そうでない場合は、ノードが検証しようとすると、過去のカウンター
または将来のカウンター
エラーが発生します.あなたの場合、カウンター
128324
を使用して低料金の操作を挿入しました.あなたのノードはあなたが何をしているのか知っているとみなし(例えば、低料金のパン屋にそれを注入させようとしている)、したがって料金をチェックしません.ネットワークで低料金のベイカーが実行されていない場合、操作が含まれず、60
ブロック(babylonnetで最小20分)の間mempoolにスタックします.これらの60ブロックの後、操作は古すぎると見なされ、mempoolから削除されます.これが、しばらくして、状況が解き放たれた理由です.これで、この無効な操作がmempoolでスタックしている間、クライアントを使用して偽造する次の操作もノードにカウンターを要求します.最後の操作が含まれていなかったため、前のカウンター
128324
は、前のトランザクションと衝突する再び使用されます.これが発生すると、mempoolは操作を次々に検証しようとするため、満足できません.最初の操作は有効であるため(含まれない場合でも)、最初の操作が適用された中間状態である内部状態に適用され、次の予想されるカウンターが増加します. 1.次回(同じアカウントに対して)操作が受信されると、mempoolはカウンターが128325
に増加することを期待します.そうでない場合は、counterin past
エラーで拒否されます.手動でカウンターを増やしようとすると、将来的にカウンター
が発生する可能性があります.この状況から抜け出す方法:
- 60ブロックが通過するのを待つと、トランザクションが古すぎるために破棄されます.
- ノードを制御できる場合は、ノードを再起動できます.ノードが停止すると、mempoolは消去されます.
- 別のノードを使用してトランザクションを偽造および注入できます. 1つは、無効な操作がmempoolにスタックすることはありません.
次のシェルリリースでは、mempoolから特定の操作を削除するために使用される管理RPCを含めることを目指しています.
P.S. RPC
を使用して、どの操作がmempoolに存在するかを確認できます./chains/main/mempool/pending_operations
TLDR: the first operation you injected in your node is valid but will be never be injected by other nodes/bakers because it has too low fees. It is then stuck in the mempool and make the the next operations you're trying to forge invalid because the next valid counter you want to use is already being taken by the too low fee operation. You can restart your node or wait for 60 blocks to pass to unlock the situation.
What I believe happens here is that the first operation you injected is considered invalid by your other peers. As you said, it can be rejected for multiple reasons (not enough fees being the most common case).
So, you forged an operation which is valid regarding the protocol and therefore valid in the mempool. Your node accepted injecting the operation because some bakers might be accepting and including 0 fees operations. However, by default, this is not the case. The operation you injected in the node is thus living in the mempool waiting for a baker to include it in a block.
So now comes the technical part. When you request the node to forge an operation for you, the client (or the API you're using) will request from the node the counter associated to your account (side note: the counter is here to prevent replay attacks). To grab this information, the node will query the data using the current state of the chain (i.e. the state that results from the application of the last block received) and will return, for example,
1000
. For the operation you're forging to be valid, its counter must then be1001
. If this is not the case, it will give you acounter in the past
orcounter in the future
error when the node is trying to validate it.In your case, you injected a too low fee operation with a counter
128324
. Your node considers that you know what you're doing (e.g. trying to get a low-fee baker to inject it) and thus does not check for the fees. If there are no low-fee baker running in the network, your operation will never be included and stuck in the mempool for60
blocks (20min minimum in babylonnet). After those 60 blocks, the operation will considered too old and purged from the mempool. This is why, after some times, the situation was unlocked.Now, while this invalid operation is stuck in the mempool, the next operation you forge using the client will also request the counter from the node and as your last operation was not included, the previous counter
128324
will be used again which collides with the previous transaction. When this happens, the mempool is not happy because it will try to validate the operations one after the other. As your first operation is valid (even if it will never be included), it will be applied on its internal state which is an intermediate state where your first operation was applied thus making the next expected counter increased by one. The next time an operation is received (for the same account) the mempool will expect the counter to be increased to128325
. If that's not the case, then it will reject it with acounter in the past
error. If you try to manually increase the counter, you might getcounter in the future
.How to get out of this situation:
- you may wait for 60 blocks to pass by and then your transaction will be discarded for being too old;
- you can restart your node if you have control over it. The mempool is erased when the node stops;
- you can forge and inject your transaction using another node. One, which will not have the invalid operation stuck in its mempool.
In the next shell release, we aim to include an admin RPC that will be used to remove a specific operation from the mempool.
P.S. You may check which operations live in the mempool using the RPC
/chains/main/mempool/pending_operations
-
次に、同じブロックで複数のトランザクションをどのように送信しますか?それは、古い操作がまだ確認されていない限り、この不一致のために新しい操作をブロードキャストできないということではありませんか?How would you then send multiple transactions in the same block? Doesn't that mean that as long as the old operation is not yet confirmed, we can't broadcast any new operation because of this mismatch there?
- 0
- 2020-05-09
- CherryDT
私は自分のバビロンノードを使用しており、以前はtezos蛇口からウォレットを追加し、tezos-clientを使用して生成されたウォレットにコインを送信しました:
eztz.js経由で送信
現在、eztz.js libを使用して、生成されたウォレットから別のウォレットにテゾを送信しようとしています. このコードを使用してください:
最初に実行したとき-ノードは操作を注入し、トランザクションのアドレスを返しますが、この転送はブロックチェーンに追加されず、残高は変更されませんでした.初回操作ログ:
2回目に送信しようとすると、カウンターエラーが発生します:
2回目のログ:
手動でカウンターを128326に設定すると、エラー
counter_in_the_future
が表示されます.30分後にカウンターエラーが発生しましたが、それでもコインを送信しようとすると、ブロックチェーンに操作が含まれず、再びカウンターエラーが発生します.
tezos-client経由で送信
生成した秘密鍵をtest_w2としてインポートし、tezos-clientでコインを送信しようとしました:
初めて同じカウンターエラーが発生しました:
しかし、30分後には機能しました:
つまり、ウォレットの生成やtezosノードではエラーが発生せず、エラーはeztz.jsクライアントまたは渡された値でのみ発生する可能性があります.たぶん私は間違った料金/gas_limit/金額を渡しましたか?
これを修正するにはどうすればよいですか?
注.実際、私はフォークされたTz.Netライブラリ(c#)を使用していますが、ワークフローはeztz.jsと同じであり、同じエラーが発生します.