Tr compiler v3 - Incremental Enumerative Compiler#418
Tr compiler v3 - Incremental Enumerative Compiler#418sanket1729 merged 2 commits intorust-bitcoin:masterfrom
Conversation
thresh-enumerationthresh-enumeration
cb5cf91 to
3d473c9
Compare
src/policy/concrete.rs
Outdated
| )), | ||
| _ => { | ||
| let (internal_key, policy) = self.clone().extract_key(unspendable_key)?; | ||
| policy.check_tapleaf()?; |
There was a problem hiding this comment.
Should update the name of the function. This implies that we can checking something on tapleafs. Perhaps, check_num_tapleaves?
I would prefer to inline the check_num_tapleaves here, but up to you.
There was a problem hiding this comment.
Yes, the function name is a misnomer. Will change the name as suggested.
src/policy/concrete.rs
Outdated
| /// Check on the number of TapLeaves | ||
| #[cfg(feature = "compiler")] | ||
| fn check_tapleaf(&self) -> Result<(), Error> { | ||
| if self.num_tap_leaves() > 100_000 { |
There was a problem hiding this comment.
Make this is local constant MAX_COMPILATION_TAP_LEAVES
| #[cfg(feature = "compiler")] | ||
| fn check_tapleaf(&self) -> Result<(), Error> { | ||
| if self.num_tap_leaves() > 100_000 { | ||
| return Err(errstr("Too many Tapleaves")); |
There was a problem hiding this comment.
Let's use a dedicated error variant instead of errstr
There was a problem hiding this comment.
This is still not addressed.
src/policy/concrete.rs
Outdated
| Ok(node) | ||
|
|
||
| #[cfg(feature = "compiler")] | ||
| fn combination(n: usize, k: usize) -> usize { |
There was a problem hiding this comment.
Whenever we call this, we need to make sure that we are having an overflow.
There was a problem hiding this comment.
This function isn't supposed to be there. Seems I messed up while squashing the commits, my bad!
src/policy/concrete.rs
Outdated
| fn num_tap_leaves(&self) -> usize { | ||
| match self { | ||
| Policy::Or(subs) => subs.iter().map(|(_prob, pol)| pol.num_tap_leaves()).sum(), | ||
| Policy::Threshold(k, subs) if *k == 1 => combination(subs.len(), *k), |
There was a problem hiding this comment.
What happens when there is overflow here? We should use all the checked_sum, checked_mul variants here to check for this. Return Option where we return None when there is overflow
| match *self { | ||
| match self { | ||
| Policy::Or(ref subs) => { | ||
| let total_odds: usize = subs.iter().map(|(ref k, _)| k).sum(); |
There was a problem hiding this comment.
As in, remove the ref . It should clean up * (*k) code in the next line
src/policy/concrete.rs
Outdated
| .collect::<Vec<_>>() | ||
| } | ||
| ref x => vec![(prob, x.clone())], | ||
| // Instead of the fixed-point algorithm, consider direct k-choose-n split if limits |
There was a problem hiding this comment.
I don't see why this comment is relevant here. This function is only splitting ors AFAIU.
src/policy/concrete.rs
Outdated
| /// Given a [`Policy`], return a vector of policies whose disjunction is isomorphic to the initial one. | ||
| /// This function is supposed to incrementally expand i.e. represent the policy as disjunction over | ||
| /// sub-policies output by it. The probability calculations are similar as | ||
| /// [to_tapleaf_prob_vec][`Policy::to_tapleaf_prob_vec`] |
There was a problem hiding this comment.
Why do you have the link twice?
src/policy/concrete.rs
Outdated
| Policy::Or(subs) => { | ||
| let total_odds = subs.iter().fold(0, |acc, x| acc + x.0); | ||
| subs.iter() | ||
| .map(|(odds, pol)| (prob * *odds as f64 / total_odds as f64, pol.clone())) |
There was a problem hiding this comment.
Should this not be recursive?
src/policy/concrete.rs
Outdated
| Policy::Threshold(k, subs) if *k == 1 => { | ||
| let total_odds = subs.len(); | ||
| subs.iter() | ||
| .map(|pol| (prob / total_odds as f64, pol.clone())) |
3d473c9 to
788a03b
Compare
sanket1729
left a comment
There was a problem hiding this comment.
code logic ACK, but would need some re-factors that will make it faster
src/miniscript/limits.rs
Outdated
| pub const MAX_PUBKEYS_PER_MULTISIG: usize = 20; | ||
|
|
||
| /// Maximum TapLeafs allowed in a compiled TapTree | ||
| pub(crate) const MAX_COMPILATION_LEAVES: usize = 10_000; |
There was a problem hiding this comment.
These constants are constants related to consensus standardness limits of bitcoin and are not specific to rust-miniscript. We should move MAX_COMPILATION_LEAVES to compiler.rs
There was a problem hiding this comment.
Should we move it to concrete.rs since that's where the tr compiler is?
src/policy/concrete.rs
Outdated
| /// any one of the conditions exclusively. | ||
| #[cfg(feature = "compiler")] | ||
| fn generate_combination<Pk: MiniscriptKey>( | ||
| policy_vec: &Vec<Policy<Pk>>, |
There was a problem hiding this comment.
We should use Rc instead of cloning it here multiple times. This should help in space and time complexity
There was a problem hiding this comment.
We would need a new data structure with Arc's here to store these instead of Policy. But we do not want so many clones here. This might be why everything is slow.
You can create something similar to Policy but with Arcs instead of Owned sub-policies.
1355757 to
fee0f7c
Compare
|
@sanket1729 I've added a new structure |
sanket1729
left a comment
There was a problem hiding this comment.
mostly ACK. found a bug when dealing with more than MAX_COMPILATION_LEAVES part.
See the last commit here https://github.com/sanket1729/rust-miniscript/tree/pr418.
We are really close to merging this. I think you would run in --release mode to see the performance difference.
fee0f7c to
a4cf8b5
Compare
src/policy/concrete.rs
Outdated
| } | ||
|
|
||
| // --- Sanity Checks --- | ||
| if enum_len > MAX_COMPILATION_LEAVES || *curr_policy == PolicyArc::Unsatisfiable { |
There was a problem hiding this comment.
We do not enumerate the sub-policy under consideration since we either exceed MAX_COMPILATION_LEAVES or the policy itself compiled to Unsatisfiable.
There was a problem hiding this comment.
This was causing bugs because the enumeration was incorrect. I think the logic here would need to be improved. If you replace thresh(51,...) with thresh(49) you would see a crash
There was a problem hiding this comment.
This was a major bug. I've fixed it in the 9c8a1c3.
thresh-enumerationa4cf8b5 to
2186b09
Compare
| #[cfg(feature = "compiler")] | ||
| fn check_tapleaf(&self) -> Result<(), Error> { | ||
| if self.num_tap_leaves() > 100_000 { | ||
| return Err(errstr("Too many Tapleaves")); |
There was a problem hiding this comment.
This is still not addressed.
src/policy/concrete.rs
Outdated
| if enum_len > MAX_COMPILATION_LEAVES || *curr_policy == PolicyArc::Unsatisfiable { | ||
| // Root-level enumeration exceeds the limit, so push back the initial policy | ||
| if ret.is_empty() { | ||
| ret.push((1.0, arc_self)); |
There was a problem hiding this comment.
This is not the expected behavior. We need to split as much as we can until we hit the limit.
There was a problem hiding this comment.
The variable enum_len stores the vector length if we consider the enumeration of plausible node. If this exceeds limit, we don't replace the initial plausible sub-policy by its enumerations (which is done after the check). I just handled the base-case where the root-level enumeration itself exceeds the limit, where we just return the policy itself.
a7b1e82 to
71e4f81
Compare
71e4f81 to
f9901ab
Compare
sanket1729
left a comment
There was a problem hiding this comment.
ACK f9901ab. Can you also rebase to latest master? I think we are good to go here
|
Unless @kanishk779 found something else in review here. |
f9901ab to
265b063
Compare
|
I will wait a couple of days for @kanishk779 to respond. Will merge this later |
|
@SarcasticNastik , can you also update the PR description? |
|
@SarcasticNastik , sorry for this. But I promise, this would be last rebase |
265b063 to
55b48fc
Compare
55b48fc to
97de242
Compare
3f451db Release 8.0.0 (sanket1729) Pull request description: Draft release PR. Still blocked on reviews of 1) #418 2) #450 3) #461 ACKs for top commit: apoelstra: ACK 3f451db Tree-SHA512: aa455fd57a894b1edb49b6273126a05c9d0897ca50ee572fa8a59b4d2a96e2013f2ed9ec4b96cd5e449ba5b5ee6bd32aa57da110df69bd35b8a970ccb1440002
…022_10 51d66d1 Merge rust-bitcoin/rust-miniscript#418: Tr compiler v3 - Incremental Enumerative Compiler
…Enumerative Compiler
97de242709178f2c75c8bffbe44718356aae1e71 Implement tr-compiler-v3 enumeration compiler (Aman Rojjha)
7d5374f223687d01b82412f0da80ef407c0ad745 Limit the number of tap-leaves output by the `tr_compiler` (Aman Rojjha)
Pull request description:
This PR is a follow-up in the Tr-compiler series. This introduces splitting of a `thresh(k, ...n...)` policy into different Tapleaves.
> For now, kindly refer to the code documentation and comments for the strategy implemented
ACKs for top commit:
sanket1729:
ACK 97de242709178f2c75c8bffbe44718356aae1e71
Tree-SHA512: dfa4517bb211e329e57dd237998e8df219cdf6208f8ec2cb3f2f4f9cf8934f272fb611f3b52dc1ad080918ddbc4fbd3ffb506812f02fa536239402a62683552d
This PR is a follow-up in the Tr-compiler series. This introduces splitting of a
thresh(k, ...n...)policy into different Tapleaves.