Repository navigation
Guard Tower Redux: Initial interface and struct setups for distributed key generation #43
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
Changes from 9 commits
7c9ad0c
419ec50
143c1ef
b5dbf55
2e4736a
7d2c928
843c7f0
b94058d
516e738
140a537
cb13084
dd1f708
33b1378
6a8fe19
8522f27
cd26017
b8668f7
c535ee4
045ce6e
0aee2d2
1ee6a47
e65c985
cc4102d
9465aaf
85696af
15a5f0c
e843d85
68c8f86
b6c1c4c
37bce33
172c705
af952f5
5a7f8d3
a1ab316
e929c6b
9d39e7d
cfbc53b
9856a92
a2e14f4
5b11a83
657281f
1b15f8b
ccff34d
a084385
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| package broadcast | ||
|
|
||
| import ( | ||
| "sync" | ||
|
|
||
| "github.com/dfinity/go-dfinity-crypto/bls" | ||
| ) | ||
|
|
||
|
|
@@ -41,28 +43,33 @@ type Channel interface { | |
| } | ||
|
|
||
| type localChannel struct { | ||
| name string | ||
| recvChans []chan Message | ||
| name string | ||
| recvChansMutex sync.Mutex | ||
| recvChans []chan Message | ||
| } | ||
|
|
||
| func (channel *localChannel) Name() string { | ||
| return channel.name | ||
| } | ||
|
|
||
| func (channel *localChannel) Send(message Message) bool { | ||
| channel.recvChansMutex.Lock() | ||
| go func(recvChans []chan Message) { | ||
| for _, recvChan := range recvChans { | ||
| recvChan <- message | ||
| } | ||
| }(channel.recvChans) | ||
| channel.recvChansMutex.Unlock() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This lock may potentially get let go before the go routine finishes executing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mmm… Which is not fine. I meant it to be fine because we snapshot |
||
|
|
||
| return true | ||
| } | ||
|
|
||
| func (channel *localChannel) RecvChan() <-chan Message { | ||
| newChan := make(chan Message) | ||
| newChan := make(chan Message, 62500) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's this number?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 250*250, or roughly the number of total expected private share messages we're throwing around during private share exchange with a 250-member group. I don't think it actually needs to be this high, but I didn't want to waste further time on figuring out a better number since this is really just for local smoke testing. |
||
|
|
||
| channel.recvChansMutex.Lock() | ||
| channel.recvChans = append(channel.recvChans, newChan) | ||
| channel.recvChansMutex.Unlock() | ||
|
|
||
| return newChan | ||
| } | ||
|
|
@@ -73,5 +80,5 @@ func (channel *localChannel) RecvChan() <-chan Message { | |
| // that is returned to the caller, so that all receive channels can receive | ||
| // the message. | ||
| func LocalChannel(name string) Channel { | ||
| return &localChannel{name, make([]chan Message, 0)} | ||
| return &localChannel{name, sync.Mutex{}, make([]chan Message, 0)} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you don't need the sync.Mutex (unless you'd like us to be very explicit)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't feel super-strongly, but the other option was to use named parameters (that is, I can't just leave the parameter off as the compiler will choke). I just did the thing that looked easiest, tbh.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a simple slice (not a slice of slices, right?) - so you can drop the zero
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't believe that's true. Slices need an initial length. Compiler seems to agree:
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. mhmm, good to know, thanks. |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,7 +53,7 @@ func (counter *localBlockCounter) BlockWaiter(numBlocks int) <-chan int { | |
| } | ||
|
|
||
| func (counter *localBlockCounter) count() { | ||
| ticker := time.NewTicker(time.Duration(time.Second / 2)) | ||
| ticker := time.NewTicker(time.Duration(500 * time.Millisecond)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've got a bad habit of doing this too - but I think we should start documenting our tick durations and timeouts. Why do we choose these numbers and where can they be tuned from? What are the consequences of going with these numbers? I only bring this up because this isn't like saying "on every tick" which is essentially like saying "every second". This is saying every "half-tick"
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anything under |
||
|
|
||
| for _ = range ticker.C { | ||
| counter.structMutex.Lock() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,29 +46,31 @@ type JustificationsMessage struct { | |
| justifications map[bls.ID]bls.SecretKey | ||
| } | ||
|
|
||
| // Execute runs the full distributed key generation lifecycle, given a broadcast | ||
| // channel to mediate it and a group size and threshold. It returns a threshold | ||
| // group member who is participating in the group if the generation was | ||
| // successful, and an error representing what went wrong if not. | ||
| // ExecuteDKG runs the full distributed key generation lifecycle, given a | ||
| // broadcast channel to mediate it and a group size and threshold. It returns a | ||
| // threshold group member who is participating in the group if the generation | ||
| // was successful, and an error representing what went wrong if not. | ||
| func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, groupSize int, threshold int) (*thresholdgroup.Member, error) { | ||
| // FIXME Probably pass in a way to ask for a receiver's public key? | ||
| // FIXME Need a way to time out in a given stage, especially the waiting | ||
| // ones. | ||
|
|
||
| memberID := rand.NewRand().String() | ||
| memberID := "0" | ||
| for memberID = rand.NewRand().String(); memberID == "0"; { | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, I'm not sure I understand what's going here and why we've got an empty for block
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I'll add a comment. We're just trying to make sure we don't generate a 0 member ID, and
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahhhh, now I see that, interesting. Yeah, that's the right way to do that. Comment will help. |
||
| fmt.Printf("[member:%v] Initializing member.\n", memberID) | ||
| localMember := thresholdgroup.NewMember(memberID, threshold) | ||
|
|
||
| recvChan := channel.RecvChan() | ||
|
|
||
| fmt.Printf("[member:%v] Waiting for join timeout...\n", memberID) | ||
| blockCounter.WaitForBlocks(5) | ||
| blockCounter.WaitForBlocks(15) | ||
|
|
||
| fmt.Printf("[member:%v] Broadcasting join.\n", memberID) | ||
| channel.Send(broadcast.NewBroadcastMessage(localMember.BlsID, JoinMessage{})) | ||
|
|
||
| // Wait for all members. | ||
| waiter := blockCounter.BlockWaiter(3) | ||
| waiter := blockCounter.BlockWaiter(10) | ||
| fmt.Printf("[member:%v] Waiting for other members...\n", memberID) | ||
| memberIDs, err := waitForMemberIDs(&localMember.BlsID, recvChan, groupSize) | ||
| if err != nil { | ||
|
|
@@ -78,7 +80,9 @@ func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, grou | |
| fmt.Printf("[member:%v] Waiting for member join timeout...\n", memberID) | ||
| <-waiter | ||
|
|
||
| waiter = blockCounter.BlockWaiter(3) | ||
| fmt.Printf("[member:%v] Saw IDs: %v\n", memberID, len(memberIDs)) | ||
|
|
||
| waiter = blockCounter.BlockWaiter(15) | ||
| fmt.Printf("[member:%v] Initiating commitment broadcast phase.\n", memberID) | ||
| sharingMember := localMember.InitializeSharing(memberIDs) | ||
|
|
||
|
|
@@ -97,7 +101,7 @@ func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, grou | |
| fmt.Printf("[member:%v] Waiting for commitment timeout...\n", memberID) | ||
| <-waiter | ||
|
|
||
| waiter = blockCounter.BlockWaiter(5) | ||
| waiter = blockCounter.BlockWaiter(20) | ||
| fmt.Printf("[member:%v] Sending private shares.\n", memberID) | ||
| err = sendShares(channel, &sharingMember) | ||
| if err != nil { | ||
|
|
@@ -113,7 +117,7 @@ func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, grou | |
| fmt.Printf("[member:%v] Waiting for share exchange timeout...\n", memberID) | ||
| <-waiter | ||
|
|
||
| waiter = blockCounter.BlockWaiter(3) | ||
| waiter = blockCounter.BlockWaiter(15) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I take it these numbers are for demo/illustrative purposes and we'll be ripping things out from here later?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yah, see above. |
||
| fmt.Printf("[member:%v] Initiating accusation/justification phase.\n", memberID) | ||
| justifyingMember := sharingMember.InitializeJustification() | ||
| fmt.Printf("[member:%v] Broadcasting accusations.\n", memberID) | ||
|
|
@@ -123,7 +127,7 @@ func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, grou | |
| } | ||
|
|
||
| fmt.Printf("[member:%v] Waiting for other accusations...\n", memberID) | ||
| err = waitForAccusations(recvChan, &justifyingMember) | ||
| err = waitForAccusations(&justifyingMember.BlsID, recvChan, &justifyingMember) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to receive all accusations: [%v]", err) | ||
| } | ||
|
|
@@ -138,7 +142,7 @@ func ExecuteDKG(blockCounter chain.BlockCounter, channel broadcast.Channel, grou | |
| } | ||
|
|
||
| fmt.Printf("[member:%v] Waiting for other justifications...\n", memberID) | ||
| err = waitForJustifications(recvChan, &justifyingMember) | ||
| err = waitForJustifications(&justifyingMember.BlsID, recvChan, &justifyingMember) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to receive all justifications: [%v]", err) | ||
| } | ||
|
|
@@ -197,11 +201,12 @@ done: | |
| } | ||
|
|
||
| func sendShares(channel broadcast.Channel, member *thresholdgroup.SharingMember) error { | ||
| fmt.Printf("[member:%v] Despatching shares!\n", member.ID) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We sure are! |
||
| for _, receiverID := range member.OtherMemberIDs() { | ||
| share := member.SecretShareForID(receiverID) | ||
| fmt.Printf("[member:%v] Despatching a share!\n", member.ID) | ||
| channel.Send(broadcast.NewPrivateMessage(member.BlsID, receiverID, MemberShareMessage{share})) | ||
| } | ||
| fmt.Printf("[member:%v] Shares despatched!\n", member.ID) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Boom! 🎉 |
||
|
|
||
| return nil | ||
| } | ||
|
|
@@ -212,7 +217,6 @@ done: | |
| switch shareMsg := msg.Data.(type) { | ||
| case MemberShareMessage: | ||
| if msg.Receiver.IsEqual(myID) { | ||
| fmt.Printf("[member:%v] Received one id from [%v].\n", myID.GetHexString(), msg.Sender.GetHexString()) | ||
| sharingMember.AddShareFromID(msg.Sender, shareMsg.Share) | ||
|
|
||
| if sharingMember.SharesComplete() { | ||
|
|
@@ -231,13 +235,17 @@ func sendAccusations(channel broadcast.Channel, member *thresholdgroup.Justifyin | |
| return nil | ||
| } | ||
|
|
||
| func waitForAccusations(recvChan <-chan broadcast.Message, justifyingMember *thresholdgroup.JustifyingMember) error { | ||
| func waitForAccusations(myID *bls.ID, recvChan <-chan broadcast.Message, justifyingMember *thresholdgroup.JustifyingMember) error { | ||
| memberIDs := justifyingMember.OtherMemberIDs() | ||
| seenAccusations := make(map[bls.ID]bool, len(memberIDs)) | ||
| done: | ||
| for msg := range recvChan { | ||
| switch accusationMsg := msg.Data.(type) { | ||
| case AccusationsMessage: | ||
| if msg.Sender.IsEqual(myID) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we are the sender of this message, move on (ie. avoid the loopback case)
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notably, we'll ultimately probably handle the “ignore messages from me” at a different level, I just needed a quick-and-dirty solution here. |
||
| continue | ||
| } | ||
|
|
||
| for _, accusedID := range accusationMsg.accusedIDs { | ||
| justifyingMember.AddAccusationFromID(msg.Sender, accusedID) | ||
| } | ||
|
|
@@ -261,13 +269,17 @@ func sendJustifications(channel broadcast.Channel, justifyingMember *thresholdgr | |
| return nil | ||
| } | ||
|
|
||
| func waitForJustifications(recvChan <-chan broadcast.Message, justifyingMember *thresholdgroup.JustifyingMember) error { | ||
| func waitForJustifications(myID *bls.ID, recvChan <-chan broadcast.Message, justifyingMember *thresholdgroup.JustifyingMember) error { | ||
| memberIDs := justifyingMember.OtherMemberIDs() | ||
| seenJustifications := make(map[bls.ID]bool, len(memberIDs)) | ||
| done: | ||
| for msg := range recvChan { | ||
| switch justificationsMsg := msg.Data.(type) { | ||
| case JustificationsMessage: | ||
| if msg.Sender.IsEqual(myID) { | ||
| continue | ||
| } | ||
|
|
||
| for accuserID, justification := range justificationsMsg.justifications { | ||
| justifyingMember.RecordJustificationFromID(msg.Sender, accuserID, justification) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,7 +12,7 @@ import ( | |
| ) | ||
|
|
||
| func main() { | ||
| bls.Init(bls.CurveFp254BNb) | ||
| bls.Init(bls.CurveFp382_1) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still don't understand all these curves and what going with one vs the other means.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Though I did kick out my old number theory book and remembered that I actually know some of this stuff ;-P
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we have a full understanding yet either. The core of it is in #31 and #40 ; namely, we would like to use the curve that has optimized support for contract usage on the EVM, which was chosen for its relevance to zkSNARKs. This is actually neither of these curves, and @mhluongo is working on that piece. What I can say is that using |
||
|
|
||
| beaconConfig := chain.GetBeaconConfig() | ||
|
|
||
|
|
||
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.
nice!