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

Add proposal Liquid tapscript case study #139

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

instagibbs
Copy link
Contributor

@instagibbs instagibbs commented Oct 31, 2019

May be interesting to include, or just keep open as a PR for visibility

The biggest chunk to digest is the weight-assigning for the k-of-k MuSig leaves.

Rationale:

Suppose you assigned all the k-of-k leaves equal weighting, leading to a near-perfect tree. Each spend would cost the same, with H-height merkle branches.

The key insight here is that in use-case considered the expectation is nearly perfect uptime for each node, therefore more than k nodes will be up and signing, so we should exploit that redundancy by putting certain nodes leaves closer to the root than others. One initial method I attempted was just to explicitly create (k+1)-of-(k+1) MuSig, (k+2)-of-(k+2) MuSig, etc, and then weight these cases with more probability to the higher-uptime case. This new method is to greedibly pick the "least overlapping" k subsets by assigning weights through brute-force counting of the "left-preferred" key subsets.

@jachiang
Copy link
Contributor

jachiang commented Oct 31, 2019

Thanks @instagibbs!

Somehow, I still get stuck on the subset computation.

Do you mind helping my understanding:

  • count has length 2^n
    • Where: 2^n is the size of the powerset of over n signers
    • (Powerset: Set of all possible subsets, 0->n)
  • We iterate from 0 to 2^n (and by extension all sets int the powerset):
    • We track the occurances of each set in count[avail]
    • Ones is the size (num of 1s of i) of the subset represented by i.
    • If the size of the set is larger k, how is avail &= avail-1 related to a reduction of ones by 1?

Cheers.

@instagibbs
Copy link
Contributor Author

If the size of the set is larger k, how is avail &= avail-1 related to a reduction of ones by 1?

bit trick https://www.geeksforgeeks.org/turn-off-the-rightmost-set-bit/

@instagibbs
Copy link
Contributor Author

your understanding seems correct

@jachiang
Copy link
Contributor

jachiang commented Oct 31, 2019

bit trick https://www.geeksforgeeks.org/turn-off-the-rightmost-set-bit/

Ah very nice, thanks @instagibbs

So as you loop through all sets in the powerset, sets which are > k, are trimmed down to k, beginning from the right side of the bit array.

  • Very interesting, so at the end the tapscripts are those of a k-of-n scheme, but with weightings derived from the assumption that when there are more than k signers available, the top k in a signer priority list take the signing duties.

Will mull it over a little more ... :)

@instagibbs
Copy link
Contributor Author

Right, you are picking(biasing the front keys) a set of weights that minimizes the "overlap" between the online signers at higher weights.

@jnewbery
Copy link
Contributor

Concept ACK. Thanks for the contribution @instagibbs!

I think it's a great idea to have external case-study contributions. I don't know where the best place for these to live is (as chapters 3.x/in a separate directory/in a different branch/something else).

My focus right now is on getting the core chapters as polished as possible, so I won't be able to review this for a while. I've had a quick look and have some high-level feedback:

  • we've added a lot of convenience functions that remove the need to add repeated code for starting nodes/generating outputs/etc. Take a look at chapter 2.0. Using those convenience functions means the chapters are entirely focused on the scenario rather than having a lot of distracting boilerplate.
  • it'd be great to have an introductory paragraph explaining the use-case. You've named the case-study 'Liquid' but there's no motivation for why you'd create a taproot output in this way. Take a look at chapter 3.1 or the case study in part 2 of chapter 2.1. Similarly, a summary at the end would be nice.
  • in general, more explanatory text between the code cells, and breaking the code up into smaller cells would help readers follow what's happening.

@jnewbery jnewbery closed this Oct 31, 2019
@jnewbery jnewbery reopened this Oct 31, 2019
@jnewbery
Copy link
Contributor

oops didn't mean to close

@instagibbs
Copy link
Contributor Author

it'd be great to have an introductory paragraph explaining the use-case

yeah that's a good idea.

I've just been gnawing on this when I don't feel like doing real work, so I'll try to clean this up with new APIs and better motivation when I can(federated hot wallet where HSMs can communicate with eachother, then offline backup where you cannot bring data back and forth).

@elichai
Copy link
Collaborator

elichai commented Nov 1, 2019

Looks pretty cool :)
Although if my calc is right your leaf generation algorithm is somewhere between n^2 and n^2*log(n). EDIT: 2^n and 2^n*C(n,k)*log(n)

I think you can do it in the following time.
Let C(n,k) be the algorithm of choosing k from n (n!/(k! * (n-k)!))
O(k)*C(n,k)

But here it's 3/5 so who cares :P

@instagibbs
Copy link
Contributor Author

instagibbs commented Nov 1, 2019 via email

@instagibbs
Copy link
Contributor Author

instagibbs commented Nov 1, 2019 via email

@elichai
Copy link
Collaborator

elichai commented Nov 1, 2019

Well, try to input n=15; k=11 :) (took on my machine ~40 seconds), and when n=17 I gave up after 2.5 minutes hehe.

while implementing an algorithm I saw that python already has an algorithm exactly for this which is roughly O(k)*C(n,k):

from itertools import combinations

n = range(17)
k = 11

a = combinations(n, k)
print(list(a))

Here 11-of-17 takes less than a second on my machine.

@instagibbs
Copy link
Contributor Author

@elichai I might be misunderstanding, but that's not a solution. That simply computes the total set of leaves, it doesn't assign weights.

@instagibbs
Copy link
Contributor Author

instagibbs commented Nov 1, 2019

To elaborate, in this model, we want to take advantage of the times when all n are up(taproot output pubkey), n-1 are up, then when n-2 are up, etc, all the way to k.

In the average case, all n are up. Sometimes 1 is down, infrequently 2 are down, and so on.

In the n-1 case, we can minimize the expected spending cost by prefering leaves that have the most unique subset of signers.

edit: Clearly, I have to work on an elevator pitch for this. It's a little frustrating to explain. Maybe I can explicitly talk about what the tree and average spend would look like with naive equal weighting? updated OP with a bit more explanation/history.

@instagibbs
Copy link
Contributor Author

Just tested randomly assigning weights for n=17. While combinations is extremely fast, the vast majority of the time appears to be the MuSig computations themselves.

@elichai
Copy link
Collaborator

elichai commented Nov 1, 2019

Ok. now I get that I misunderstood what you did :)
I'm no longer sure if/what suits this. feel free to ignore my complaints(that were mostly jokes as it's just a python example)

@bitschmidty
Copy link
Contributor

Concept ACK

I was able able to successfully run the notebooks without error.

Thanks @instagibbs !

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.

5 participants