Commit 3b00a77d authored by Péter Szilágyi's avatar Péter Szilágyi Committed by Felix Lange

crypto, pow: add pure Go implementation of ethash

parent 288700c4
......@@ -37,6 +37,11 @@ var (
secp256k1_halfN = new(big.Int).Div(secp256k1_N, big.NewInt(2))
)
// Hasher is a repetitive hasher allowing the same hash data structures to be
// reused between hash runs instead of requiring new ones to be created.
type Hasher func(data []byte) []byte
// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
d := sha3.NewKeccak256()
for _, b := range data {
......@@ -45,6 +50,8 @@ func Keccak256(data ...[]byte) []byte {
return d.Sum(nil)
}
// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
// converting it to an internal Hash data structure.
func Keccak256Hash(data ...[]byte) (h common.Hash) {
d := sha3.NewKeccak256()
for _, b := range data {
......@@ -54,6 +61,47 @@ func Keccak256Hash(data ...[]byte) (h common.Hash) {
return h
}
// Keccak256Hasher creates a repetitive Keccak256 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 Keccak256Hasher() Hasher {
hasher := sha3.NewKeccak256()
return func(data []byte) []byte {
hasher.Write(data)
result := hasher.Sum(nil)
hasher.Reset()
return result
}
}
// Keccak512 calculates and returns the Keccak512 hash of the input data.
func Keccak512(data ...[]byte) []byte {
d := sha3.NewKeccak512()
for _, b := range data {
d.Write(b)
}
return d.Sum(nil)
}
// Keccak512Hasher creates a repetitive Keccak512 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 Keccak512Hasher() Hasher {
hasher := sha3.NewKeccak512()
return func(data []byte) []byte {
hasher.Write(data)
result := hasher.Sum(nil)
hasher.Reset()
return result
}
}
// Deprecated: For backward compatibility as other packages depend on these
func Sha3Hash(data ...[]byte) common.Hash { return Keccak256Hash(data...) }
......
......@@ -15,6 +15,9 @@ import (
// NewKeccak256 creates a new Keccak-256 hash.
func NewKeccak256() hash.Hash { return &state{rate: 136, outputLen: 32, dsbyte: 0x01} }
// NewKeccak512 creates a new Keccak-512 hash.
func NewKeccak512() hash.Hash { return &state{rate: 72, outputLen: 64, dsbyte: 0x01} }
// New224 creates a new SHA3-224 hash.
// Its generic security strength is 224 bits against preimage attacks,
// and 112 bits against collision attacks.
......
......@@ -322,7 +322,6 @@
// func keccakF1600(state *[25]uint64)
TEXT ·keccakF1600(SB), 0, $200-8
MOVQ state+0(FP), rpState
SUBQ $(8*25), SP
// Convert the user state into an internal state
NOTQ _be(rpState)
......@@ -388,5 +387,4 @@ TEXT ·keccakF1600(SB), 0, $200-8
NOTQ _mi(rpState)
NOTQ _sa(rpState)
ADDQ $(8*25), SP
RET
This diff is collapsed.
This diff is collapsed.
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Source: https://golang.org/src/crypto/cipher/xor.go
package pow
import (
"runtime"
"unsafe"
)
const wordSize = int(unsafe.Sizeof(uintptr(0)))
const supportsUnaligned = runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le" || runtime.GOARCH == "s390x"
// fastXORBytes xors in bulk. It only works on architectures that
// support unaligned read/writes.
func fastXORBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
w := n / wordSize
if w > 0 {
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
aw := *(*[]uintptr)(unsafe.Pointer(&a))
bw := *(*[]uintptr)(unsafe.Pointer(&b))
for i := 0; i < w; i++ {
dw[i] = aw[i] ^ bw[i]
}
}
for i := (n - n%wordSize); i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
func safeXORBytes(dst, a, b []byte) int {
n := len(a)
if len(b) < n {
n = len(b)
}
for i := 0; i < n; i++ {
dst[i] = a[i] ^ b[i]
}
return n
}
// xorBytes xors the bytes in a and b. The destination is assumed to have enough
// space. Returns the number of bytes xor'd.
func xorBytes(dst, a, b []byte) int {
if supportsUnaligned {
return fastXORBytes(dst, a, b)
}
// TODO(hanwen): if (dst, a, b) have common alignment
// we could still try fastXORBytes. It is not clear
// how often this happens, and it's only worth it if
// the block encryption itself is hardware
// accelerated.
return safeXORBytes(dst, a, b)
}
// fastXORWords XORs multiples of 4 or 8 bytes (depending on architecture.)
// The arguments are assumed to be of equal length.
func fastXORWords(dst, a, b []byte) {
dw := *(*[]uintptr)(unsafe.Pointer(&dst))
aw := *(*[]uintptr)(unsafe.Pointer(&a))
bw := *(*[]uintptr)(unsafe.Pointer(&b))
n := len(b) / wordSize
for i := 0; i < n; i++ {
dw[i] = aw[i] ^ bw[i]
}
}
func xorWords(dst, a, b []byte) {
if supportsUnaligned {
fastXORWords(dst, a, b)
} else {
safeXORBytes(dst, a, b)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment