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  }