github.com/theQRL/go-zond@v0.1.1/beacon/types/update.go (about) 1 // Copyright 2022 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 "errors" 21 "fmt" 22 23 "github.com/theQRL/go-zond/beacon/merkle" 24 "github.com/theQRL/go-zond/beacon/params" 25 "github.com/theQRL/go-zond/common" 26 ) 27 28 // LightClientUpdate is a proof of the next sync committee root based on a header 29 // signed by the sync committee of the given period. Optionally, the update can 30 // prove quasi-finality by the signed header referring to a previous, finalized 31 // header from the same period, and the finalized header referring to the next 32 // sync committee root. 33 // 34 // See data structure definition here: 35 // https://github.com/ethereum/consensus-specs/blob/dev/specs/altair/light-client/sync-protocol.md#lightclientupdate 36 type LightClientUpdate struct { 37 AttestedHeader SignedHeader // Arbitrary header out of the period signed by the sync committee 38 NextSyncCommitteeRoot common.Hash // Sync committee of the next period advertised in the current one 39 NextSyncCommitteeBranch merkle.Values // Proof for the next period's sync committee 40 41 FinalizedHeader *Header `rlp:"nil"` // Optional header to announce a point of finality 42 FinalityBranch merkle.Values // Proof for the announced finality 43 44 score *UpdateScore // Weight of the update to compare between competing ones 45 } 46 47 // Validate verifies the validity of the update. 48 func (update *LightClientUpdate) Validate() error { 49 period := update.AttestedHeader.Header.SyncPeriod() 50 if SyncPeriod(update.AttestedHeader.SignatureSlot) != period { 51 return errors.New("signature slot and signed header are from different periods") 52 } 53 if update.FinalizedHeader != nil { 54 if update.FinalizedHeader.SyncPeriod() != period { 55 return errors.New("finalized header is from different period") 56 } 57 if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexFinalBlock, update.FinalityBranch, merkle.Value(update.FinalizedHeader.Hash())); err != nil { 58 return fmt.Errorf("invalid finalized header proof: %w", err) 59 } 60 } 61 if err := merkle.VerifyProof(update.AttestedHeader.Header.StateRoot, params.StateIndexNextSyncCommittee, update.NextSyncCommitteeBranch, merkle.Value(update.NextSyncCommitteeRoot)); err != nil { 62 return fmt.Errorf("invalid next sync committee proof: %w", err) 63 } 64 return nil 65 } 66 67 // Score returns the UpdateScore describing the proof strength of the update 68 // Note: thread safety can be ensured by always calling Score on a newly received 69 // or decoded update before making it potentially available for other threads 70 func (update *LightClientUpdate) Score() UpdateScore { 71 if update.score == nil { 72 update.score = &UpdateScore{ 73 SignerCount: uint32(update.AttestedHeader.Signature.SignerCount()), 74 SubPeriodIndex: uint32(update.AttestedHeader.Header.Slot & 0x1fff), 75 FinalizedHeader: update.FinalizedHeader != nil, 76 } 77 } 78 return *update.score 79 } 80 81 // UpdateScore allows the comparison between updates at the same period in order 82 // to find the best update chain that provides the strongest proof of being canonical. 83 // 84 // UpdateScores have a tightly packed binary encoding format for efficient p2p 85 // protocol transmission. Each UpdateScore is encoded in 3 bytes. 86 // When interpreted as a 24 bit little indian unsigned integer: 87 // - the lowest 10 bits contain the number of signers in the header signature aggregate 88 // - the next 13 bits contain the "sub-period index" which is he signed header's 89 // slot modulo params.SyncPeriodLength (which is correlated with the risk of the chain being 90 // re-orged before the previous period boundary in case of non-finalized updates) 91 // - the highest bit is set when the update is finalized (meaning that the finality 92 // header referenced by the signed header is in the same period as the signed 93 // header, making reorgs before the period boundary impossible 94 type UpdateScore struct { 95 SignerCount uint32 // number of signers in the header signature aggregate 96 SubPeriodIndex uint32 // signed header's slot modulo params.SyncPeriodLength 97 FinalizedHeader bool // update is considered finalized if has finalized header from the same period and 2/3 signatures 98 } 99 100 // finalized returns true if the update has a header signed by at least 2/3 of 101 // the committee, referring to a finalized header that refers to the next sync 102 // committee. This condition is a close approximation of the actual finality 103 // condition that can only be verified by full beacon nodes. 104 func (u *UpdateScore) finalized() bool { 105 return u.FinalizedHeader && u.SignerCount >= params.SyncCommitteeSupermajority 106 } 107 108 // BetterThan returns true if update u is considered better than w. 109 func (u UpdateScore) BetterThan(w UpdateScore) bool { 110 var ( 111 uFinalized = u.finalized() 112 wFinalized = w.finalized() 113 ) 114 if uFinalized != wFinalized { 115 return uFinalized 116 } 117 return u.SignerCount > w.SignerCount 118 }