Shell: early detection of incompatible new heads and branches.

This commit is contained in:
Grégoire Henry 2018-05-10 16:59:48 +02:00 committed by Benjamin Canou
parent 96dd65e36d
commit 6170ae2246

View File

@ -123,43 +123,33 @@ let bootstrap_new_branch w _ancestor _head unknown_prefix =
let validate_new_head w hash (header : Block_header.t) = let validate_new_head w hash (header : Block_header.t) =
let pv = Worker.state w in let pv = Worker.state w in
let chain_state = Distributed_db.chain_state pv.parameters.chain_db in debug w
State.Block.known chain_state header.shell.predecessor >>= function "fetching operations for new head %a from peer %a"
| false -> Block_hash.pp_short hash
debug w P2p_peer.Id.pp_short pv.peer_id ;
"missing predecessor for new head %a from peer %a" map_p
Block_hash.pp_short hash (fun i ->
P2p_peer.Id.pp_short pv.peer_id ; Worker.protect w begin fun () ->
Distributed_db.Request.current_branch pv.parameters.chain_db ~peer:pv.peer_id () ; Distributed_db.Operations.fetch
return () ~timeout:pv.parameters.limits.block_operations_timeout
| true -> pv.parameters.chain_db ~peer:pv.peer_id
debug w (hash, i) header.shell.operations_hash
"fetching operations for new head %a from peer %a" end)
Block_hash.pp_short hash (0 -- (header.shell.validation_passes - 1)) >>=? fun operations ->
P2p_peer.Id.pp_short pv.peer_id ; debug w
map_p "requesting validation for new head %a from peer %a"
(fun i -> Block_hash.pp_short hash
Worker.protect w begin fun () -> P2p_peer.Id.pp_short pv.peer_id ;
Distributed_db.Operations.fetch Block_validator.validate
~timeout:pv.parameters.limits.block_operations_timeout ~notify_new_block:pv.parameters.notify_new_block
pv.parameters.chain_db ~peer:pv.peer_id pv.parameters.block_validator pv.parameters.chain_db
(hash, i) header.shell.operations_hash hash header operations >>=? fun _block ->
end) debug w
(0 -- (header.shell.validation_passes - 1)) >>=? fun operations -> "end of validation for new head %a from peer %a"
debug w Block_hash.pp_short hash
"requesting validation for new head %a from peer %a" P2p_peer.Id.pp_short pv.peer_id ;
Block_hash.pp_short hash set_bootstrapped pv ;
P2p_peer.Id.pp_short pv.peer_id ; return ()
Block_validator.validate
~notify_new_block:pv.parameters.notify_new_block
pv.parameters.block_validator pv.parameters.chain_db
hash header operations >>=? fun _block ->
debug w
"end of validation for new head %a from peer %a"
Block_hash.pp_short hash
P2p_peer.Id.pp_short pv.peer_id ;
set_bootstrapped pv ;
return ()
let only_if_fitness_increases w distant_header cont = let only_if_fitness_increases w distant_header cont =
let pv = Worker.state w in let pv = Worker.state w in
@ -177,35 +167,64 @@ let only_if_fitness_increases w distant_header cont =
return () return ()
end else cont () end else cont ()
let may_validate_new_head w hash header = let assert_acceptable_head w hash (header: Block_header.t) =
let pv = Worker.state w in let pv = Worker.state w in
let chain_state = Distributed_db.chain_state pv.parameters.chain_db in let chain_state = Distributed_db.chain_state pv.parameters.chain_db in
State.Block.known chain_state hash >>= function State.Chain.acceptable_block chain_state hash header >>= fun acceptable ->
| true -> begin fail_unless acceptable
State.Block.known_valid chain_state hash >>= function (Validation_errors.Checkpoint_error (hash, Some pv.peer_id))
| true ->
debug w let may_validate_new_head w hash (header : Block_header.t) =
"ignoring previously validated block %a from peer %a" let pv = Worker.state w in
Block_hash.pp_short hash let chain_state = Distributed_db.chain_state pv.parameters.chain_db in
P2p_peer.Id.pp_short pv.peer_id ; State.Block.known_valid chain_state hash >>= fun valid_block ->
set_bootstrapped pv ; State.Block.known_invalid chain_state hash >>= fun invalid_block ->
pv.last_validated_head <- header ; State.Block.known_valid chain_state
return () header.shell.predecessor >>= fun valid_predecessor ->
| false -> State.Block.known_invalid chain_state
debug w header.shell.predecessor >>= fun invalid_predecessor ->
"ignoring known invalid block %a from peer %a" if valid_block then begin
Block_hash.pp_short hash debug w
P2p_peer.Id.pp_short pv.peer_id ; "ignoring previously validated block %a from peer %a"
fail Validation_errors.Known_invalid Block_hash.pp_short hash
end P2p_peer.Id.pp_short pv.peer_id ;
| false -> set_bootstrapped pv ;
only_if_fitness_increases w header @@ fun () -> pv.last_validated_head <- header ;
validate_new_head w hash header return ()
end else if invalid_block then begin
debug w
"ignoring known invalid block %a from peer %a"
Block_hash.pp_short hash
P2p_peer.Id.pp_short pv.peer_id ;
fail Validation_errors.Known_invalid
end else if invalid_predecessor then begin
debug w
"ignoring known invalid block %a from peer %a"
Block_hash.pp_short hash
P2p_peer.Id.pp_short pv.peer_id ;
Distributed_db.commit_invalid_block pv.parameters.chain_db
hash header [Validation_errors.Known_invalid] >>=? fun _ ->
fail Validation_errors.Known_invalid
end else if not valid_predecessor then begin
debug w
"missing predecessor for new head %a from peer %a"
Block_hash.pp_short hash
P2p_peer.Id.pp_short pv.peer_id ;
Distributed_db.Request.current_branch
pv.parameters.chain_db ~peer:pv.peer_id () ;
return ()
end else begin
only_if_fitness_increases w header @@ fun () ->
assert_acceptable_head w hash header >>=? fun () ->
validate_new_head w hash header
end
let may_validate_new_branch w distant_hash locator = let may_validate_new_branch w distant_hash locator =
let pv = Worker.state w in let pv = Worker.state w in
let distant_header, _ = (locator : Block_locator.t :> Block_header.t * _) in let distant_header, _ = (locator : Block_locator.t :> Block_header.t * _) in
only_if_fitness_increases w distant_header @@ fun () -> only_if_fitness_increases w distant_header @@ fun () ->
assert_acceptable_head w
(Block_header.hash distant_header) distant_header >>=? fun () ->
let chain_state = Distributed_db.chain_state pv.parameters.chain_db in let chain_state = Distributed_db.chain_state pv.parameters.chain_db in
State.Block.known_ancestor chain_state locator >>= function State.Block.known_ancestor chain_state locator >>= function
| None -> | None ->