Operazione inserita nel nodo, ma non aggiunta alla blockchain | Errore contatore portafoglio
1 risposta
- voti
-
- 2020-01-02
TLDR : laprima operazione che haiiniettatoneltuonodo è validamanon verràmaiiniettata da altrinodi/panettieriperché ha commissionitroppobasse. Viene quindibloccatonelmempoole rende le operazioni successive che staitentando difalsificarenon valideperchéilprossimo contatore valido che desideri utilizzare ègià statopreso dall'operazione apagamentotroppobasso. Puoi riavviareiltuonodo o attendere chepassino 60blocchiper sbloccare la situazione.
Quello che credo accada qui è che laprima operazione che haiiniettato è consideratanon valida dagli altrituoi colleghi. Come hai detto,puòessere rifiutatoper diversimotivi (il casopiù comune è lamancanza di commissioni sufficienti).
Quindi,haiforgiato un'operazione che è valida rispetto alprotocolloe quindi validanelmempool. Iltuonodo ha accettato diiniettare l'operazioneperché alcunipanettieripotrebbero accettaree includere operazioni a 0 commissioni. Tuttavia,perimpostazionepredefinita,questonon èil caso. L'operazione che haiiniettatonelnodo è quindi viverenelmempoolin attesa che unpanettiere loincludain unblocco.
Quindi ora arriva lapartetecnica. Quando richiedi alnodo difalsificare un'operazioneperte,il client (o l'API che stai utilizzando) richiederà alnodoil contatore associato altuo account (nota amargine:il contatore è quiperprevenire attacchi di replay). Per acquisire questeinformazioni,ilnodointerrogherài dati utilizzando lo stato corrente della catena (ovvero lo stato che risulta dall'applicazione dell'ultimoblocco ricevuto)e restituirà,adesempio,
1000
. Affinché l'operazione che staifalsificando sia valida,il suo contatore deveessere1001
. In caso contrario,verrà visualizzato unerrorecontatorenelpassato
ocontatorein futuro
quandoilnodo cerca di convalidarlo.Neltuo caso,haiinserito un'operazione atariffatroppobassa con un contatore
128324
. Iltuonodo ritiene chetu sappia cosa staifacendo (adesempio,cercando di convincere unpanettiere abasso costo ainiettarlo)e quindinon controlla le commissioni. Senon ci sonopanettieri abasso costoin esecuzionenella rete,latua operazionenon saràmaiinclusae bloccatanelmempoolper60
blocchi (minimo 20minutiin babylonnet). Dopo quei 60blocchi,l'operazione sarà consideratatroppo vecchiae cancellata dalmempool. Eccoperché,dopo alcune volte,la situazione è stata sbloccata.Ora,mentre questa operazionenon valida èbloccatain mempool,laprossima operazione che crei utilizzandoil client richiederà ancheil contatore dalnodoe poiché l'ultima operazionenon è statainclusa,il contatoreprecedente
128324
verrà utilizzato dinuovo che si scontra con latransazioneprecedente. Quando ciò accade,mempoolnon è contentoperchéproverà a convalidare le operazioni una dopo l'altra. Poiché latuaprima operazione è valida (anche senon saràmaiinclusa),verrà applicata al suo statointerno che è uno statointermedioin cui è stata applicata latuaprima operazione aumentando cosìil contatore atteso successivo di uno. Laprossima volta che viene ricevuta un'operazione (per lo stesso account),mempool si aspetterà cheil contatore venga aumentato a128325
. In caso contrario,verrà rifiutato con unerrorecounterin thepast
. Seprovi ad aumentaremanualmenteil contatore,potresti ottenerecontatorein futuro
.Come uscire da questa situazione:
- puoi aspettare chepassino 60blocchie poi latuatransazione verrà scartataperchétroppo vecchia;
- puoi riavviareiltuonodo sene haiil controllo. Ilmempool viene cancellato quandoilnodo siferma;
- puoifalsificaree iniettare latuatransazione utilizzando un altronodo. Uno,chenon avrà l'operazionenon validabloccatanel suomempool.
Nellaprossima release della shell,ciproponiamo diincludere un RPC di amministrazione che verrà utilizzatoper rimuovere un'operazione specifica damempool.
P.S. Puoi controllare quali operazioni risiedonoin mempool usando RPC
/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
-
Comeinviereste quindipiùtransazioninello stessoblocco?Non significa chefino a quando la vecchia operazionenon è ancora confermata,nonpossiamotrasmetterenessunanuova operazione a causa di questamancata corrispondenza?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
Usoilmionodobabbylone inprecedenza ho aggiunto unportafoglio datezosfaucete invio alcunemonete almioportafogliogenerato contezos-client:
Inviatramiteeztz.js
Ora sto cercando diinviaretezos da unportafogliogenerato a un altro coneztz.js lib. Usa questo codice:
Quando loeseguoper laprima volta,ilnodoinietta lamia operazionee persino l'indirizzo di ritorno dellatransazione,ma questotrasferimentonon viene aggiunto allablockchain,ilmio saldonon è statomodificato. Registri delleprime operazioni:
Quando si ètentato diinviare la seconda volta,viene visualizzato l'errore del contatore:
Registri della seconda volta:
Se siimpostamanualmenteil contatore su 128326,verrà visualizzato l'errore
counter_in_the_future
.Errore del contatore scomparso dopomezz'ora,ma seprovo ainviaremonete,l'operazionenon verràinclusanellablockchaine riceverò dinuovo l'errore del contatore.
Inviatramitetezos-client
Hoimportato lamia chiaveprivatagenerata cometest_w2e hoprovato ainviaremonete contezos-client:
Laprima volta che ricevo lo stessoerrore del contatore:
Ma dopomezz'ora hafunzionato:
Quindi significa,errorenonnellagenerazione diportafogli onodotezos,l'errorepuòessere solonel clienteztz.js onei valoripassati. Forse hopassato unatariffa/limite_gas/importoerrato?
Comeposso risolvere questoproblema?
Nota. In realtà,utilizzo la libreria Tz.Netbiforcuta (c #),ma ha lo stessoflusso di lavoro dieztz.jse ricevogli stessierrori.