Sync speed improvements by better crypto cache
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
DataHoarder 2023-05-23 09:31:20 +02:00
parent db5a26de4f
commit 2ad5e1ba38
Signed by: DataHoarder
SSH key fingerprint: SHA256:OLTRf6Fl87G52SiR7sWLGNzlJt4WOX+tfI2yxo0z7xk
6 changed files with 35 additions and 19 deletions

View file

@ -60,7 +60,7 @@ func BenchmarkCoinbaseDerivation(b *testing.B) {
var i atomic.Uint64
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
GetEphemeralPublicKeyAndViewTag(&packed, txKey, i.Load())
GetEphemeralPublicKeyAndViewTag(&packed, txKey, i.Add(1))
}
})
}
@ -73,7 +73,7 @@ func BenchmarkCoinbaseDerivationInline(b *testing.B) {
b.RunParallel(func(pb *testing.PB) {
p := new(edwards25519.Point)
for pb.Next() {
getEphemeralPublicKeyInline(spendPub, viewPub, privateKey, i.Load(), p)
getEphemeralPublicKeyInline(spendPub, viewPub, privateKey, i.Add(1), p)
}
})
}
@ -81,14 +81,16 @@ func BenchmarkCoinbaseDerivationInline(b *testing.B) {
func BenchmarkCoinbaseDerivationNoAllocate(b *testing.B) {
packed := testAddress3.ToPackedAddress()
txKey := (*crypto.PrivateKeyScalar)(privateKey)
spendPub, viewPub := packed.SpendPublicKey().AsPoint().Point(), packed.ViewPublicKey().AsPoint().Point()
txKey := privateKey
var i atomic.Uint64
b.RunParallel(func(pb *testing.PB) {
hasher := crypto.GetKeccak256Hasher()
defer crypto.PutKeccak256Hasher(hasher)
for pb.Next() {
GetEphemeralPublicKeyAndViewTagNoAllocate(&packed, txKey, i.Load(), hasher)
GetEphemeralPublicKeyAndViewTagNoAllocate(spendPub, viewPub, txKey, i.Add(1), hasher)
}
})
}

View file

@ -42,18 +42,15 @@ func GetEphemeralPublicKeyAndViewTag(a Interface, txKey crypto.PrivateKey, outpu
}
// GetEphemeralPublicKeyAndViewTagNoAllocate Special version of GetEphemeralPublicKeyAndViewTag
func GetEphemeralPublicKeyAndViewTagNoAllocate(a *PackedAddress, txKey *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
scalar := txKey.Scalar()
var spendPublicKeyPoint, viewPublicKeyPoint, point, cofactor, intermediatePublicKey, ephemeralPublicKey edwards25519.Point
_, _ = spendPublicKeyPoint.SetBytes((*a)[0][:])
_, _ = viewPublicKeyPoint.SetBytes((*a)[1][:])
point.UnsafeVarTimeScalarMult(scalar, &viewPublicKeyPoint)
func GetEphemeralPublicKeyAndViewTagNoAllocate(spendPublicKeyPoint, viewPublicKeyPoint *edwards25519.Point, txKey *edwards25519.Scalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
var point, cofactor, intermediatePublicKey, ephemeralPublicKey edwards25519.Point
point.UnsafeVarTimeScalarMult(txKey, viewPublicKeyPoint)
cofactor.MultByCofactor(&point)
pK, viewTag := crypto.GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(crypto.PublicKeyBytes(cofactor.Bytes()), outputIndex, hasher)
derivationSharedData, viewTag := crypto.GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(crypto.PublicKeyBytes(cofactor.Bytes()), outputIndex, hasher)
intermediatePublicKey.ScalarBaseMult(&pK)
ephemeralPublicKey.Add(&intermediatePublicKey, &spendPublicKeyPoint)
intermediatePublicKey.ScalarBaseMult(&derivationSharedData)
ephemeralPublicKey.Add(&intermediatePublicKey, spendPublicKeyPoint)
var ephemeralPublicKeyBytes crypto.PublicKeyBytes
copy(ephemeralPublicKeyBytes[:], ephemeralPublicKey.Bytes())

View file

@ -2,6 +2,7 @@ package sidechain
import (
"encoding/binary"
"git.gammaspectra.live/P2Pool/edwards25519"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
@ -25,12 +26,14 @@ type DerivationCacheInterface interface {
type DerivationCache struct {
deterministicKeyCache utils.Cache[deterministicTransactionCacheKey, *crypto.KeyPair]
ephemeralPublicKeyCache utils.Cache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag]
pubKeyToPointCache utils.Cache[crypto.PublicKeyBytes, *edwards25519.Point]
}
func NewDerivationLRUCache() *DerivationCache {
d := &DerivationCache{
deterministicKeyCache: utils.NewLRUCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
ephemeralPublicKeyCache: utils.NewLRUCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
pubKeyToPointCache: utils.NewLRUCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
}
return d
}
@ -39,6 +42,7 @@ func NewDerivationMapCache() *DerivationCache {
d := &DerivationCache{
deterministicKeyCache: utils.NewMapCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
ephemeralPublicKeyCache: utils.NewMapCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
pubKeyToPointCache: utils.NewLRUCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
}
return d
}
@ -46,6 +50,7 @@ func NewDerivationMapCache() *DerivationCache {
func (d *DerivationCache) Clear() {
d.deterministicKeyCache.Clear()
d.ephemeralPublicKeyCache.Clear()
d.pubKeyToPointCache.Clear()
}
func (d *DerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, txKeySlice crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
@ -57,7 +62,7 @@ func (d *DerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, txKeyS
if ephemeralPubKey, ok := d.ephemeralPublicKeyCache.Get(key); ok {
return ephemeralPubKey.PublicKey, ephemeralPubKey.ViewTag
} else {
pKB, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a, txKeyScalar, outputIndex, hasher)
pKB, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(d.getPublicKeyPoint(*a.SpendPublicKey()), d.getPublicKeyPoint(*a.ViewPublicKey()), txKeyScalar.Scalar(), outputIndex, hasher)
d.ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag})
return pKB, viewTag
}
@ -76,3 +81,13 @@ func (d *DerivationCache) GetDeterministicTransactionKey(seed types.Hash, prevId
return data
}
}
func (d *DerivationCache) getPublicKeyPoint(publicKey crypto.PublicKeyBytes) *edwards25519.Point {
if point, ok := d.pubKeyToPointCache.Get(publicKey); ok {
return point
} else {
point = publicKey.AsPoint().Point()
d.pubKeyToPointCache.Set(publicKey, point)
return point
}
}

View file

@ -15,7 +15,7 @@ func (d *NilDerivationCache) Clear() {
}
func (d *NilDerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, _ crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a, txKeyScalar, outputIndex, hasher)
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a.SpendPublicKey().AsPoint().Point(), a.ViewPublicKey().AsPoint().Point(), txKeyScalar.Scalar(), outputIndex, hasher)
return ephemeralPubKey.AsBytes(), viewTag
}

View file

@ -14,8 +14,8 @@ import (
"git.gammaspectra.live/P2Pool/sha3"
"golang.org/x/exp/slices"
"log"
"lukechampine.com/uint128"
"math"
"math/bits"
)
type GetByMainIdFunc func(h types.Hash) *PoolBlock
@ -256,7 +256,7 @@ func GetShares(tip *PoolBlock, consensus *Consensus, difficultyByHeight block.Ge
// ShuffleShares Sorts shares according to consensus parameters. Requires pre-sorted shares based on address
func ShuffleShares[T any](shares []T, shareVersion ShareVersion, privateKeySeed types.Hash) {
n := len(shares)
n := uint64(len(shares))
if shareVersion > ShareVersion_V1 && n > 1 {
h := crypto.PooledKeccak256(privateKeySeed[:])
seed := binary.LittleEndian.Uint64(h[:])
@ -265,9 +265,9 @@ func ShuffleShares[T any](shares []T, shareVersion ShareVersion, privateKeySeed
seed = 1
}
for i := 0; i < (n - 1); i++ {
for i := uint64(0); i < (n - 1); i++ {
seed = utils.XorShift64Star(seed)
k := int(uint128.From64(seed).Mul64(uint64(n - i)).Hi)
k, _ := bits.Mul64(seed, n-i)
//swap
shares[i], shares[i+k] = shares[i+k], shares[i]
}

View file

@ -1,5 +1,7 @@
package utils
// XorShift64Star Implementation of xorshift* https://en.wikipedia.org/wiki/Xorshift#xorshift*
// x must be initialized to a non-zero value
func XorShift64Star(x uint64) uint64 {
x ^= x >> 12
x ^= x << 25