github.com/theQRL/go-zond@v0.1.1/beacon/types/config.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 "crypto/sha256" 21 "fmt" 22 "os" 23 "sort" 24 "strconv" 25 "strings" 26 27 "github.com/theQRL/go-zond/beacon/merkle" 28 "github.com/theQRL/go-zond/common" 29 "github.com/theQRL/go-zond/common/hexutil" 30 "gopkg.in/yaml.v3" 31 ) 32 33 // syncCommitteeDomain specifies the signatures specific use to avoid clashes 34 // across signing different data structures. 35 const syncCommitteeDomain = 7 36 37 // Fork describes a single beacon chain fork and also stores the calculated 38 // signature domain used after this fork. 39 type Fork struct { 40 // Name of the fork in the chain config (config.yaml) file{ 41 Name string 42 43 // Epoch when given fork version is activated 44 Epoch uint64 45 46 // Fork version, see https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#custom-types 47 Version []byte 48 49 // calculated by computeDomain, based on fork version and genesis validators root 50 domain merkle.Value 51 } 52 53 // computeDomain returns the signature domain based on the given fork version 54 // and genesis validator set root. 55 func (f *Fork) computeDomain(genesisValidatorsRoot common.Hash) { 56 var ( 57 hasher = sha256.New() 58 forkVersion32 merkle.Value 59 forkDataRoot merkle.Value 60 ) 61 copy(forkVersion32[:], f.Version) 62 hasher.Write(forkVersion32[:]) 63 hasher.Write(genesisValidatorsRoot[:]) 64 hasher.Sum(forkDataRoot[:0]) 65 66 f.domain[0] = syncCommitteeDomain 67 copy(f.domain[4:], forkDataRoot[:28]) 68 } 69 70 // Forks is the list of all beacon chain forks in the chain configuration. 71 type Forks []*Fork 72 73 // domain returns the signature domain for the given epoch (assumes that domains 74 // have already been calculated). 75 func (f Forks) domain(epoch uint64) (merkle.Value, error) { 76 for i := len(f) - 1; i >= 0; i-- { 77 if epoch >= f[i].Epoch { 78 return f[i].domain, nil 79 } 80 } 81 return merkle.Value{}, fmt.Errorf("unknown fork for epoch %d", epoch) 82 } 83 84 // SigningRoot calculates the signing root of the given header. 85 func (f Forks) SigningRoot(header Header) (common.Hash, error) { 86 domain, err := f.domain(header.Epoch()) 87 if err != nil { 88 return common.Hash{}, err 89 } 90 var ( 91 signingRoot common.Hash 92 headerHash = header.Hash() 93 hasher = sha256.New() 94 ) 95 hasher.Write(headerHash[:]) 96 hasher.Write(domain[:]) 97 hasher.Sum(signingRoot[:0]) 98 99 return signingRoot, nil 100 } 101 102 func (f Forks) Len() int { return len(f) } 103 func (f Forks) Swap(i, j int) { f[i], f[j] = f[j], f[i] } 104 func (f Forks) Less(i, j int) bool { return f[i].Epoch < f[j].Epoch } 105 106 // ChainConfig contains the beacon chain configuration. 107 type ChainConfig struct { 108 GenesisTime uint64 // Unix timestamp of slot 0 109 GenesisValidatorsRoot common.Hash // Root hash of the genesis validator set, used for signature domain calculation 110 Forks Forks 111 } 112 113 // AddFork adds a new item to the list of forks. 114 func (c *ChainConfig) AddFork(name string, epoch uint64, version []byte) *ChainConfig { 115 fork := &Fork{ 116 Name: name, 117 Epoch: epoch, 118 Version: version, 119 } 120 fork.computeDomain(c.GenesisValidatorsRoot) 121 122 c.Forks = append(c.Forks, fork) 123 sort.Sort(c.Forks) 124 125 return c 126 } 127 128 // LoadForks parses the beacon chain configuration file (config.yaml) and extracts 129 // the list of forks. 130 func (c *ChainConfig) LoadForks(path string) error { 131 file, err := os.ReadFile(path) 132 if err != nil { 133 return fmt.Errorf("failed to read beacon chain config file: %v", err) 134 } 135 config := make(map[string]string) 136 if err := yaml.Unmarshal(file, &config); err != nil { 137 return fmt.Errorf("failed to parse beacon chain config file: %v", err) 138 } 139 var ( 140 versions = make(map[string][]byte) 141 epochs = make(map[string]uint64) 142 ) 143 epochs["GENESIS"] = 0 144 145 for key, value := range config { 146 if strings.HasSuffix(key, "_FORK_VERSION") { 147 name := key[:len(key)-len("_FORK_VERSION")] 148 if v, err := hexutil.Decode(value); err == nil { 149 versions[name] = v 150 } else { 151 return fmt.Errorf("failed to decode hex fork id %q in beacon chain config file: %v", value, err) 152 } 153 } 154 if strings.HasSuffix(key, "_FORK_EPOCH") { 155 name := key[:len(key)-len("_FORK_EPOCH")] 156 if v, err := strconv.ParseUint(value, 10, 64); err == nil { 157 epochs[name] = v 158 } else { 159 return fmt.Errorf("failed to parse epoch number %q in beacon chain config file: %v", value, err) 160 } 161 } 162 } 163 for name, epoch := range epochs { 164 if version, ok := versions[name]; ok { 165 delete(versions, name) 166 c.AddFork(name, epoch, version) 167 } else { 168 return fmt.Errorf("fork id missing for %q in beacon chain config file", name) 169 } 170 } 171 for name := range versions { 172 return fmt.Errorf("epoch number missing for fork %q in beacon chain config file", name) 173 } 174 sort.Sort(c.Forks) 175 return nil 176 }