github.com/ledgerwatch/erigon-lib@v1.0.0/chain/chain_db.go (about)

     1  /*
     2     Copyright 2021 Erigon contributors
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package chain
    18  
    19  import (
    20  	"encoding/binary"
    21  	"encoding/json"
    22  	"fmt"
    23  
    24  	"github.com/ledgerwatch/erigon-lib/common"
    25  	"github.com/ledgerwatch/erigon-lib/kv"
    26  )
    27  
    28  // GetConfig retrieves the consensus settings based on the given genesis hash.
    29  func GetConfig(db kv.Getter, buf []byte) (*Config, error) {
    30  	hash, err := CanonicalHash(db, 0, buf)
    31  	if err != nil {
    32  		return nil, fmt.Errorf("failed ReadCanonicalHash: %w", err)
    33  	}
    34  	if hash == nil {
    35  		return nil, nil
    36  	}
    37  	data, err := db.GetOne(kv.ConfigTable, hash)
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	if len(data) == 0 {
    42  		return nil, nil
    43  	}
    44  	var config Config
    45  	if err := json.Unmarshal(data, &config); err != nil {
    46  		return nil, fmt.Errorf("invalid chain config JSON: %s, %w", data, err)
    47  	}
    48  	return &config, nil
    49  }
    50  
    51  func CanonicalHash(db kv.Getter, number uint64, buf []byte) ([]byte, error) {
    52  	buf = common.EnsureEnoughSize(buf, 8)
    53  	binary.BigEndian.PutUint64(buf, number)
    54  	data, err := db.GetOne(kv.HeaderCanonical, buf)
    55  	if err != nil {
    56  		return nil, fmt.Errorf("failed CanonicalHash: %w, number=%d", err, number)
    57  	}
    58  	if len(data) == 0 {
    59  		return nil, nil
    60  	}
    61  
    62  	return data, nil
    63  }
    64  
    65  // HeadHeaderHash retrieves the hash of the current canonical head header.
    66  func HeadHeaderHash(db kv.Getter) ([]byte, error) {
    67  	data, err := db.GetOne(kv.HeadHeaderKey, []byte(kv.HeadHeaderKey))
    68  	if err != nil {
    69  		return nil, fmt.Errorf("ReadHeadHeaderHash failed: %w", err)
    70  	}
    71  	return data, nil
    72  }
    73  
    74  func CurrentBlockNumber(db kv.Getter) (*uint64, error) {
    75  	headHash, err := HeadHeaderHash(db)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	return HeaderNumber(db, headHash)
    80  }
    81  
    82  // HeaderNumber returns the header number assigned to a hash.
    83  func HeaderNumber(db kv.Getter, hash []byte) (*uint64, error) {
    84  	data, err := db.GetOne(kv.HeaderNumber, hash)
    85  	if err != nil {
    86  		return nil, fmt.Errorf("ReadHeaderNumber failed: %w", err)
    87  	}
    88  	if len(data) == 0 {
    89  		return nil, nil
    90  	}
    91  	if len(data) != 8 {
    92  		return nil, fmt.Errorf("ReadHeaderNumber got wrong data len: %d", len(data))
    93  	}
    94  	number := binary.BigEndian.Uint64(data)
    95  	return &number, nil
    96  }