1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| func TestE2EConcurrent(t *testing.T) { setUp("info") threshold := testThreshold
//从先前产生的testParticipants个私钥文件中读出testThreshold+1个私钥来参与 //参与多签的私钥存储于数组keys中,参与多签的partiyId存储于signPIDS中 keys, signPIDs, err := keygen.LoadKeygenTestFixturesRandomSet(testThreshold+1, testParticipants) assert.NoError(t, err, "should load keygen fixtures") assert.Equal(t, testThreshold+1, len(keys)) assert.Equal(t, testThreshold+1, len(signPIDs))
// PHASE: signing // use a shuffled selection of the list of parties for this test p2pCtx := tss.NewPeerContext(signPIDs) parties := make([]*LocalParty, 0, len(signPIDs))
errCh := make(chan *tss.Error, len(signPIDs)) //消息通道 outCh := make(chan tss.Message, len(signPIDs)) //多签结束通道 endCh := make(chan SignatureData, len(signPIDs)) //接收消息的Update updater := test.SharedPartyUpdater //要签名的数据 hash, _ := hex.DecodeString(msg)
//启动testThreshold+1的参与者 for i := 0; i < len(signPIDs); i++ { fmt.Println("parameters party id: ", signPIDs[i]) params := tss.NewParameters(p2pCtx, signPIDs[i], len(signPIDs), threshold) P := NewLocalParty(new(big.Int).SetBytes(hash), params, keys[i], outCh, endCh).(*LocalParty) //将参与者的party存储,后续接收到信息时,需传递给对应的party parties = append(parties, P) go func(P *LocalParty) { if err := P.Start(); err != nil { errCh <- err } }(P) }
var ended int32 signing: for { // fmt.Printf("ACTIVE GOROUTINES: %d\n", runtime.NumGoroutine()) select { case err := <-errCh: common.Logger.Errorf("Error: %s", err) assert.FailNow(t, err.Error()) break signing
case msg := <-outCh: //有消息发出,这里消息有两种,一种是广播,需将消息传递给出自己之外的参与者;一种是定向,需将消息传递给定向的那个参与者 dest := msg.GetTo() fmt.Println(msg.Type(), " from ", msg.GetFrom(), " to ", msg.GetTo()) //如果to == nill,就说明是广播消息 if dest == nil { for _, P := range parties { if P.PartyID().Index == msg.GetFrom().Index { continue } //将消息传递给对应party go updater(P, msg, errCh) } } else { if dest[0].Index == msg.GetFrom().Index { t.Fatalf("party %d tried to send a message to itself (%d)", dest[0].Index, msg.GetFrom().Index) } //定向将消息传递给对应的party go updater(parties[dest[0].Index], msg, errCh) }
case sig := <-endCh: //到这里签名有结果了,多签就完成了,签名的数据分别是R、S fmt.Println("R=>",new(big.Int).SetBytes(sig.R)) fmt.Println("S=>", new(big.Int).SetBytes(sig.S)) // fmt.Println("sig=>", hex.EncodeToString(sig.Signature)) //后面就是校验了 //因为是本地启动了多个协程作为参与者,且是使用的相同的channel,所以endCh会收到每一个参与者的多签结果 atomic.AddInt32(&ended, 1) fmt.Println("==> end") //当所以的参与者都完成了签名 if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { t.Logf("Done. Received save data from %d participants", ended) R := parties[0].temp.bigR r := parties[0].temp.rx fmt.Printf("sign result: R(%s, %s), r=%s\n", R.X().String(), R.Y().String(), r.String())
modN := common.ModInt(tss.EC().Params().N)
// BEGIN check s correctness sumS := big.NewInt(0) for _, p := range parties { sumS = modN.Add(sumS, p.temp.si) } //这里计算出来的sumS和sig.S是相同的值, fmt.Printf("S: %s\n", sumS.String()) fmt.Println("pub", keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y())
// END check s correctness
// 以ecdsa来校验签名的正确性 pkX, pkY := keys[0].ECDSAPub.X(), keys[0].ECDSAPub.Y() pk := ecdsa.PublicKey{ Curve: tss.EC(), X: pkX, Y: pkY, } ok := ecdsa.Verify(&pk, hash, R.X(), sumS) assert.True(t, ok, "ecdsa verify must pass") t.Log("ECDSA signing test done.") // END ECDSA verify if atomic.LoadInt32(&ended) == int32(len(signPIDs)) { break signing } } } } }
|