-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Force block refetch if transaction is re-collated in a different block #1917
Conversation
4407123
to
c34c708
Compare
Pull Request Test Coverage Report for Build eaae1e0e-bc98-46d1-9495-fe739e747651
💛 - Coveralls |
@pasqu4le I would like you to take over this PR and make the following additions:
Ideally, the worker should implement |
e779cbe
to
b49de95
Compare
@pasqu4le please add a CHANGELOG entry and a few words in indexer README about the temporary fetcher |
query = | ||
from(block in Block, | ||
join: transactions in assoc(block, :transactions), | ||
where: block.consensus, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we going to refetch all blocks?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I couldn't find a way to find blocks with missing transactions without checking all blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Though, we should probably add a field to blocks
table (refetch_needed
) and set it to true
for all existing blocks.
This would prevent this worker from starting from scratch on every restart and ensure it stops completely when it's done.
cc @pasqu4le.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good, I'm on it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to refetch new incoming blocks, so we will need to set true
for them.
I don't want to "contaminate" the rest of the codebase with these temporary fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TIL Ecto.Schema.field
's :default
does not override Ecto.Migration,add
's :default
on new elements.
I ended up setting to false
the migration's :default
and adding a small update to execute
there as well.
b49de95
to
888b4f7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from the minor comments LGTM
end | ||
|
||
execute( | ||
"UPDATE blocks SET refetch_needed = TRUE;", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pasqu4le just curious, why do we need two updates here? Is UPDATE blocks SET refetch_needed = FALSE;
not enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second one (set to FALSE
) is kinda pointless, but it is there to use execute/2
instead of execute/1
so that ecto knows this is a reversible operation and rollback
s can be performed. I tried to give it a NULL;
as a no-op, because there is no need to make any changes for a rollback given that the field is going to be removed anyway, but ecto did not like that.
The reason there is a set to TRUE
is so to force the re-fetch of existing blocks while having the default: false
for newer ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
""
as a second parameter seems to work in such cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I didn't know that, I replaced it with ""
now
apps/indexer/README.md
Outdated
@@ -92,6 +92,7 @@ After all deployed instances get all needed data, these fetchers should be depre | |||
|
|||
- `uncataloged_token_transfers`: extracts token transfers from logs, which previously weren't parsed due to unknown format | |||
- `uncles_without_index`: adds previously unfetched `index` field for unfetched blocks in `block_second_degree_relations` | |||
- `blocks_transactions_mismatch`: refetches each block once and revokes consensus to those whose transaction number mismatches, to correct the result of a race condition |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pasqu4le could you please extend this description a little bit more
- describe what does not
mismatches
to what - clarify the race condition case
89a9ce2
to
8361f93
Compare
Regression test for the race condition described in issue #1911
Don't discard a transaction if it was eventually collated in the period between replaced transaction worker initialization and actual dropping.
Due to race conditions described in #1911 transactions from a consensus block might get overwritten by the same transactions from a non-consensus block. To prevent this we force a block refetch (by marking it as non-consensus), if a transaction belonging to it gets overwritten by the same transaction from a different block.
…tching transactions After the solution for #1991 it is necessary to remove consensus from blocks whose number of transactions mismatch compared to a node, so that these blocks are refetched.
8361f93
to
64acef7
Compare
Motivation
Due to race conditions described in #1911 transactions from a consensus block might get overwritten by the same transactions from a non-consensus block.
Changes
To prevent this we force a block refetch (by marking it as non-consensus), if a transaction belonging to it gets overwritten by the same transaction from a different block.
Also, a potential race condition is fixed in replaced transactions worker: it doesn't mark as
dropped/replaced
the transactions that eventually ended up in a block.Upgrading
A transient
old_block_hash
field is added totransactions
table for atomic deriving of re-collated transactions.Checklist for your PR
CHANGELOG.md
with this PR