Skip to content

push-based decoding#2184

Closed
Kixunil wants to merge 8 commits intorust-bitcoin:masterfrom
Kixunil:push_decode
Closed

push-based decoding#2184
Kixunil wants to merge 8 commits intorust-bitcoin:masterfrom
Kixunil:push_decode

Conversation

@Kixunil
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil commented Nov 10, 2023

This is a demo of push-based decoding - sloppy programming ahead! Insufficient error handling, no DoS protection, missing checks during decoding, missing documentation, some things (no-std) not tested, different MSRV...

This is now ready.

I'm mainly gathering general feedback: is this something we want to do? Do you think the added complexity is worth it? Do you have other ideas to improve it (other than intentionally ignored parts).

Note that this is currently just decoding, encoding to come later unless this proposal is rejected.

Also regarding MSRV, I could make it lower but it'd help if I didn't have to. It should be 1.51 but I didn't actually check - I tested with 1.63. What do you think about bumping it?

Closes #1741
Closes #1251

@Kixunil Kixunil added enhancement help wanted 1.0 Issues and PRs required or helping to stabilize the API labels Nov 10, 2023
@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Nov 12, 2023

I've just learned about ControlFlow which I think would be much more clear than Result<Infallible, Result<(), Error> but the MSRV would have to be 1.55. What do you think?

@apoelstra
Copy link
Copy Markdown
Member

Neat! I am in favor of using ControlFlow. Maybe initially we should add this API in parallel to the existing one and cfg-gate it on 1.55. It seems like on the MSRV-for-stable thread we've achieved rough consensus on something in the mid-1.60s but we're waiting on Debian and the 2-year rule to actually pull the trigger. Something of this scale I think we'd want some real-world testing before fully cutting over to it, so it could make sense to have a parallel API.

cc #1251 where push-based decoding was first discussed.

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Nov 13, 2023

I'm not sure how much we can feature-gate it if we want to delegate the impls. (Maintaining two different implementations is annoying; though thankfully they shouldn't change much.) If we're going to do that I would limit it to one release or so.

Also I don't think we can reasonably feature gate it on Rust version - cfg in Cargo.toml doesn't support that and putting #[cfg] ins the entire stack seems too much.

Note that 1.55 is already >2 years old (September 2021) and 1.63 is in Debian stable. But if we're going to bump it I'd jump to 1.56 which is still 2 years old and supports edition 2021 (we don't have to use it right away but it's nice to have).

@apoelstra
Copy link
Copy Markdown
Member

Sounds good to me. cc @tcharding is there an existing issue that we should glom onto to discuss MSRV bumps, or should @Kixunil just make a PR to bump to 1.56 and we'll try to get a bunch of ACKs.

cc #1722.

@tcharding
Copy link
Copy Markdown
Member

Lets PR and push forward! I tried bringing up Rust 1.57 a few months ago but I was too early because it was not yet 2 years old, #1983

I'd like to see 1.56, edition 2021 would make my life a bunch easier.

@tcharding
Copy link
Copy Markdown
Member

tcharding commented Nov 14, 2023

I'm keen for this PR. I don't have any comments or suggestions other than that I'm afraid.

@tcharding
Copy link
Copy Markdown
Member

Just in case you go to do it @Kixunil, I did the MSRV bump #2188

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Nov 14, 2023

I'm keen for this PR. I don't have any comments or suggestions other than that I'm afraid.

That's fine. I was mainly checking that my approach isn't viewed as horribly complicated or something like that.

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Nov 14, 2023

Updated to use ControlFlow, edition 2021, and a new method I added to clean up the code a bit.

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Jan 17, 2024

Rebased and a bit improved but not really ready. Working on encoding now.

@Kixunil Kixunil force-pushed the push_decode branch 10 times, most recently from 804193f to c41e5b9 Compare January 19, 2024 22:00
@Kixunil Kixunil marked this pull request as ready for review January 20, 2024 00:35
Kixunil added 6 commits July 24, 2024 11:35
This implements `bitcoin_consensus_encoding::Decode` for `Transaction`
and the types used inside it to demonstrate how `push_decode` can be
used to abstract over the byte source (sync/async, std/no-std). The
change is designed to be incremental so the exisitng code continues to
use old traits, we're just adding new capabilities that may later
replace the current encoding approach.
Similarly to push-based decoding there's pull-based encoding. This
change adds pull-based encoding support for the types that were
already implementing push-bassed encoding plus `Script` which can be
encoded but not decoded.
@github-actions github-actions bot added C-bitcoin PRs modifying the bitcoin crate C-internals PRs modifying the internals crate labels Jul 24, 2024
@Kixunil Kixunil marked this pull request as draft July 24, 2024 11:38
@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Jul 24, 2024

Just rebase, will address the review later.

@coveralls
Copy link
Copy Markdown

Pull Request Test Coverage Report for Build 10075949365

Details

  • 726 of 958 (75.78%) changed or added relevant lines in 14 files are covered.
  • 23 unchanged lines in 4 files lost coverage.
  • Overall coverage decreased (-0.3%) to 82.914%

Changes Missing Coverage Covered Lines Changed/Added Lines %
bitcoin/src/consensus/serde.rs 0 1 0.0%
bitcoin/src/consensus/encode.rs 39 42 92.86%
consensus-encoding/src/units_impls.rs 3 6 50.0%
consensus-encoding/src/lib.rs 46 50 92.0%
consensus-encoding/src/decode.rs 39 49 79.59%
consensus-encoding/src/varint.rs 71 96 73.96%
bitcoin/src/blockdata/witness.rs 87 118 73.73%
consensus-encoding/src/vec.rs 32 70 45.71%
consensus-encoding/src/encode.rs 205 262 78.24%
bitcoin/src/blockdata/transaction.rs 179 239 74.9%
Files with Coverage Reduction New Missed Lines %
bitcoin/src/blockdata/witness.rs 1 85.94%
bitcoin/src/blockdata/transaction.rs 4 86.74%
bitcoin/src/consensus/encode.rs 6 91.09%
bitcoin/src/consensus/mod.rs 12 34.33%
Totals Coverage Status
Change from base Build 10059904982: -0.3%
Covered Lines: 20226
Relevant Lines: 24394

💛 - Coveralls

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Jul 24, 2024

Also I'd love to rebase this on top of #3100 (not that I love rebasing this monstrosity...)

@jirijakes
Copy link
Copy Markdown
Contributor

Concept ACK.

Just spent whole morning trying to understand. But after a few hours it started to click. Pretty cool!

TLDR: It's all basically Rust version of Haskell's binary package :-)

data Decoder a = Fail !B.ByteString String
              | Partial (Maybe B.ByteString -> Decoder a)
              | Done !B.ByteString a
              | BytesRead !Int64 (Int64 -> Decoder a)

newtype Get a = C { runCont :: forall r.
                               B.ByteString ->
                               Success a r ->
                               Decoder   r }

type Success a r = B.ByteString -> a -> Decoder r

instance Monad Get where 

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Jul 27, 2024

But after a few hours it started to click.

I knew I wanted to expand the documentation a lot but damn, I didn't expect it to take people hours without it. :(

Good to know.

@jirijakes
Copy link
Copy Markdown
Contributor

jirijakes commented Jul 27, 2024

I didn't expect it to take people hours without it. :(

There are many details to understand, part of them in push_decode which I was not familiar with; for example: in transaction decoder, what do sub_decode + wrap_sub_decode do and why? how do all the macros work? etc. It takes a while to understand.

I don't think it's problem of documentation, rather it's the size and (inherent) complexity.

@Kixunil
Copy link
Copy Markdown
Collaborator Author

Kixunil commented Jul 27, 2024

Yeah, the thing is, I hope it won't be required to understand all of it to get benefits. Basically understand the basic idea, have examples how to use it and some examples how to implement decoders/encoders. sub_decode and wrap_decode are indeed a bit weird but pretty niche and thankfully also somewhat nice.

Side note: I had some other ideas that would make the crate even bigger but would result in simpler usage. Some of those ideas are quite crazy though :D.

tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Sep 26, 2025
This is Kix's work shamelessly stolen from without his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Sep 30, 2025
This is Kix's work shamelessly stolen from his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Sep 30, 2025
This is Kix's work shamelessly stolen from his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Oct 1, 2025
This is Kix's work shamelessly stolen from his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Oct 1, 2025
This is Kix's work shamelessly stolen from his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Oct 1, 2025
This is Kix's work shamelessly stolen from his draft PR rust-bitcoin#2184

Implement a decoder for decoding compact size integer. Will be
used to decode the length prefix when implementing vec decoders.

Co-authored-by: Martin Habovstiak <martin.habovstiak@gmail.com>
@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding closed this Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.0 Issues and PRs required or helping to stabilize the API C-bitcoin PRs modifying the bitcoin crate C-consensus_encoding PRs modifying the consensus-encoding crate C-internals PRs modifying the internals crate enhancement help wanted

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Encodable and Decodable should be named Encode and Decode Push-based consensus decoding

6 participants