This commit is contained in:
Paweł Bylica 2018-05-31 15:37:44 +00:00 committed by GitHub
commit 56d3b93e74
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 16 deletions

View file

@ -18,7 +18,6 @@ package ethash
import ( import (
"encoding/binary" "encoding/binary"
"hash"
"math/big" "math/big"
"reflect" "reflect"
"runtime" "runtime"
@ -94,17 +93,6 @@ func calcDatasetSize(epoch int) uint64 {
// reused between hash runs instead of requiring new ones to be created. // reused between hash runs instead of requiring new ones to be created.
type hasher func(dest []byte, data []byte) type hasher func(dest []byte, data []byte)
// makeHasher creates a repetitive hasher, allowing the same hash data structures
// to be reused between hash runs instead of requiring new ones to be created.
// The returned function is not thread safe!
func makeHasher(h hash.Hash) hasher {
return func(dest []byte, data []byte) {
h.Write(data)
h.Sum(dest[:0])
h.Reset()
}
}
// seedHash is the seed to use for generating a verification cache and the mining // seedHash is the seed to use for generating a verification cache and the mining
// dataset. // dataset.
func seedHash(block uint64) []byte { func seedHash(block uint64) []byte {
@ -112,7 +100,7 @@ func seedHash(block uint64) []byte {
if block < epochLength { if block < epochLength {
return seed return seed
} }
keccak256 := makeHasher(sha3.NewKeccak256()) keccak256 := sha3.KeccakFast256
for i := 0; i < int(block/epochLength); i++ { for i := 0; i < int(block/epochLength); i++ {
keccak256(seed, seed) keccak256(seed, seed)
} }
@ -166,7 +154,7 @@ func generateCache(dest []uint32, epoch uint64, seed []byte) {
} }
}() }()
// Create a hasher to reuse between invocations // Create a hasher to reuse between invocations
keccak512 := makeHasher(sha3.NewKeccak512()) keccak512 := sha3.KeccakFast512
// Sequentially produce the initial dataset // Sequentially produce the initial dataset
keccak512(cache, seed) keccak512(cache, seed)
@ -299,7 +287,7 @@ func generateDataset(dest []uint32, epoch uint64, cache []uint32) {
defer pend.Done() defer pend.Done()
// Create a hasher to reuse between invocations // Create a hasher to reuse between invocations
keccak512 := makeHasher(sha3.NewKeccak512()) keccak512 := sha3.KeccakFast512
// Calculate the data segment this thread should generate // Calculate the data segment this thread should generate
batch := uint32((size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads))) batch := uint32((size + hashBytes*uint64(threads) - 1) / (hashBytes * uint64(threads)))
@ -373,7 +361,7 @@ func hashimoto(hash []byte, nonce uint64, size uint64, lookup func(index uint32)
// in-memory cache) in order to produce our final value for a particular header // in-memory cache) in order to produce our final value for a particular header
// hash and nonce. // hash and nonce.
func hashimotoLight(size uint64, cache []uint32, hash []byte, nonce uint64) ([]byte, []byte) { func hashimotoLight(size uint64, cache []uint32, hash []byte, nonce uint64) ([]byte, []byte) {
keccak512 := makeHasher(sha3.NewKeccak512()) keccak512 := sha3.KeccakFast512
lookup := func(index uint32) []uint32 { lookup := func(index uint32) []uint32 {
rawData := generateDatasetItem(cache, index, keccak512) rawData := generateDatasetItem(cache, index, keccak512)

View file

@ -4,6 +4,8 @@
package sha3 package sha3
import "encoding/binary"
// spongeDirection indicates the direction bytes are flowing through the sponge. // spongeDirection indicates the direction bytes are flowing through the sponge.
type spongeDirection int type spongeDirection int
@ -190,3 +192,60 @@ func (d *state) Sum(in []byte) []byte {
dup.Read(hash) dup.Read(hash)
return append(in, hash...) return append(in, hash...)
} }
func keccakFast(out []byte, bits int, data []byte) {
const wordSize = 8
hashSize := bits / 8
blockSize := (1600 - bits * 2) / 8
var state [25]uint64
dataIndex := 0
dataLen := len(data)
for dataLen >= blockSize {
for i := 0; i < (blockSize / wordSize); i++ {
state[i] ^= binary.LittleEndian.Uint64(data[dataIndex:])
dataIndex += wordSize
}
keccakF1600(&state)
dataLen -= blockSize
}
stateIndex := 0
for dataLen >= wordSize {
state[stateIndex] ^= binary.LittleEndian.Uint64(data[dataIndex:])
stateIndex++
dataIndex += wordSize
dataLen -= wordSize
}
var lastWord [8]byte
lastWordIndex := 0
for dataLen > 0 {
lastWord[lastWordIndex] = data[dataIndex]
lastWordIndex++
dataIndex++
dataLen--
}
lastWord[lastWordIndex] = 0x01
state[stateIndex] ^= binary.LittleEndian.Uint64(lastWord[:])
state[(blockSize/wordSize) - 1] ^= 0x8000000000000000
keccakF1600(&state)
for i := 0; i < (hashSize / wordSize); i++ {
binary.LittleEndian.PutUint64(out[i * 8:], state[i])
}
}
func KeccakFast256(dest []byte, data []byte) {
keccakFast(dest, 256, data)
}
func KeccakFast512(dest []byte, data []byte) {
keccakFast(dest, 512, data)
}