github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/eth/protocols/snap/range.go (about) 1 // Copyright 2021 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 snap 18 19 import ( 20 "math/big" 21 22 "github.com/holiman/uint256" 23 24 "github.com/scroll-tech/go-ethereum/common" 25 ) 26 27 // hashRange is a utility to handle ranges of hashes, Split up the 28 // hash-space into sections, and 'walk' over the sections 29 type hashRange struct { 30 current *uint256.Int 31 step *uint256.Int 32 } 33 34 // newHashRange creates a new hashRange, initiated at the start position, 35 // and with the step set to fill the desired 'num' chunks 36 func newHashRange(start common.Hash, num uint64) *hashRange { 37 left := new(big.Int).Sub(hashSpace, start.Big()) 38 step := new(big.Int).Div( 39 new(big.Int).Add(left, new(big.Int).SetUint64(num-1)), 40 new(big.Int).SetUint64(num), 41 ) 42 step256 := new(uint256.Int) 43 step256.SetFromBig(step) 44 45 return &hashRange{ 46 current: new(uint256.Int).SetBytes32(start[:]), 47 step: step256, 48 } 49 } 50 51 // Next pushes the hash range to the next interval. 52 func (r *hashRange) Next() bool { 53 next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) 54 if overflow { 55 return false 56 } 57 r.current = next 58 return true 59 } 60 61 // Start returns the first hash in the current interval. 62 func (r *hashRange) Start() common.Hash { 63 return r.current.Bytes32() 64 } 65 66 // End returns the last hash in the current interval. 67 func (r *hashRange) End() common.Hash { 68 // If the end overflows (non divisible range), return a shorter interval 69 next, overflow := new(uint256.Int).AddOverflow(r.current, r.step) 70 if overflow { 71 return common.HexToHash("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") 72 } 73 return next.SubUint64(next, 1).Bytes32() 74 } 75 76 // incHash returns the next hash, in lexicographical order (a.k.a plus one) 77 func incHash(h common.Hash) common.Hash { 78 var a uint256.Int 79 a.SetBytes32(h[:]) 80 a.AddUint64(&a, 1) 81 return common.Hash(a.Bytes32()) 82 }