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  }