github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/sequencesender/datacommittee.go (about) 1 package sequencesender 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "sort" 8 "strings" 9 10 "github.com/0xPolygon/supernets2-data-availability/batch" 11 "github.com/0xPolygon/supernets2-data-availability/client" 12 "github.com/0xPolygon/supernets2-data-availability/sequence" 13 ethman "github.com/0xPolygon/supernets2-node/etherman" 14 "github.com/0xPolygon/supernets2-node/etherman/types" 15 jTypes "github.com/0xPolygon/supernets2-node/jsonrpc/types" 16 "github.com/0xPolygon/supernets2-node/log" 17 "github.com/ethereum/go-ethereum/common" 18 ) 19 20 type signatureMsg struct { 21 addr common.Address 22 signature []byte 23 err error 24 } 25 26 func (s *SequenceSender) getSignaturesAndAddrsFromDataCommittee(ctx context.Context, sequences []types.Sequence) ([]byte, error) { 27 // Get current committee 28 committee, err := s.etherman.GetCurrentDataCommittee() 29 if err != nil { 30 return nil, err 31 } 32 33 // Get last accInputHash 34 var accInputHash common.Hash 35 if sequences[0].BatchNumber != 0 { 36 prevBatch, err := s.state.GetBatchByNumber(ctx, sequences[0].BatchNumber-1, nil) 37 if err != nil { 38 return nil, err 39 } 40 accInputHash = prevBatch.AccInputHash 41 } 42 43 // Authenticate as trusted sequencer by signing the sequences 44 sequence := sequence.Sequence{ 45 Batches: []batch.Batch{}, 46 OldAccInputHash: accInputHash, 47 } 48 for _, seq := range sequences { 49 sequence.Batches = append(sequence.Batches, batch.Batch{ 50 Number: jTypes.ArgUint64(seq.BatchNumber), 51 GlobalExitRoot: seq.GlobalExitRoot, 52 Timestamp: jTypes.ArgUint64(seq.Timestamp), 53 Coinbase: common.HexToAddress(s.cfg.SenderAddress), 54 L2Data: seq.BatchL2Data, 55 }) 56 } 57 signedSequence, err := sequence.Sign(s.privKey) 58 if err != nil { 59 return nil, err 60 } 61 62 // Request signatures to all members in parallel 63 ch := make(chan signatureMsg, len(committee.Members)) 64 signatureCtx, cancelSignatureCollection := context.WithCancel(ctx) 65 for _, member := range committee.Members { 66 go requestSignatureFromMember(signatureCtx, *signedSequence, member, ch) 67 } 68 69 // Collect signatures 70 msgs := []signatureMsg{} 71 var collectedSignatures uint64 72 var failedToCollect uint64 73 for collectedSignatures < committee.RequiredSignatures { 74 msg := <-ch 75 if msg.err != nil { 76 log.Errorf("error when trying to get signature from %s: %s", msg.addr, msg.err) 77 failedToCollect++ 78 if len(committee.Members)-int(failedToCollect) < int(committee.RequiredSignatures) { 79 cancelSignatureCollection() 80 return nil, errors.New("too many members failed to send their signature") 81 } 82 } else { 83 log.Infof("received signature from %s", msg.addr) 84 collectedSignatures++ 85 } 86 msgs = append(msgs, msg) 87 } 88 89 // Stop requesting as soon as we have N valid signatures 90 cancelSignatureCollection() 91 92 return buildSignaturesAndAddrs(signatureMsgs(msgs), committee.Members), nil 93 } 94 95 func requestSignatureFromMember(ctx context.Context, signedSequence sequence.SignedSequence, member ethman.DataCommitteeMember, ch chan signatureMsg) { 96 // request 97 c := client.New(member.URL) 98 log.Infof("sending request to sign the sequence to %s at %s", member.Addr.Hex(), member.URL) 99 signature, err := c.SignSequence(signedSequence) 100 if err != nil { 101 ch <- signatureMsg{ 102 addr: member.Addr, 103 err: err, 104 } 105 return 106 } 107 // verify returned signature 108 signedSequence.Signature = signature 109 signer, err := signedSequence.Signer() 110 if err != nil { 111 ch <- signatureMsg{ 112 addr: member.Addr, 113 err: err, 114 } 115 return 116 } 117 if signer != member.Addr { 118 ch <- signatureMsg{ 119 addr: member.Addr, 120 err: fmt.Errorf("invalid signer. Expected %s, actual %s", member.Addr.Hex(), signer.Hex()), 121 } 122 return 123 } 124 ch <- signatureMsg{ 125 addr: member.Addr, 126 signature: signature, 127 } 128 } 129 130 func buildSignaturesAndAddrs(msgs signatureMsgs, members []ethman.DataCommitteeMember) []byte { 131 res := []byte{} 132 sort.Sort(msgs) 133 for _, msg := range msgs { 134 log.Debugf("adding signature %s from %s", common.Bytes2Hex(msg.signature), msg.addr.Hex()) 135 res = append(res, msg.signature...) 136 } 137 for _, member := range members { 138 log.Debugf("adding addr %s", common.Bytes2Hex(member.Addr.Bytes())) 139 res = append(res, member.Addr.Bytes()...) 140 } 141 log.Debugf("full res %s", common.Bytes2Hex(res)) 142 return res 143 } 144 145 type signatureMsgs []signatureMsg 146 147 func (s signatureMsgs) Len() int { return len(s) } 148 func (s signatureMsgs) Less(i, j int) bool { 149 return strings.ToUpper(s[i].addr.Hex()) < strings.ToUpper(s[j].addr.Hex()) 150 } 151 func (s signatureMsgs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }