Skip to content

Commit

Permalink
feat: introduce hash cache to improve performance
Browse files Browse the repository at this point in the history
This is part of the optimizations from BSC, microbench show the change
could introduce ~20% speed up of simple erc20 transfer scenario.

The original PR of BSC: bnb-chain/bsc#257
  • Loading branch information
sunny2022da committed Apr 10, 2024
1 parent 3813e13 commit d126651
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions crypto/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"github.com/VictoriaMetrics/fastcache"
"hash"
"io"
"math/big"
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,52 @@ 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 {
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) {
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 d126651

Please sign in to comment.