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 }