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 }