The core protocol of WoopChain
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
woop/pow/sha2bday.go

79 lines
1.8 KiB

6 years ago
package pow
import (
"bytes"
"crypto/sha256"
"encoding/binary"
)
func checkSha2BDay(proof []byte, nonce, data []byte, diff uint32) bool {
if len(proof) != 24 {
return false
}
prefix1 := proof[:8]
prefix2 := proof[8:16]
prefix3 := proof[16:]
if bytes.Equal(prefix1, prefix2) || bytes.Equal(prefix2, prefix3) ||
bytes.Equal(prefix1, prefix3) {
return false
}
resBuf := make([]byte, 32)
h := sha256.New()
h.Write(prefix1)
h.Write(data)
h.Write(nonce)
h.Sum(resBuf[:0])
res1 := binary.BigEndian.Uint64(resBuf) & ((1 << diff) - 1)
h.Reset()
h.Write(prefix2)
h.Write(data)
h.Write(nonce)
h.Sum(resBuf[:0])
res2 := binary.BigEndian.Uint64(resBuf) & ((1 << diff) - 1)
h.Reset()
h.Write(prefix3)
h.Write(data)
h.Write(nonce)
h.Sum(resBuf[:0])
res3 := binary.BigEndian.Uint64(resBuf) & ((1 << diff) - 1)
return res1 == res2 && res2 == res3
}
func fulfilSha2BDay(nonce []byte, diff uint32, data []byte) []byte {
// TODO make multithreaded if the difficulty is high enough.
// For light proof-of-work requests, the overhead of parallelizing is
// not worth it.
type Pair struct {
First, Second uint64
}
var i uint64 = 1
prefix := make([]byte, 8)
resBuf := make([]byte, 32)
lut := make(map[uint64]Pair)
h := sha256.New()
for {
binary.BigEndian.PutUint64(prefix, i)
h.Write(prefix)
h.Write(data)
h.Write(nonce)
h.Sum(resBuf[:0])
res := binary.BigEndian.Uint64(resBuf) & ((1 << diff) - 1)
pair, ok := lut[res]
if ok {
if pair.Second != 0 {
ret := make([]byte, 24)
binary.BigEndian.PutUint64(ret, pair.First)
binary.BigEndian.PutUint64(ret[8:], pair.Second)
copy(ret[16:], prefix)
return ret
}
lut[res] = Pair{First: pair.First, Second: i}
} else {
lut[res] = Pair{First: i}
}
h.Reset()
i++
}
}