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

Value refactor #237

Merged

Conversation

uncomputable
Copy link
Collaborator

Rename the variants of Value and construct {256, 512}-bit values safely.

@uncomputable uncomputable force-pushed the 2024-07-value-refactor branch 2 times, most recently from 11235bc to 1a81869 Compare July 24, 2024 16:36
@uncomputable uncomputable requested a review from apoelstra July 24, 2024 16:36
@uncomputable
Copy link
Collaborator Author

Fixed the jets-bench subcrate.

src/value.rs Outdated
/// this means that the unit value doesn't contain any information.
///
/// The unit value is wrapped in left and right values
/// to encode information.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In 7459af0:

"The unit value must be embedded in a sum type to encode information."

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I like the word "wrap" because we wrap values in Rust all the time. Values cannot be embedded inside types.

src/value.rs Outdated
///
/// A left value is the first option for a sum type `A + B`.
/// It means we go left and wrap a value of type `A`.
/// The choice of going left encodes one bit.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In 7459af0:

I find this "go left" terminology confusing. I think it's clearer to just say "Encodes a value of type A as a sum type A + B, using a bit to specify that the left type is occupied." Similar with the below.

src/value.rs Outdated
/// It means we go both left and right and
/// that we wrap values of both type `A` and type `B`.
/// There is no choice,
/// so the information is contained solely in the wrapped values.
Copy link
Collaborator

Choose a reason for hiding this comment

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

In 7459af0:

This "only option" business is definitely confusing. The number of values in a product type is equal to the product of the numbers of values of the factor types. I would drop this paragraph and say "Since there is no ambiguity about which types are occupied, no additional bits are used and the information is contained solely in the wrapped values.". If you want to say this at all.

.collect::<Vec<u8>>()
.try_into()
.unwrap();
let mid_state = Value::u256(&arr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

In 010e675:

I guess it doesn't matter because we intend to drop this code anyway after #239 but it would be nice to get rid of the unnecessary Vec here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I switched to using Value::power_of_two, which is also internally called by Value::u256. We still have to allocate a Vec, like on master, but we no longer have to create an extra byte array.

@apoelstra
Copy link
Collaborator

utACK 1a81869. Let me know if you want to address the above comments, and I can ack/merge.

Value::Left and Value::Right better reflect the parallel to Either::Left
and Either::Right. Value::Product is more easily readable than
Value::Prod.
Value::left matches Value::Left and Value::as_left.
Value::right matches Value::Right and Value::as_right.
Value::product matches Value::Product and Value::as_product.
@uncomputable uncomputable force-pushed the 2024-07-value-refactor branch from 1a81869 to f308d5e Compare July 26, 2024 21:03
@uncomputable
Copy link
Collaborator Author

Rebased on master after #239 got merged

@@ -169,14 +169,15 @@ impl SimplicityEncode for SimplicityCtx8 {
.iter()
.flat_map(|x| x.to_be_bytes())
.collect::<Vec<u8>>();
let mid_state = Value::u256_from_slice(&arr);
debug_assert_eq!(arr.len(), 32);
let mid_state = Value::power_of_two(&arr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

In c1527fa:

I'm confused as to what you're doing here. In the previous version of this commit you used Value::u256 because this is guaranteed to be 32 bytes. But now you are just adding another runtime assertion. And this still doesn't touch the unnecessary Vec in the line above.

Copy link
Collaborator Author

@uncomputable uncomputable Jul 27, 2024

Choose a reason for hiding this comment

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

I can convert [u32; 8] directly into [u8; 32] if you want. The code will be more verbose because I will have to initialize the array and then assign values byte by byte. I cannot use Rust's iterator API, AFAIK.

I misunderstood your original comment. I thought you called the Vec unnecessary because I converted it into an [u8; 32] array on the stack. I removed the array, but you seem to have wanted me to remove the Vec altogether.

If we create a Value from &[u8; 32] then we assert the length of the
slice at compile time and cannot fail at runtime. Similar for &[u8; 64].
This is similar to rust-bitcoin's from_byte_array with the difference
that Value takes the bytes by reference.

It turns out, in rust-simplicity we can simply convert every call of
{u256, u512}_from_slice to a call of {u256, u512} without problem.
In the jets-bench subcrate, we have to convert [u32; 8] to [u8; 32]
or &[u8; 33] to &[u8; 32] via try_into. I think this is still worth
doing, and we can see in the code that these conversions will never fail.

Keep {u256, u512}_from_slice for backwards compatability.
I don't think we need these methods any more. A caller with an
arbitrarily-sized slice can use Value::power_of_two. A caller with a
precisely-sized slice can use the safer Value::{u256, u512}.

We can remove this commit from the PR if it turns out that we need
{u256, u512}_from_slice for some reason.
@uncomputable uncomputable force-pushed the 2024-07-value-refactor branch from f308d5e to 85fd5b3 Compare July 27, 2024 08:24
@uncomputable
Copy link
Collaborator Author

Removed the unnecessary vector.

@apoelstra
Copy link
Collaborator

Ok, awesome. ACK 85fd5b3 except that I'd prefer that these new functions took arrays by value, not by reference. It is almost certainly slower, and more annoying for the programmer, to be passing 32-byte objects around by reference.

@uncomputable uncomputable merged commit da16118 into BlockstreamResearch:master Jul 27, 2024
16 checks passed
@uncomputable uncomputable deleted the 2024-07-value-refactor branch July 27, 2024 22:36
@apoelstra
Copy link
Collaborator

I did not actually test this or use the github "approve" button. I did not intend my comment to be read as an ACK.

@uncomputable
Copy link
Collaborator Author

uncomputable commented Jul 28, 2024

The github-merge script from the bitcoin maintainer tools interpreted the comment as an ACK. Sorry for that. I will open a fixup PR to pass the 32 / 64 bytes by value.

@uncomputable uncomputable mentioned this pull request Jul 28, 2024
@apoelstra
Copy link
Collaborator

No worries -- I shouldn't have written ACK in all caps so that the script wouldn't pick it up. And because this is such a minor thing I should've been clearer that I wanted you to respond to it before merging.

uncomputable added a commit that referenced this pull request Jul 29, 2024
5c6a26f refactor: Rename power_of_two -> from_byte_array (Christian Lewe)
3df9475 feat: Pass byte arrays by value to construct Value (Christian Lewe)

Pull request description:

  Fixes outstanding issues of #237 which I failed to address before merging.

ACKs for top commit:
  apoelstra:
    ACK 5c6a26f nice\!

Tree-SHA512: 9ab3acc83b5040c9c5a839682d4eb06e7b23bd91fb23a62cdec27433a34477d5b49c3b932822b180ea254022513ca458a1ca15d8f22873da767f719cd2cbcba2
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.

2 participants