github.com/klaytn/klaytn@v1.12.1/node/cn/snap/range.go (about) 1 // Modifications Copyright 2022 The klaytn Authors 2 // Copyright 2021 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from eth/protocols/snap/range.go (2022/06/29). 19 // Modified and improved for the klaytn development. 20 21 package snap 22 23 import ( 24 "math/big" 25 26 "github.com/holiman/uint256" 27 "github.com/klaytn/klaytn/common" 28 ) 29 30 // hashRange is a utility to handle ranges of hashes, Split up the 31 // hash-space into sections, and 'walk' over the sections 32 type hashRange struct { 33 current *uint256.Int 34 step *uint256.Int 35 } 36 37 // newHashRange creates a new hashRange, initiated at the start position, 38 // and with the step set to fill the desired 'num' chunks 39 func newHashRange(start common.Hash, num uint64) *hashRange { 40 left := new(big.Int).Sub(hashSpace, start.Big()) 41 step := new(big.Int).Div( 42 new(big.Int).Add(left, new(big.Int).SetUint64(num-1)), 43 new(big.Int).SetUint64(num), 44 ) 45 step256 := new(uint256.Int) 46 step256.SetFromBig(step) 47 48 return &hashRange{ 49 current: new(uint256.Int).SetBytes32(start[:]), 50 step: step256, 51 } 52 } 53 54 // Next pushes the hash range to the next interval. 55 func (r *hashRange) Next() bool { 56 next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) 57 if overflow { 58 return false 59 } 60 r.current = next 61 return true 62 } 63 64 // Start returns the first hash in the current interval. 65 func (r *hashRange) Start() common.Hash { 66 return r.current.Bytes32() 67 } 68 69 // End returns the last hash in the current interval. 70 func (r *hashRange) End() common.Hash { 71 // If the end overflows (non divisible range), return a shorter interval 72 next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) 73 if overflow { 74 return common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 75 } 76 return next.SubUint64(next, 1).Bytes32() 77 } 78 79 // incHash returns the next hash, in lexicographical order (a.k.a plus one) 80 func incHash(h common.Hash) common.Hash { 81 var a uint256.Int 82 a.SetBytes32(h[:]) 83 a.AddUint64(&a, 1) 84 return common.Hash(a.Bytes32()) 85 }