Serialize node block in the requested form, stripping witness.#1069
Open
echennells wants to merge 1 commit into
Open
Serialize node block in the requested form, stripping witness.#1069echennells wants to merge 1 commit into
echennells wants to merge 1 commit into
Conversation
A peer requesting a block without witness (getdata MSG_BLOCK) crashes the node. messages::block held the store's wire bytes plus an advisory witnessed_ flag, and serialize/size guarded on witness == witnessed_. The generic serializer calls serialize with the default witness = true, so the guard fails, serialize returns false, and the null payload is sent without a null check. Any peer can trigger it. The guard is the root error, but the witness argument must also function: a witness node servicing a non-witness peer must strip the witness on serialize, and the serializer cannot rely on the held object's form because one object may be sent to peers with differing requirements. Hold a system::chain::block_view instead of raw bytes and delegate serialize and size to block.to_data(witness) and block.serialized_size(witness); the view strips the witness when serialized without it. protocol_block_out_106 selects the form at read time via get_wire_block(link, witness) and wraps the result in the view. messages::transaction carries the same guard but nothing serializes it yet (transaction-out re-serializes from the parsed transaction), so it is left unchanged. Depends on the libbitcoin-system block_view and transaction_view to_data implementation.
db94fe2 to
627e27c
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A peer requesting a block without witness (
getdata MSG_BLOCK) crashes the node.messages::blockheld the store's wire bytes plus an advisorywitnessed_flag, andserialize/sizeguarded onwitness == witnessed_. The generic serializer callsserializewith the defaultwitness = true, so the guard fails,serializereturns false, and the null payload is sent without a null check — any peer can trigger it (in debug thesize()assert trips first).The guard is the root error, but the
witnessargument must also function: a witness node servicing a non-witness peer must strip the witness on serialize, and the serializer cannot rely on the held object's form, because one object may be sent to peers with differing requirements.The message now holds a
system::chain::block_viewinstead of the wire bytes and delegatesserialize/sizetoblock.to_data(witness)/block.serialized_size(witness)— the view strips the witness when serialized without it.protocol_block_out_106selects the form at read time. The incorrect guard and assert are removed.messages::transactioncarries the same guard, but nothing serializes it yet (transaction-out re-serializes from the parsed transaction), so it is left unchanged.Depends on libbitcoin/libbitcoin-system#1905 — will not build without it.
Full node test suite green.