github.com/core-coin/go-core/v2@v2.1.9/consensus/cryptore/algorithm.go (about)

     1  // Copyright 2017 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package cryptore
    18  
    19  import (
    20  	"hash"
    21  
    22  	"golang.org/x/crypto/sha3"
    23  )
    24  
    25  const (
    26  	epochLength = 30000 // Blocks per epoch
    27  )
    28  
    29  // hasher is a repetitive hasher allowing the same hash data structures to be
    30  // reused between hash runs instead of requiring new ones to be created.
    31  type hasher func(dest []byte, data []byte)
    32  
    33  // makeHasher creates a repetitive hasher, allowing the same hash data structures to
    34  // be reused between hash runs instead of requiring new ones to be created. The returned
    35  // function is not thread safe!
    36  func makeHasher(h hash.Hash) hasher {
    37  	// sha3.state supports Read to get the sum, use it to avoid the overhead of Sum.
    38  	// Read alters the state but we reset the hash before every operation.
    39  	type readerHash interface {
    40  		hash.Hash
    41  		Read([]byte) (int, error)
    42  	}
    43  	rh, ok := h.(readerHash)
    44  	if !ok {
    45  		panic("can't find Read method on hash")
    46  	}
    47  	outputLen := rh.Size()
    48  	return func(dest []byte, data []byte) {
    49  		rh.Reset()
    50  		rh.Write(data)
    51  		rh.Read(dest[:outputLen])
    52  	}
    53  }
    54  
    55  // seedHash is the seed to use for generating a verification cache and the mining
    56  // dataset.
    57  func seedHash(block uint64) []byte {
    58  	seed := make([]byte, 32)
    59  	if block < epochLength {
    60  		return seed
    61  	}
    62  	SHA3 := makeHasher(sha3.New256())
    63  	for i := 0; i < int(block/epochLength); i++ {
    64  		SHA3(seed, seed)
    65  	}
    66  	return seed
    67  }