Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve block version #1351

Merged

Conversation

tcharding
Copy link
Member

@tcharding tcharding commented Oct 26, 2022

After initial attempt and review this PR has been re-written.

  • Patch 1: Make types in block more terse, this is preparatory clean up based on suggestion below.
  • Patch 2: Make inner value of Version private to hide the i32/u32 discrepancy

This is a follow up to #1240

@tcharding tcharding changed the title Use u32 for block version instead of i32 Use u32 for block version instead of i32 Oct 26, 2022
nlanson
nlanson previously approved these changes Oct 26, 2022
@apoelstra
Copy link
Member

This has been proposed from time to time and nacked because Bitcoin Core uses i32, so if we use a different type then we are deviating from the protocol in some philosophical sense.

@tcharding
Copy link
Member Author

Oh, did I misunderstand your comment: #1240 (comment)

I interpreted that comment as a concept ack for this PR?

@apoelstra
Copy link
Member

No, you did interpret me right :). This idea has been nacked in the past, but not by me.

I'm tempted though to just go all the way to a proper newtype here rather than potentially debating u32 vs i32.

@tcharding tcharding changed the title Use u32 for block version instead of i32 Improve block version Oct 27, 2022
@tcharding
Copy link
Member Author

I'm tempted though to just go all the way to a proper newtype here rather than potentially debating u32 vs i32.

I don't fully get what you mean by "all the way to a proper newtype" since its a struct already, I had a go at abstracting away the i32/u32 business by making the inner value private. Does that meet your criteria?

@apoelstra
Copy link
Member

@tcharding yeah, I like this direction (and in this case we could change the internal repr to u32 if we wanted as long as we were convinced there were no API-visible ways to distinguish this).

I think that we need some from_consensus/to_consensus methods that would let you get an i32 out though, because I'm not convinced that the current API is sufficient to do everything that people might want to do.

@tcharding
Copy link
Member Author

tcharding commented Oct 28, 2022

Added as a separate patch. I was liberal with docs about Bitcoin Core and the oddness of there being a signed inner value.

@tcharding
Copy link
Member Author

Forgot to rebase to pick up CI fix.

@tcharding
Copy link
Member Author

Its hard to get good help :)

@@ -111,18 +113,40 @@ impl BlockHeader {
#[derive(Copy, PartialEq, Eq, Clone, Debug, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
pub struct BlockVersion(pub i32);
pub struct Version(i32);
Copy link
Contributor

@nlanson nlanson Oct 28, 2022

Choose a reason for hiding this comment

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

We're still keeping the inner value as i32?

There are a quite a few instances of casting u32 to i32 and vice versa internally so I think the switch to u32 should still be here.

Copy link
Member

Choose a reason for hiding this comment

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

@nlanson the version is conceptually a signed integer. This is how it is represented in the reference implementation of Bitcoin.

Copy link
Member

Choose a reason for hiding this comment

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

For casts, I see two casts to u32 and one to i32, all to deal with the top-bit business. I don't think this is too bad.

I would ACK a PR which changed the internal repr to u32 but I don't think it's necessary and I slightly prefer the current situation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

i32 is ridiculous, what does a negative version even mean? Time travel?

Unless Core somewhere actually uses something like -42 for version and doesn't treat it as a bag of bits I prefer u32. Thankfully newtype will shield the outside code from most of this nonsense.

@@ -301,7 +325,7 @@ impl Block {
// number (including a sign bit). Height is the height of the mined
// block in the block chain, where the genesis block is height zero (0).

if self.header.version < BlockVersion(2) {
if self.header.version < Version(2) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if self.header.version < Version(2) {
if self.header.version < Version::TWO {

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah yes, thanks. Used as suggested.

apoelstra
apoelstra previously approved these changes Oct 28, 2022
Copy link
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 bef3fcb

@tcharding
Copy link
Member Author

Rebased and used Version::TWO in block as suggested.

apoelstra
apoelstra previously approved these changes Nov 4, 2022
Copy link
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 64ae953

Copy link
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.

I'm still not sure if I should ACK i32... I think I will but I will give myself some time to be sure.

@@ -143,21 +167,21 @@ impl BlockVersion {
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Potentially interesting method:

/// Returns `true` if it looks like this version is affected by overt use of ASIC BOOST.
///
/// Some longer explanation of what's ASIC BOOST and what we check here.
pub fn resembles_asic_boost() {
// I don't remember which exact bits AB uses
}

bitcoin/src/blockdata/block.rs Outdated Show resolved Hide resolved
pub fn to_consensus(self) -> i32 {
self.0
}

/// Check whether the version number is signalling a soft fork at the given bit.
///
/// A block is signalling for a soft fork under BIP-9 if the first 3 bits are `001` and
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps we should panic for non-sensical values of bit?

Currently the types in the block module have longer names than
necessary, "header" and "version" identifiers contain the word "block",
this is unnecessary because we can write `block::Header` instead of
`BlockHeader` when context is required. This allows us to use the naked
type `Header` inside the `block` module with no loss of clarity.

We are stuck with `BlockHash` because the type is defined along with all
the other hash types in `hash_types`, leave it as is for now but
re-export it from the `block` module to assist in putting types that are
used together in scope in the same place, making import statements more
ergonomic.
The Bitcoin block version is a signed integer for historical reasons,
but we bit twiddle it like an unsigned integer and during consensus
encode/decode we cast the signed value to an unsigned value.

In order to hide this confusion, make the inner value private and add a
couple of constants for v1 and v2 block versions.
The `Version` type uses a signed 32 bit integer inner type but we bit
twiddle as if it was a `u32`. We recently made the inner type private to
hide the data type because of this oddness.

Add methods `from_consensus` and `to_consensus` to facilitate any
possible thing users may want to do with a consensus version value.
"Bitcoin Core" is conventionally named using capital letters.

Audit and fix all mentions of "Bitcoin Core" in the codebase to use
capital letters.
@tcharding
Copy link
Member Author

tcharding commented Nov 5, 2022

Changes in force push:

  • rebase to pick up clippy fixes
  • Used correct capitialisation of "Bitcoin Core" (amended patch)
  • Added an additional patch that fixes capitialisaton of Bitcoin Core codebase wide

Please note, two comments from @Kixunil have not been addressed, waiting on input from others. Also waiting on further input from you Kix re the i32 thing, no rush.

thanks

Copy link
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.

ACK 248f9a3

These changes contain un-publishing the internal representation which is a good step towards removing signed insanity, so it makes no sense to block this.

I'm kinda tempted into arguing that conversion methods should be something like to_core_like_consensus to signify that they are provided for compatibility with core but it may be that the negative version does have some interesting semantics and I didn't have the time to dig into it yet.

Copy link
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 248f9a3

@apoelstra apoelstra merged commit 4bce69d into rust-bitcoin:master Nov 6, 2022
@tcharding tcharding deleted the 10-26-block-version-use-u32 branch November 7, 2022 20:34
tcharding pushed a commit to tcharding/rust-bitcoin that referenced this pull request Nov 7, 2022
248f9a3 Use capital letters for Bitcoin Core (Tobin C. Harding)
832169e Add to/from_consensus methods to Version type (Tobin C. Harding)
24984f0 Make block::Version inner value private (Tobin C. Harding)
7e146ed Make types in block module more terse (Tobin C. Harding)

Pull request description:

  After initial attempt and review this PR has been re-written.

  - Patch 1: Make types in `block` more terse, this is preparatory clean up based on suggestion below.
  - Patch 2: Make inner value of `Version` private to hide the i32/u32 discrepancy

  This is a follow up to rust-bitcoin#1240

ACKs for top commit:
  Kixunil:
    ACK 248f9a3
  apoelstra:
    ACK 248f9a3

Tree-SHA512: ee031035288a2bcc246a9837a6028c254c51daf78a5cc2441b467ab7f183f1700a63911a2e78b84a20674ce0a83851a7c3bb7e46644a56fdd255685b9a0bf7f2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants