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