Skip to content

Latest commit

 

History

History
31 lines (19 loc) · 4.79 KB

2022-05-18-#24148-2.md

File metadata and controls

31 lines (19 loc) · 4.79 KB

This is a 2-part Review Club for PR by Antoine Poinsot which introduces Miniscript support for Output Descriptors. In this second part participants focused on the Miniscript Output Descriptor implementation.

Questions

Which function is responsible for parsing the output descriptor strings? How does it determine whether the string represents a MiniscriptDescriptor, instead of any other type (including a WSHDescriptor) 🔗

bonus: What's the behaviour of Func("func_name", expr) that is used quite frequently in ParseScript? Are there side effects? 🔗
  • If the func_name and a parenthesis wrapper is found in expr, they get removed from expr and Func returns true. If it is not found, Func returns false and expr remains unchanged.
  • This is usefull to remove wrappers, e.g. expr="wsh(pk(...))", Func("wsh", expr) would change expr to (pk(...)).

Does MiniscriptDescriptor accept Miniscript policy or Miniscript or both? 🔗

  • The PR just doesn't include a policy compiler.

Node<Key>::ContainsDuplicateKey returns a bool. What is the return type of TreeEvalMaybe<std::set<Key>>(upfn), and how does it get cast to a bool?

  • TreeEvalMaybe returns an std::optional<Result>, where Result is a templated typename. Per https://en.cppreference.com/w/cpp/utility/optional: when cast to a bool, std::optional becomes true if the object contains a value and false if it does not contain a value (std::nullopt).

When choosing between two available satisfactions, why should the one that involves less or no signatures be preferred? For example, consider the policy or(and(older(21), pk(B)), thresh(2, pk(A), pk(B))) which can always be spent when both A and B sign, and can be spent after 21 blocks when just B signs. After 21 blocks, both satisfactions are available, but why would the satisfaction that involves just B’s signature be preferable? 🔗

  • An initial thought could be less signatures -> less witness data -> smaller tx -> less fees to pay, but that's not always the case. Imagine a situation where you have the choice between two satisfaction paths. One involves no signatures, but is bigger. One involves signature but is smaller. You should still prefer the bigger, no signatures one. Why?
  • It has to do with third-party malleability, the ability for someone not participating in the tx (not holding the required keys to sign) to modify the witness of a transaction. Witness data is not covered by signatures, so third parties (e.g. when relaying a tx) can change this at will. In most cases, this will make the tx invalid because the witness doesn't satisfy the scriptPubKey anymore, but there are cases where the witness remains valid even after it is modified.
  • So you need third parties not being able to change which satisfaction path was used. In our scenario, if the second branch is satisfied thresh(2, pk(A), pk(B)), a third party can malleate the satisfaction by removing the signature for A and force the script to go through the first path since having the signature for B is enough. However, the other way around is not possible. If you only announce A, the third party couldn't possibly drop B.
  • A third party can't add signatures but can drop them. So if the honest signers use a construction with a "redundant" signature, even if it is smaller, third parties can mutate it into the bigger no-sig variant.