Replies: 3 comments
-
cc @sanket1729 @notmandatory and also I will bring this issue up today or tomorrow during the rust-bitcoin summit in Nashville. |
Beta Was this translation helpful? Give feedback.
-
@apoelstra, I did some preliminary analysis on the binary generated by New results after removing Ctx parameter. Miniscript is still 110Kb text data compared to rust-bitcoin which is < 50 Kb (hashes + bech32 + bitcoin.) WIP Branch remove Ctx from Miniscript struct and converting that into an enum here. This is not ready for merge and tests are still not working and it is based on Jan version of miniscript. If this is not sufficient, I think having a dynamic dispatch for Pk will be useful in further reducing the size of binaries. All of the APIs are effectively compiled once for each Pk. We lose performance doing this, but maybe we have to do this :( In my small experiments, the compiler is smart enough to not include interpreter related code binary in binary if we don't use it. We don't have to worry about feature gating interperter related stuff in cfg flag, but we can do that as required. |
Beta Was this translation helpful? Give feedback.
-
Related to context object, it is great idea. As long as basic APIs for descriptors don't change, I don't mind making things harder for advanced users of Miniscript. |
Beta Was this translation helpful? Give feedback.
-
In rust-simplicity we have a context parameter that you must pass to every leaf node. We use this context object to hold a slab allocator for nodes to improve cache locality and so that we can programattically cache common constructions.
Simplicity is structurally very similar to Miniscript except that it can express arbitrary functions rather than just monotone ones, and its leaf nodes are computational primitives (the identity and unit function) rather than key/hash/time checks. In rust-simplicity we were forced to have a context object because our programs are represented as DAGs rather than trees so you can "naturally" construct cycles within the type inference logic, so we couldn't use
Arc
without our fuzzer complaining aboutleaked memory. But once we had the context object for type inference, we realized that we could also use it to slab-allocate entire nodes, eliminating the recursive representation of nodes entirely.
Miniscript does not have type inference (or rather, it has a very boring form of type inference where every expression has a unique specific type no matter where it appears), so
Arc
works fine. But by using a recursive structure containingArc<Self>
we have a number of problems:Drop
impl, necessitating theMAX_RECURSION_DEPTH
constant and the recent string of bugfixes related to that.Arc::drop
.Miniscript
type is an enum, Rust gives us a ton of constructors that can be used to construct invalid values...Arc
s.I propose that we copy the structure from rust-simplicity for Miniscript, where:
Node
type which is an opaque struct (it can still be calledMiniscript
).Inner
enum which is the public enum which users can get read-only access to, and can use to match. (Users can create their own invalidInner
s if they want but they can't convert to aMiniscript
without going through the typechecker.)Miniscript::key(pk)
which is infallible;Miniscript::and_v(&Self, &Self)
which can error if the child types are incompatible; etc etc.Context
object which contains a slab allocator for nodes and contains a non-genericBox<dyn ScriptContext>
that it uses to do correctness checks during construction. So theCtx
generic goes away across the board. To manually constructMiniscript
objects users must create this object (and they can/should create distinct ones for distinctMiniscript
s, though I think in Miniscript this doesn't matter). But theMiniscript
s will holdArc
s to their context so users don't need to keep them alive, and when parsing from strings/scripts users never see them.miniscript.post_order_iter().keys_only()
rather than needing the specializedForEachKey
trait.TranslatePk
trait with an inherentMiniscript::translate
method which takes a genericTranslator
, and which rather than returning a top-level crate::Error only returns an error if the translation results in duplicate keys (I think this the only error that can actually happen) (and I think this would fix Translator traits take up a lot of space #717). The equivalent method in Simplicity isNode::convert
but I'm hesitant to link to that since the Simplicity version is way more complicated. But for your curiosity our equivalent toTranslator
, is this trait, which has the documentation for how to use it.TL;DR I am proposing to
let ctx = Context::new()
line if they use these constructors (but if they are parsing from strings/scripts no change)Ctx
generic onMiniscript
futz with the iterator API a bitEdit After a moment's thought, I think the iterator stuff should be dropped from this discussion since it's a minor thing, not really fleshed out, and not necessary to the main proposal.
Beta Was this translation helpful? Give feedback.
All reactions