Skip to content

psbt: Encode keytype as a compact size unsigned integer#2906

Merged
apoelstra merged 1 commit intorust-bitcoin:masterfrom
tcharding:06-24-psbt-key-type
Oct 15, 2024
Merged

psbt: Encode keytype as a compact size unsigned integer#2906
apoelstra merged 1 commit intorust-bitcoin:masterfrom
tcharding:06-24-psbt-key-type

Conversation

@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding commented Jun 24, 2024

Currently we use u8 for key type but it was pointed out that we should be using a u64 and encoding it as a compact type. The reason our code works now is because the compact type encoding for a u8 (less than

This breaks the serde impl, as shown by changes to the regression tests,

Fix: #2891

@github-actions github-actions bot added C-bitcoin PRs modifying the bitcoin crate test labels Jun 24, 2024
@tcharding tcharding marked this pull request as draft June 24, 2024 04:37
Copy link
Copy Markdown
Collaborator

@Kixunil Kixunil left a comment

Choose a reason for hiding this comment

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

Just change the constants to be u64. It removes some guarantees but I don't think anyone cares.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jun 24, 2024

Oh, and not supporting 128-bit architectures is definitely more reasonable than diverging from the BIP.

@apoelstra
Copy link
Copy Markdown
Member

Another solution to this bug would be just to state that we diverge from the bip and only support key types less than 0xFD - which seems like a reasonably sane thing to do.

We definitely should not do this. "Our implementation supports only 253 keytypes" is a pretty serious limitation.

As for the casts, some are because our constants are u8s. Just change them to u64s. And some are because our VarInt API gives us u64s but we actually want usizes. I think a better approach might be to first address #1016 / #2907 by resurrecting #2133 as a pair of methods encode::deserialize_compact_size32() -> u32 and encode::deserialize_varint_compact_size() -> usize which encapsulates the cast. (We already do not support 16-bit systems so casting from u32 to usize is fine.) Both methods should enforce the "MAX_SIZE" 32MB limit so that we can use a u32 rather than u64.

Once we have those methods we can do this PR more cleanly.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Jun 26, 2024

And some are because our VarInt API gives us u64s but we actually want usizes.

Which ones? I only saw one that was there already and that one is fine because it's bounded by MAX_VEC_SIZE.

@apoelstra
Copy link
Copy Markdown
Member

Maybe it's just the one.

@tcharding
Copy link
Copy Markdown
Member Author

Note to self, re-work this after #2972 is done.

@tcharding tcharding force-pushed the 06-24-psbt-key-type branch from c6df708 to d5c7122 Compare August 28, 2024 23:01
@github-actions github-actions bot added the C-internals PRs modifying the internals crate label Aug 28, 2024
@tcharding tcharding marked this pull request as ready for review August 28, 2024 23:02
@tcharding
Copy link
Copy Markdown
Member Author

Please read updated PR description. (I left this not as a draft to signal request for review)

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Aug 29, 2024

I don't understand how this is related to #3250, can you explain?

@tcharding
Copy link
Copy Markdown
Member Author

tcharding commented Aug 29, 2024

I thought #3250 caused fedimint to have database entries that they could no longer parse. Similarly this breaks serde impls so if stuff was written to database using serde then this PR will again break folk.

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented Aug 29, 2024

They can't parse it because they don't know the length upfront and our API stopped providing streamed deserialization.

It could in theory happen that someone stored information as PSBT and loaded in the same application and used one of the values: 255, 254, or 253 which are now special and they'd indeed not notice it's broken beforehand if they never accessed it in a different application and it would apparently work and this change would break them. I highly doubt this is the case and if it happened to anyone they can just depend on both the old version and the new one and convert the types. We might provide a library support for this if there is more than one such project because it doesn't make sense to put it into a library if there's only one.

Since I believe this is extremely unlikely, we should just wait and see if anyone complains.

@tcharding tcharding force-pushed the 06-24-psbt-key-type branch from d5c7122 to c93b6d0 Compare August 29, 2024 17:34
@tcharding tcharding marked this pull request as draft August 29, 2024 17:34
@github-actions
Copy link
Copy Markdown

🚨 API BREAKING CHANGE DETECTED

To see the changes click details on "Check semver breaks / PR Semver - stable toolchain" job then expand "Run semver checker script" and scroll to the end of the section.

@github-actions github-actions bot added the API break This PR requires a version bump for the next release label Aug 29, 2024
Currently we use `u8` for key type but it was pointed out that we should
be using a `u64` and encoding it as a compact type. The reason our code
works now is because the compact type encoding for a `u8` (less than
253) is the same as for a `u8`.

This breaks the `serde` impl, as shown by changes to the regression tests.
@tcharding tcharding force-pushed the 06-24-psbt-key-type branch from c93b6d0 to 2f656f7 Compare October 10, 2024 00:39
@github-actions github-actions bot removed the C-internals PRs modifying the internals crate label Oct 10, 2024
@tcharding tcharding requested a review from Kixunil October 10, 2024 00:40
@tcharding tcharding marked this pull request as ready for review October 10, 2024 00:40
@apoelstra
Copy link
Copy Markdown
Member

Quite frustrating about the serde breakage.

I kinda think we should drop the derived serde impl and just always encode as base64.

But this PR is fine for now.

Copy link
Copy Markdown
Member

@apoelstra apoelstra left a comment

Choose a reason for hiding this comment

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

ACK 2f656f7 successfully ran local tests

@tcharding
Copy link
Copy Markdown
Member Author

4 days ack'ed can be merged when you are ready please.

@apoelstra apoelstra merged commit 88af71c into rust-bitcoin:master Oct 15, 2024
tcharding added a commit to tcharding/rust-bitcoin that referenced this pull request Oct 27, 2024
In rust-bitcoin#2906 we switched from using a `u8` for type keys to using a `u64`
and encoding as a compact int (inline with the spec). Note that a `u8`
encodes to the same bytes as a `u64` when the value is < 252.

In that patch, I introduced a bug because the length returned by
`PoprietaryKey::consensus_encode` uses a hard code 1 for the length of
the encoding (because of single byte) instead of the variable length for
the new compact encoding.

Bug showed up in fuzzing, and was isolated by Jamil - mad props.
@tcharding tcharding deleted the 06-24-psbt-key-type branch October 28, 2024 01:04
apoelstra added a commit that referenced this pull request Oct 29, 2024
c89b816 psbt: Fix bug in Subtype consensus_encode (Tobin C. Harding)

Pull request description:

  In #2906 we switched from using a `u8` for type keys to using a `u64` and encoding as a compact int (inline with the spec). Note that a `u8` encodes to the same bytes as a `u64` when the value is < 252.

  In that patch, I introduced a bug because the length returned by `PoprietaryKey::consensus_encode` uses a hard code 1 for the length of the encoding (because of single byte) instead of the variable length for the new compact encoding.

  Bug showed up in fuzzing, and was isolated by Jamil - mad props.

  Fix: #3501

ACKs for top commit:
  jamillambert:
    ACK c89b816
  apoelstra:
    ACK c89b816; successfully ran local tests

Tree-SHA512: 1b61b6a9ece197d74038ceedb447fd3ca21db8e2a6a96c9281a99ac232c18c3ca55da8e3f46930401714d3575e9a406a36e4f44929ca963208a5df4be6b46cfb
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API break This PR requires a version bump for the next release C-bitcoin PRs modifying the bitcoin crate test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

psbt::raw::Key's type_value field should be serialized as VarInt

3 participants