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

Remove WitnessNode #265

Merged

Conversation

uncomputable
Copy link
Collaborator

@uncomputable uncomputable commented Feb 7, 2025

Remove WitnessNode by merging its code with the nearly identical ConstructNode.

@uncomputable uncomputable force-pushed the 2025-02-remove-witness-node branch from dfd1516 to d80f52b Compare February 10, 2025 12:36
@uncomputable uncomputable marked this pull request as ready for review February 10, 2025 12:36
@uncomputable
Copy link
Collaborator Author

Rebased on master

@apoelstra
Copy link
Collaborator

In ce012c5:

I'm really confused by the claim that you can remove an error variant by just putting incorrect data into the program. Can you elaborate why this is reasonable?

@apoelstra
Copy link
Collaborator

Oh, I see, this is only in the SimpleFinalizer which is basically a test-only structure which can already easily be cajoled into putting invalid data into a program. Yeah, we definitely shouldn't have error variants in the top-level Error enum that are only used by this thing.

@uncomputable
Copy link
Collaborator Author

uncomputable commented Feb 10, 2025

putting incorrect data into the program

My approach is to insert reasonable default data into a program during finalization. The data does not change the CMR of the program. The user will see how the program fails on the Bit Machine and be able to make adjustments based on that.

The underlying idea is that Simplicity development will involve frequent running of the Bit Machine. We should strive to make these execution errors as helpful as possible and we should make it as easy as possible to create a program that can be run (reducing error paths during finalization).

@apoelstra
Copy link
Collaborator

My approach is to insert reasonable default data into a program during finalization. The data does not change the CMR of the program. The user will see how the program fails on the Bit Machine and be able to make adjustments based on that.

It's not "reasonable default data". It's unremarkable, possibly-valid data that was put into a program without the user's knowledge and will result in incredibly confusing errors. The user will not "see how the program fails on the Bit Machine". If they are lucky the program will fail at all, and then they will need to sift through their witness data and find the magic zero bits that were fabricated by this library.

I agree that we should strive to make debugging and errors as simple as possible. I do not believe that it will ever be possible for debugging to be so simple that it's OK for the development toolchain to be silently inserting bad data into real programs.

It's fine if this is test-only code or code that we intend to rip out. (As noted in its doccomment, this finalizer already does no type-checking even though this is now easily possible with our API, and it also can't handle disconnect, and it doesn't attempt any pruning, etc etc). But if you are saying that this is something you seriously want to do, then NACK.

@uncomputable
Copy link
Collaborator Author

uncomputable commented Feb 10, 2025

I'm surprised by the backlash since the idea of reducing error paths during finalization is a continuation from the zero values from #259. In a test program, made-up default values might make a program run on the Bit Machine, but if the same happens in a production program then your program is insecure. The library will never accidentally make up a valid signature, etc. But yeah, it would be good to make sure the program takes the spending paths that the user intended.

In any case, this PR only touches SimpleFinalizer which is used in unit tests. The merger of WitnessNode into CommitNode has nothing to do with finalization error handling.

@apoelstra
Copy link
Collaborator

The zero values in #259 are only used in places where we expect that they will never be visible to the user (because they will be converted to hidden nodes and deleted). There is a giant block comment explaining this. And furthermore, I had hoped that we would be able to get rid of this once we had hidden nodes again.

@apoelstra
Copy link
Collaborator

Can you add a block comment to the SimpleFinalizer saying that this finalizer is only expected to be used for tests and demos, that synthesizing dummy data inside a finalizer is not reasonable production behavior, and that we will revisit this at some point in the future?

We can remove an error path by using the respective zero value as
default witness value.
The difference between ConstructNode and WitnessNode was always
confusing.

ConstructNode came earlier and was used mostly for decoding programs.
Its witness nodes were always empty because there are no witness
values during decoding.

WitnessNode was added later for creating satisfied Simplicity policies.
Its witness nodes were potentially filled (Option<Value>) because a
witness value might exist (satisfied fragment) or not exist (unsatisfied
fragment).

The code base for ConstructNode and for WitnessNode is almost identical.
Small changes make both identical and allow us to remove one of them.

In this commit, we set <Construct as Marker>::Witness to Option<Value>
and by copy over the finalization code from WitnessNode. We replace all
code occurrences of `Witness*` with `Construct*`. Finally, we delete
src/node/witness.rs entirely.
@uncomputable uncomputable force-pushed the 2025-02-remove-witness-node branch from d80f52b to 61b7ddc Compare February 10, 2025 18:11
@uncomputable
Copy link
Collaborator Author

I added a disclaimer to SimpleFinalizer that is should not be used in production and why.

I will use Hiding to handle missing paths during finalization in a follow-up PR. That doesn't introduce unexpected default values.

Copy link
Collaborator

@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 61b7ddc; successfully ran local tests

@apoelstra apoelstra merged commit 7da0f37 into BlockstreamResearch:master Feb 10, 2025
16 checks passed
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