git.gammaspectra.live/P2Pool/consensus@v0.0.0-20240403173234-a039820b20c9/p2pool/p2p/challenge.go (about)

     1  package p2p
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"git.gammaspectra.live/P2Pool/consensus/monero/crypto"
     7  	"git.gammaspectra.live/P2Pool/consensus/types"
     8  	"sync/atomic"
     9  	"unsafe"
    10  )
    11  
    12  const HandshakeChallengeSize = 8
    13  const HandshakeChallengeDifficulty = 10000
    14  
    15  type HandshakeChallenge [HandshakeChallengeSize]byte
    16  
    17  func FindChallengeSolution(challenge HandshakeChallenge, consensusId types.Hash, stop *atomic.Bool) (solution uint64, hash types.Hash, ok bool) {
    18  
    19  	var buf [HandshakeChallengeSize*2 + types.HashSize]byte
    20  	copy(buf[:], challenge[:])
    21  	copy(buf[HandshakeChallengeSize:], consensusId[:])
    22  	var salt uint64
    23  
    24  	var saltSlice [int(unsafe.Sizeof(salt))]byte
    25  	_, _ = rand.Read(saltSlice[:])
    26  	salt = binary.LittleEndian.Uint64(saltSlice[:])
    27  
    28  	h := crypto.GetKeccak256Hasher()
    29  	defer crypto.PutKeccak256Hasher(h)
    30  
    31  	var sum types.Hash
    32  
    33  	for {
    34  		h.Reset()
    35  		binary.LittleEndian.PutUint64(buf[types.HashSize+HandshakeChallengeSize:], salt)
    36  		_, _ = h.Write(buf[:])
    37  		crypto.HashFastSum(h, sum[:])
    38  
    39  		//check if we have been asked to stop
    40  		if stop.Load() {
    41  			return salt, sum, false
    42  		}
    43  
    44  		if types.DifficultyFrom64(binary.LittleEndian.Uint64(sum[len(sum)-int(unsafe.Sizeof(uint64(0))):])).Mul64(HandshakeChallengeDifficulty).Hi == 0 {
    45  			//found solution
    46  			return salt, sum, true
    47  		}
    48  
    49  		salt++
    50  	}
    51  }
    52  
    53  func CalculateChallengeHash(challenge HandshakeChallenge, consensusId types.Hash, solution uint64) (hash types.Hash, ok bool) {
    54  	hash = crypto.PooledKeccak256(challenge[:], consensusId[:], binary.LittleEndian.AppendUint64(nil, solution))
    55  	return hash, types.DifficultyFrom64(binary.LittleEndian.Uint64(hash[types.HashSize-int(unsafe.Sizeof(uint64(0))):])).Mul64(HandshakeChallengeDifficulty).Hi == 0
    56  }