Skip to content

Commit

Permalink
feat: introduce hash cache to improve performance (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
sunny2022da committed Apr 11, 2024
1 parent 3813e13 commit 2bf1a70
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"math/big"
"os"

"github.com/VictoriaMetrics/fastcache"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/rlp"
Expand All @@ -47,6 +48,8 @@ const DigestLength = 32
var (
secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))

keccakState256Cache = fastcache.New(100 * 1024 * 1024)
)

var errInvalidPubkey = errors.New("invalid secp256k1 public key")
Expand All @@ -66,31 +69,56 @@ func NewKeccakState() KeccakState {

// HashData hashes the provided data using the KeccakState and returns a 32 byte hash
func HashData(kh KeccakState, data []byte) (h common.Hash) {
if hash, ok := keccakState256Cache.HasGet(nil, data); ok {
return common.BytesToHash(hash)
}
kh.Reset()
kh.Write(data)
kh.Read(h[:])
keccakState256Cache.Set(data, h.Bytes())
return h
}

// Keccak256 calculates and returns the Keccak256 hash of the input data.
func Keccak256(data ...[]byte) []byte {
// Only visit cache when input contains only one []byte to reduce cache overhead
// and avoid complexity of cache calculation.
if len(data) == 1 {
if hash, ok := keccakState256Cache.HasGet(nil, data[0]); ok {
return hash
}
}
b := make([]byte, 32)
d := NewKeccakState()
for _, b := range data {
d.Write(b)
}
d.Read(b)
if len(data) == 1 {
keccakState256Cache.Set(data[0], b)
}
return b
}

// 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) {
// Only visit cache when input contains only one []byte to reduce cache overhead
// and avoid complexity of cache calculation.
if len(data) == 1 {
if hash, ok := keccakState256Cache.HasGet(nil, data[0]); ok {
return common.BytesToHash(hash)
}
}

d := NewKeccakState()
for _, b := range data {
d.Write(b)
}
d.Read(h[:])
if len(data) == 1 {
keccakState256Cache.Set(data[0], h.Bytes())
}
return h
}

Expand Down

0 comments on commit 2bf1a70

Please sign in to comment.