github.com/theQRL/go-zond@v0.1.1/beacon/types/committee.go (about) 1 // Copyright 2023 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package types 18 19 import ( 20 "crypto/sha256" 21 "encoding/json" 22 "fmt" 23 "math/bits" 24 25 bls "github.com/protolambda/bls12-381-util" 26 "github.com/theQRL/go-zond/beacon/params" 27 "github.com/theQRL/go-zond/common" 28 "github.com/theQRL/go-zond/common/hexutil" 29 ) 30 31 // SerializedSyncCommitteeSize is the size of the sync committee plus the 32 // aggregate public key. 33 const SerializedSyncCommitteeSize = (params.SyncCommitteeSize + 1) * params.BLSPubkeySize 34 35 // SerializedSyncCommittee is the serialized version of a sync committee 36 // plus the aggregate public key. 37 type SerializedSyncCommittee [SerializedSyncCommitteeSize]byte 38 39 // jsonSyncCommittee is the JSON representation of a sync committee. 40 // 41 // See data structure definition here: 42 // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate 43 type jsonSyncCommittee struct { 44 Pubkeys []hexutil.Bytes `json:"pubkeys"` 45 Aggregate hexutil.Bytes `json:"aggregate_pubkey"` 46 } 47 48 // MarshalJSON implements json.Marshaler. 49 func (s *SerializedSyncCommittee) MarshalJSON() ([]byte, error) { 50 sc := jsonSyncCommittee{Pubkeys: make([]hexutil.Bytes, params.SyncCommitteeSize)} 51 for i := range sc.Pubkeys { 52 sc.Pubkeys[i] = make(hexutil.Bytes, params.BLSPubkeySize) 53 copy(sc.Pubkeys[i][:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize]) 54 } 55 sc.Aggregate = make(hexutil.Bytes, params.BLSPubkeySize) 56 copy(sc.Aggregate[:], s[params.SyncCommitteeSize*params.BLSPubkeySize:]) 57 return json.Marshal(&sc) 58 } 59 60 // UnmarshalJSON implements json.Marshaler. 61 func (s *SerializedSyncCommittee) UnmarshalJSON(input []byte) error { 62 var sc jsonSyncCommittee 63 if err := json.Unmarshal(input, &sc); err != nil { 64 return err 65 } 66 if len(sc.Pubkeys) != params.SyncCommitteeSize { 67 return fmt.Errorf("invalid number of pubkeys %d", len(sc.Pubkeys)) 68 } 69 for i, key := range sc.Pubkeys { 70 if len(key) != params.BLSPubkeySize { 71 return fmt.Errorf("pubkey %d has invalid size %d", i, len(key)) 72 } 73 copy(s[i*params.BLSPubkeySize:], key[:]) 74 } 75 if len(sc.Aggregate) != params.BLSPubkeySize { 76 return fmt.Errorf("invalid aggregate pubkey size %d", len(sc.Aggregate)) 77 } 78 copy(s[params.SyncCommitteeSize*params.BLSPubkeySize:], sc.Aggregate[:]) 79 return nil 80 } 81 82 // Root calculates the root hash of the binary tree representation of a sync 83 // committee provided in serialized format. 84 // 85 // TODO(zsfelfoldi): Get rid of this when SSZ encoding lands. 86 func (s *SerializedSyncCommittee) Root() common.Hash { 87 var ( 88 hasher = sha256.New() 89 padding [64 - params.BLSPubkeySize]byte 90 data [params.SyncCommitteeSize]common.Hash 91 l = params.SyncCommitteeSize 92 ) 93 for i := range data { 94 hasher.Reset() 95 hasher.Write(s[i*params.BLSPubkeySize : (i+1)*params.BLSPubkeySize]) 96 hasher.Write(padding[:]) 97 hasher.Sum(data[i][:0]) 98 } 99 for l > 1 { 100 for i := 0; i < l/2; i++ { 101 hasher.Reset() 102 hasher.Write(data[i*2][:]) 103 hasher.Write(data[i*2+1][:]) 104 hasher.Sum(data[i][:0]) 105 } 106 l /= 2 107 } 108 hasher.Reset() 109 hasher.Write(s[SerializedSyncCommitteeSize-params.BLSPubkeySize : SerializedSyncCommitteeSize]) 110 hasher.Write(padding[:]) 111 hasher.Sum(data[1][:0]) 112 hasher.Reset() 113 hasher.Write(data[0][:]) 114 hasher.Write(data[1][:]) 115 hasher.Sum(data[0][:0]) 116 return data[0] 117 } 118 119 // Deserialize splits open the pubkeys into proper BLS key types. 120 func (s *SerializedSyncCommittee) Deserialize() (*SyncCommittee, error) { 121 sc := new(SyncCommittee) 122 for i := 0; i <= params.SyncCommitteeSize; i++ { 123 key := new(bls.Pubkey) 124 125 var bytes [params.BLSPubkeySize]byte 126 copy(bytes[:], s[i*params.BLSPubkeySize:(i+1)*params.BLSPubkeySize]) 127 128 if err := key.Deserialize(&bytes); err != nil { 129 return nil, err 130 } 131 if i < params.SyncCommitteeSize { 132 sc.keys[i] = key 133 } else { 134 sc.aggregate = key 135 } 136 } 137 return sc, nil 138 } 139 140 // SyncCommittee is a set of sync committee signer pubkeys and the aggregate key. 141 // 142 // See data structure definition here: 143 // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate 144 type SyncCommittee struct { 145 keys [params.SyncCommitteeSize]*bls.Pubkey 146 aggregate *bls.Pubkey 147 } 148 149 // VerifySignature returns true if the given sync aggregate is a valid signature 150 // or the given hash. 151 func (sc *SyncCommittee) VerifySignature(signingRoot common.Hash, signature *SyncAggregate) bool { 152 var ( 153 sig bls.Signature 154 keys = make([]*bls.Pubkey, 0, params.SyncCommitteeSize) 155 ) 156 if err := sig.Deserialize(&signature.Signature); err != nil { 157 return false 158 } 159 for i, key := range sc.keys { 160 if signature.Signers[i/8]&(byte(1)<<(i%8)) != 0 { 161 keys = append(keys, key) 162 } 163 } 164 return bls.FastAggregateVerify(keys, signingRoot[:], &sig) 165 } 166 167 //go:generate go run github.com/fjl/gencodec -type SyncAggregate -field-override syncAggregateMarshaling -out gen_syncaggregate_json.go 168 169 // SyncAggregate represents an aggregated BLS signature with Signers referring 170 // to a subset of the corresponding sync committee. 171 // 172 // See data structure definition here: 173 // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/beacon-chain.md#syncaggregate 174 type SyncAggregate struct { 175 Signers [params.SyncCommitteeBitmaskSize]byte `gencodec:"required" json:"sync_committee_bits"` 176 Signature [params.BLSSignatureSize]byte `gencodec:"required" json:"sync_committee_signature"` 177 } 178 179 type syncAggregateMarshaling struct { 180 Signers hexutil.Bytes 181 Signature hexutil.Bytes 182 } 183 184 // SignerCount returns the number of signers in the aggregate signature. 185 func (s *SyncAggregate) SignerCount() int { 186 var count int 187 for _, v := range s.Signers { 188 count += bits.OnesCount8(v) 189 } 190 return count 191 }