Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Fix fork choice #10837

Merged
merged 10 commits into from
Jul 8, 2019
Merged

Fix fork choice #10837

merged 10 commits into from
Jul 8, 2019

Conversation

ngotchac
Copy link
Contributor

@ngotchac ngotchac commented Jul 4, 2019

Fixes #10085

It seems that is_from_route_finalized was computed for the parent's block finalization at each iteration in fn tree_route. Thus if a fork happened, and the common ancestor was finalized, the from branch would be marked as finalized although it wasn't, and the switch to the better branch would never happened.

`is_from_route_finalized` check before switching to parent
@ngotchac ngotchac added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. labels Jul 4, 2019
@ngotchac ngotchac requested review from dvdplm and sorpaas July 4, 2019 08:37
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

But I really think we need to write a bunch of tests to make sure it's working correctly. Some cases I have in mind - (X) means that X is finalised.

Case 1:
(A) - A1 - A2 - A3[to]
    - B1 - B2[from]

Case 2:
A - A1 - (A2) - A3[from]
  - B1 -  B2[to]

Case 3:
A - (A1)[to] - A2[from]

Case 4:
A - (A1)[from] - A2[to]

I believe Case 4 will incorrectly return is_from_route_finalized: false, but so was the previous code, so we should either carefuly check the consequences and change the behaviour or document it properly and make sure it's will not cause us trouble in the future.

Copy link
Collaborator

@dvdplm dvdplm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the correct fix to me. I agree with @tomusdrw that this needs good unit tests (follow up PR?) and I'd really like to hear from @sorpaas too.

@dvdplm
Copy link
Collaborator

dvdplm commented Jul 4, 2019

The test failure here is fixable by a rebase.

Copy link
Collaborator

@sorpaas sorpaas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

* master:
  refactor: whisper: Add type aliases and update rustdocs in message.rs (#10812)
  Break circular dependency between Client and Engine (part 1) (#10833)
  tests: Relates to #10655: Test instructions for Readme (#10835)
  refactor: Related #9459 - evmbin: replace untyped json! macro with fully typed serde serialization using Rust structs (#10657)
  idiomatic changes to PodState (#10834)
  Allow --nat extip:your.host.here.org (#10830)
  When updating the client or when called from RPC, sleep should mean sleep (#10814)
  Remove excessive warning (#10831)
  Fix typo in README.md (#10828)
  ethcore does not use byteorder (#10829)
  Better logging when backfilling ancient blocks fail (#10796)
  depends: Update wordlist to v1.3 (#10823)
  cargo update -p smallvec (#10822)
  replace memzero with zeroize crate (#10816)
  Don't repeat the logic from Default impl (#10813)
  removed additional_params method (#10818)
  Add Constantinople eips to the dev (instant_seal) config (#10809)
@ordian ordian modified the milestones: 2.6, 2.7 Jul 5, 2019
@ngotchac
Copy link
Contributor Author

ngotchac commented Jul 5, 2019

@tomusdrw I added tests for tree_route as you described, but didn't modify the behavior you described on test case 4. I'm actually not quite sure where this could occur, so I don't know if we should modify it or not.

@@ -136,6 +138,29 @@ impl BlockBuilder {
})
}

/// Add a block with randomly generated transactions.
#[inline]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a test helper yes? Is it performance sensitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I think it's only used for tests. I just followed the structure of the other similar methods, so I'm not sure whether inline is needed here.

@@ -166,11 +191,19 @@ impl BlockBuilder {
let mut block = Block::default();
let metadata = get_metadata();
let block_number = parent_number + 1;
let transactions = metadata.transactions;
let transactions_root = ordered_trie_root(transactions.iter().map(|tx| {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You sure you need to loop over all txs and encode them like this, and why as a stream and not rlp::encode? Honest question, I really don't know!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh, .map(rlp::encode) produces the same result and is shorter

Copy link
Collaborator

@debris debris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm! there is just one minor idiomatic fix to do in a test :)

@@ -166,11 +191,19 @@ impl BlockBuilder {
let mut block = Block::default();
let metadata = get_metadata();
let block_number = parent_number + 1;
let transactions = metadata.transactions;
let transactions_root = ordered_trie_root(transactions.iter().map(|tx| {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeh, .map(rlp::encode) produces the same result and is shorter

@debris debris added B0-patch-stable 🕷 Pull request should also be back-ported to the stable branch. B1-patch-beta 🕷🕷 A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. and removed A0-pleasereview 🤓 Pull request needs code review. labels Jul 6, 2019
@dvdplm dvdplm requested a review from tomusdrw July 8, 2019 10:01
Copy link
Collaborator

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

assert_eq!(bc.best_block_hash(), a2_hash);

mark_finalized(a1_hash, &db, &bc);
assert!(!bc.tree_route(a1_hash, a2_hash).unwrap().is_from_route_finalized);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we document this counter intuitive behavior in the function docs? A small NOTE would suffice, that is_from_route_finalized works only if from and to are on different forks (i.e. have common ancestor or one is not an ancestor of the other)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I added a comment to the tree_route method.

Cargo.lock Outdated
@@ -55,18 +55,26 @@ dependencies = [

[[package]]
name = "aho-corasick"
version = "0.6.8"
version = "0.6.10"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you run cargo update? :)
it would make backporting harder, so please revert

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I just deleted the lock file and re-built the project...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of deleting, can you checkout Cargo.lock from master and build it with it?

git checkout master Cargo.lock
cargo check

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sure, sorry about that. Done.

parity-util-mem = "0.1"
itertools = "0.5"
kvdb = "0.1"
log = "0.4"
parity-bytes = "0.1"
parking_lot = "0.8"
rand = "0.6"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be it be a dev dep?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, actually the generator.rs module is not for tests only

@debris debris merged commit 073d242 into master Jul 8, 2019
@debris debris deleted the ng-fix-fork-choice branch July 8, 2019 17:21
ordian added a commit that referenced this pull request Jul 9, 2019
* master:
  Run cargo fix on a few of the worst offenders (#10854)
  removed redundant fork choice abstraction (#10849)
  Extract state-db from ethcore (#10858)
  Fix fork choice (#10837)
  Move more code into state-account (#10840)
  Remove compiler warning (#10865)
  [ethash] use static_assertions crate (#10860)
dvdplm added a commit that referenced this pull request Jul 9, 2019
* master:
  Run cargo fix on a few of the worst offenders (#10854)
  removed redundant fork choice abstraction (#10849)
  Extract state-db from ethcore (#10858)
  Fix fork choice (#10837)
  Move more code into state-account (#10840)
  Remove compiler warning (#10865)
  [ethash] use static_assertions crate (#10860)
@phahulin
Copy link
Contributor

Is this included in any of the already released versions (the last one atm is 2.5.6)? If not yet, which version is it scheduled to be included into?

@jam10o-new
Copy link
Contributor

@phahulin it was included in 2.6.0 (beta) so it is available on the 2.6 branch releases - I'm not sure if it was backported to stable at any point as well though...

dvdplm pushed a commit that referenced this pull request Sep 11, 2019
* Fix fork choice:
`is_from_route_finalized` check before switching to parent

* Add tests for `tree_route` with finalization

* Fix Cargo dependencies

* Add comment on `tree_route` for finalization.
Refactor a test.

* Fix compilation error

* Checkout Cargo.lock from master
dvdplm pushed a commit that referenced this pull request Sep 11, 2019
* Fix fork choice:
`is_from_route_finalized` check before switching to parent

* Add tests for `tree_route` with finalization

* Fix Cargo dependencies

* Add comment on `tree_route` for finalization.
Refactor a test.

* Fix compilation error

* Checkout Cargo.lock from master
This was referenced Sep 12, 2019
s3krit added a commit that referenced this pull request Sep 12, 2019
* add more tx tests (#11038)
* Fix parallel transactions race-condition (#10995)
* Add blake2_f precompile (#11017)
* [trace] introduce trace failed to Ext (#11019)
* Edit publish-onchain.sh to use https (#11016)
* Fix deadlock in network-devp2p (#11013)
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
* xDai chain support and nodes list update (#10989)
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
* EIP-1344 Add CHAINID op-code (#10983)
* manual publish jobs for releases, no changes for nightlies (#10977)
* [blooms-db] Fix benchmarks (#10974)
* Verify transaction against its block during import (#10954)
* Better error message for rpc gas price errors (#10931)
* Fix fork choice (#10837)
* Fix compilation on recent nightlies (#10991)
s3krit added a commit that referenced this pull request Sep 12, 2019
* add more tx tests (#11038)
* Fix parallel transactions race-condition (#10995)
* Add blake2_f precompile (#11017)
* [trace] introduce trace failed to Ext (#11019)
* Edit publish-onchain.sh to use https (#11016)
* Fix deadlock in network-devp2p (#11013)
* EIP 1108: Reduce alt_bn128 precompile gas costs (#11008)
* xDai chain support and nodes list update (#10989)
* EIP 2028: transaction gas lowered from 68 to 16 (#10987)
* EIP-1344 Add CHAINID op-code (#10983)
* manual publish jobs for releases, no changes for nightlies (#10977)
* [blooms-db] Fix benchmarks (#10974)
* Verify transaction against its block during import (#10954)
* Better error message for rpc gas price errors (#10931)
* tx-pool: accept local tx with higher gas price when pool full (#10901)
* Fix fork choice (#10837)
* Cleanup unused vm dependencies (#10787)
* Fix compilation on recent nightlies (#10991)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A7-looksgoodcantmerge 🙄 Pull request is reviewed well, but cannot be merged due to conflicts. B0-patch-stable 🕷 Pull request should also be back-ported to the stable branch. M4-core ⛓ Core client code / Rust.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Node is failing to sync with error "Error: Error(Engine(RequiresClient)"
8 participants