Skip to content

Conversation

laanwj
Copy link
Member

@laanwj laanwj commented Dec 15, 2014

This pull replaces almost all uses of uint256 and all uses of uint160 to use opaque byte blobs blob256 and blob160 with only the following operations:

  • Default initialization to 0, or from a vector of bytes
  • Assignment from other blobXXXs
  • IsNull() compare to special all-zeros value
  • SetNull() clear to special all-zeros value: Bitcoin needs IsNull() / SetNull() because we often use the all-zeroes value as a marker for errors and empty values.
  • < for sorting in maps.
  • != == test for (in)equality
  • GetHex/SetHex/ToString because they're just so useful
  • begin()/end() raw access to the data
  • size() returns a fixed size
  • GetSerializeSize() Serialize Unserialize serialization just reads and writes the bytes
  • GetCheapHash() this is similar to GetLow64() and returns part of the value as uint64_t, for cheap hashing when the contents are assumed distributed uniformy random.

uint256 (used for proof-of-work mainly), on the other hand, loses all functionality like raw bytes access and serialization. Its memory should not be accessed directly. This is necessary for #888 (big endian support).
uint160 is completely removed as Bitcoin Core does no 160-bit integer arithmetic.

Overall steps (see commits)

Even though the diff is huge, I've tried to follow a logical and easy to review process:

  1. Introduce base_uint::SetNull and base_uint::IsNull() as well as other methods that will later be on base_blob, to prepare for migration

  2. Replace x=0 with .SetNull(), x==0 with IsNull(), x!=0 with !IsNull(). Replace uses of uint256(0) with uint256().

  3. Introduce blob256 and blob160 as well as conversion functions (only needed for blob256, we don't ever compute with uint160).

  4. Replace GetLow64() with GetCheapHash()

  5. Rename uint256 and uint160 to blob256 and blob160 except where big integers are really necessary. For reviewing convenience I separated this out into

    A) pure renames uintXXX to blobXXX, can easily be verified (in reverse) with
    find -name *.h -print0 | xargs -0 sed -i 's/blob256/uint256/g'
    find -name *.cpp -print0 | xargs -0 sed -i 's/blob256/uint256/g'
    find -name *.h -print0 | xargs -0 sed -i 's/blob160/uint160/g'
    find -name *.cpp -print0 | xargs -0 sed -i 's/blob160/uint160/g'

    B) string conversions uint256("string") to blob256S("string")

    C) Added #includes and predeclared classes

    D) Necessary conversions between uint256 and blob256 Focus reviewing here

  6. Remove now-unused methods from base_uint and blob160/blob256, eg GetHash, also remove unused uint160.

Eases step-by-step migration to blob.
Replace x=0 with .SetNull(),
x==0 with IsNull(), x!=0 with !IsNull().
Replace uses of uint256(0) with uint256().
Convert between blobs and uints, mostly for proof of work checks.
SignatureHash and its test function SignatureHashOld
return uint256(1) as a special error signaling value.
Return a local static constant with the same value instead.
Clients outside the class have no business poking at the internals.
Avoid dangerous cases where 0 is interpreted as std::string(0).
Keyword `explicit` does not help here.
@paveljanik
Copy link
Contributor

This appears to be unused now:

src/test/uint256_tests.cpp:const double R1Sdouble = 0.7096329412477836074; 

@laanwj
Copy link
Member Author

laanwj commented Dec 16, 2014

@paveljanik Thanks, I'll remove it. All *S variables in uint256_tests.cpp are for testing uint160, which went away.

No uint160 arithmetic is used at all. Also remove the tests.
@laanwj
Copy link
Member Author

laanwj commented Dec 16, 2014

Re: people complaining about rebasing their pulls, if the large diff in 'A: pure renames' is problematic, we could cheat by changing uint256 and uint160 to be blob types and introduce a new type for actual 256 bit integer arithmetic. But as clear type names are important I don't really like this.


friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; }
friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; }
friend inline bool operator<(const base_blob& a, const base_blob& b) {
Copy link
Member

Choose a reason for hiding this comment

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

Would it break anything if we defined the ordering of blob256 as platform-dependent? That would allow using memcmp for this operator too.

Copy link
Member

Choose a reason for hiding this comment

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

In fact, I think that would allow implementing blob* as wrappers around byte arrays, and leave all integer conversion to uint*.

EDIT: Sorry, they already are byte-arrays; I should read more before commenting.

EDIT2: In fact, I think the implementation below is already identical to just "memcmp(a.data, b.data, sizeof(a.data)) < 0".

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's identical to memcmp, good catch. Will use that.

@sipa
Copy link
Member

sipa commented Dec 16, 2014

I would actually like the PR as a whole to just introduce arith_uint256 or something (for the version with arithmetic semantics) and leave uint256/uint160 in place (for the version without). That will result in a much smaller patchset, and require much less rebasings while this is being reviewed.

Perhaps later there can be mass rename that is trivial to review and merge.

@laanwj
Copy link
Member Author

laanwj commented Dec 16, 2014

Ok, reluctantly agreed... As I say above already I hate the idea of using uint160/uint256 for what are not actually integers and introduce a yes_this_is_really_an_int256 for real uint256 arithmetic, but yes the diff will be much smaller.

@laanwj
Copy link
Member Author

laanwj commented Dec 16, 2014

Closing, will reopen after reorganization.

Continued in #5490

@laanwj laanwj closed this Dec 16, 2014
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants