-
Notifications
You must be signed in to change notification settings - Fork 908
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
psbt: fix PSBT mutation in the changeset #6762
psbt: fix PSBT mutation in the changeset #6762
Conversation
1a61116
to
e5dd379
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Real fix is to fix linearize_inputs
so that it doesn't delete data...
common/psbt_open.c
Outdated
// This behavior also caused issues with a different hsmd, as documented in: | ||
// https://github.com/ElementsProject/lightning/issues/6672 | ||
orig_deep_copy = clone_psbt(tmpctx, orig); | ||
cs = psbt_get_changeset(tmpctx, orig_deep_copy, new); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better fix would be to update linearize_input
so that it doesn't mutate the inputs; that'll fix it for all calling paths rather than this one.
see
#6672 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@niftynei looking at linearize_input
on master
-
Lines 66 to 74 in e1ac241
psbt->inputs[0] = *in; | |
psbt->num_inputs++; | |
/* Sort the inputs, so serializing them is ok */ | |
wally_map_sort(&psbt->inputs[0].unknowns, 0); | |
/* signatures, keypaths, etc - we dont care if they change */ | |
wally_psbt_input_set_final_witness(&psbt->inputs[0], NULL); |
I see:
psbt->inputs[0] = *in;
- that makes a copy of the input struct bytes, copying any pointers without copying underlying memorywally_psbt_input_set_final_witness(&psbt->inputs[0], NULL);
- this uses theSET_STRUCT
macro, which in turn frees the memory originally pointed to. as far as I understand, this results in a dangling pointer in the original input struct.- there's also the
/* Hide the inputs we added
comment below, but it's too late by that time
so I'm actually not sure why the code in master
doesn't just crash.
but in any case, a potential fix to this and the unwanted mutation may be to do psbt->inputs[0].final_witness = NULL
, so the original memory is not touched. and the same for the other four calls of the form wally_psbt_input_set_*()
Yes, I put this in my FIXME comment, because I think the only way is cloning psbt inputs that get sorted in I am missing somethings? @niftynei |
98e64e8
to
ac109ee
Compare
I think the following change (instead) minimizes the restructuring risk by isolating the workaround to a single case: @@ -933,18 +933,25 @@ openchannel2_signed_deserialize(struct openchannel2_psbt_payload *payload,
fatal("Plugin supplied PSBT that's missing required fields. %s",
type_to_string(tmpctx, struct wally_psbt, psbt));
+ /* NOTE - The psbt_contribs_changed function nulls lots of
+ * fields in place to compare the PSBTs. This removes the
+ * witness stack held in final_witness. Give it a clone of
+ * the PSBT to hack on instead ... */
+ struct wally_psbt *psbt_clone;
+ psbt_clone = clone_psbt(tmpctx, psbt);
+
/* Verify that inputs/outputs are the same. Note that this is a
* 'de minimus' check -- we just look at serial_ids. If you've
* totally managled the data here but left the serial_ids intact,
* you'll get a failure back from the peer when you send
* commitment sigs */
- if (psbt_contribs_changed(payload->psbt, psbt))
+ if (psbt_contribs_changed(payload->psbt, psbt_clone))
fatal("Plugin must not change psbt input/output set. "
"orig: %s. updated: %s",
type_to_string(tmpctx, struct wally_psbt,
payload->psbt),
type_to_string(tmpctx, struct wally_psbt,
- psbt));
+ psbt_clone));
if (payload->psbt)
tal_free(payload->psbt); |
common/psbt_open.c
Outdated
@@ -494,20 +494,31 @@ bool psbt_output_to_external(const struct wally_psbt_output *output) | |||
return !(!result); | |||
} | |||
|
|||
bool psbt_contribs_changed(struct wally_psbt *orig, | |||
bool psbt_contribs_changed(const struct wally_psbt *orig, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think both arguments to psbt_contribs_changed
should be const. They are linearized internally to facilitate normalized comparison, but I don't think a caller would expect either argument to be modified.
Specifically, VLS is having trouble with the 2nd argument being modified, not the first so this fix won't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I put this as FIXME because we should change some logic down.
An easy solution is to clone the input and output while we are sorting, without cloning all the PSBT
15c3fb5
to
968b3b4
Compare
During the changeset calculation after the `openchannel2_sign` hook. So this commit patch the problem with the following change: - Addressed an issue where `psbt_get_changeset` was modifying the original PSBT unnecessarily. - This modification led to problems with a different hsmd, as referenced in [Issue ElementsProject#6672](ElementsProject#6672). - Noted a potential optimization where only a subpart of the PSBT needs to be cloned, as the mutation is specific to inputs. Link: ElementsProject#6672 Reported-by: @devrandom Suggested-by: Ken Sedgwick <[email protected]> Co-Developed-by: Ken Sedgwick <[email protected]> Signed-off-by: Vincenzo Palazzo <[email protected]>
968b3b4
to
0ace4c6
Compare
Agree we should fix linearize, but this at least fixes the immediate problem. And we don't have clone functions for inputs, so caller needs to do this for now :( |
I will work on libwally for this but I think it takes some time |
During the changeset calculation after the
openchannel2_sign
hook.So this commit patches the problem with the following change:
psbt_get_changeset
was modifying the original PSBT unnecessarily.Fixes: #6672