Sync speed improvements by better crypto cache
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
db5a26de4f
commit
2ad5e1ba38
|
@ -60,7 +60,7 @@ func BenchmarkCoinbaseDerivation(b *testing.B) {
|
||||||
var i atomic.Uint64
|
var i atomic.Uint64
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
for pb.Next() {
|
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) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
p := new(edwards25519.Point)
|
p := new(edwards25519.Point)
|
||||||
for pb.Next() {
|
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) {
|
func BenchmarkCoinbaseDerivationNoAllocate(b *testing.B) {
|
||||||
packed := testAddress3.ToPackedAddress()
|
packed := testAddress3.ToPackedAddress()
|
||||||
|
|
||||||
txKey := (*crypto.PrivateKeyScalar)(privateKey)
|
spendPub, viewPub := packed.SpendPublicKey().AsPoint().Point(), packed.ViewPublicKey().AsPoint().Point()
|
||||||
|
|
||||||
|
txKey := privateKey
|
||||||
|
|
||||||
var i atomic.Uint64
|
var i atomic.Uint64
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
hasher := crypto.GetKeccak256Hasher()
|
hasher := crypto.GetKeccak256Hasher()
|
||||||
defer crypto.PutKeccak256Hasher(hasher)
|
defer crypto.PutKeccak256Hasher(hasher)
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
GetEphemeralPublicKeyAndViewTagNoAllocate(&packed, txKey, i.Load(), hasher)
|
GetEphemeralPublicKeyAndViewTagNoAllocate(spendPub, viewPub, txKey, i.Add(1), hasher)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,18 +42,15 @@ func GetEphemeralPublicKeyAndViewTag(a Interface, txKey crypto.PrivateKey, outpu
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEphemeralPublicKeyAndViewTagNoAllocate Special version of GetEphemeralPublicKeyAndViewTag
|
// GetEphemeralPublicKeyAndViewTagNoAllocate Special version of GetEphemeralPublicKeyAndViewTag
|
||||||
func GetEphemeralPublicKeyAndViewTagNoAllocate(a *PackedAddress, txKey *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
|
func GetEphemeralPublicKeyAndViewTagNoAllocate(spendPublicKeyPoint, viewPublicKeyPoint *edwards25519.Point, txKey *edwards25519.Scalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
|
||||||
scalar := txKey.Scalar()
|
var point, cofactor, intermediatePublicKey, ephemeralPublicKey edwards25519.Point
|
||||||
var spendPublicKeyPoint, viewPublicKeyPoint, point, cofactor, intermediatePublicKey, ephemeralPublicKey edwards25519.Point
|
point.UnsafeVarTimeScalarMult(txKey, viewPublicKeyPoint)
|
||||||
_, _ = spendPublicKeyPoint.SetBytes((*a)[0][:])
|
|
||||||
_, _ = viewPublicKeyPoint.SetBytes((*a)[1][:])
|
|
||||||
point.UnsafeVarTimeScalarMult(scalar, &viewPublicKeyPoint)
|
|
||||||
cofactor.MultByCofactor(&point)
|
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)
|
intermediatePublicKey.ScalarBaseMult(&derivationSharedData)
|
||||||
ephemeralPublicKey.Add(&intermediatePublicKey, &spendPublicKeyPoint)
|
ephemeralPublicKey.Add(&intermediatePublicKey, spendPublicKeyPoint)
|
||||||
|
|
||||||
var ephemeralPublicKeyBytes crypto.PublicKeyBytes
|
var ephemeralPublicKeyBytes crypto.PublicKeyBytes
|
||||||
copy(ephemeralPublicKeyBytes[:], ephemeralPublicKey.Bytes())
|
copy(ephemeralPublicKeyBytes[:], ephemeralPublicKey.Bytes())
|
||||||
|
|
|
@ -2,6 +2,7 @@ package sidechain
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"git.gammaspectra.live/P2Pool/edwards25519"
|
||||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
|
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
|
||||||
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
|
||||||
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
|
||||||
|
@ -25,12 +26,14 @@ type DerivationCacheInterface interface {
|
||||||
type DerivationCache struct {
|
type DerivationCache struct {
|
||||||
deterministicKeyCache utils.Cache[deterministicTransactionCacheKey, *crypto.KeyPair]
|
deterministicKeyCache utils.Cache[deterministicTransactionCacheKey, *crypto.KeyPair]
|
||||||
ephemeralPublicKeyCache utils.Cache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag]
|
ephemeralPublicKeyCache utils.Cache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag]
|
||||||
|
pubKeyToPointCache utils.Cache[crypto.PublicKeyBytes, *edwards25519.Point]
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDerivationLRUCache() *DerivationCache {
|
func NewDerivationLRUCache() *DerivationCache {
|
||||||
d := &DerivationCache{
|
d := &DerivationCache{
|
||||||
deterministicKeyCache: utils.NewLRUCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
|
deterministicKeyCache: utils.NewLRUCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
|
||||||
ephemeralPublicKeyCache: utils.NewLRUCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
|
ephemeralPublicKeyCache: utils.NewLRUCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
|
||||||
|
pubKeyToPointCache: utils.NewLRUCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
@ -39,6 +42,7 @@ func NewDerivationMapCache() *DerivationCache {
|
||||||
d := &DerivationCache{
|
d := &DerivationCache{
|
||||||
deterministicKeyCache: utils.NewMapCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
|
deterministicKeyCache: utils.NewMapCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
|
||||||
ephemeralPublicKeyCache: utils.NewMapCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
|
ephemeralPublicKeyCache: utils.NewMapCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
|
||||||
|
pubKeyToPointCache: utils.NewLRUCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
@ -46,6 +50,7 @@ func NewDerivationMapCache() *DerivationCache {
|
||||||
func (d *DerivationCache) Clear() {
|
func (d *DerivationCache) Clear() {
|
||||||
d.deterministicKeyCache.Clear()
|
d.deterministicKeyCache.Clear()
|
||||||
d.ephemeralPublicKeyCache.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) {
|
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 {
|
if ephemeralPubKey, ok := d.ephemeralPublicKeyCache.Get(key); ok {
|
||||||
return ephemeralPubKey.PublicKey, ephemeralPubKey.ViewTag
|
return ephemeralPubKey.PublicKey, ephemeralPubKey.ViewTag
|
||||||
} else {
|
} 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})
|
d.ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag})
|
||||||
return pKB, viewTag
|
return pKB, viewTag
|
||||||
}
|
}
|
||||||
|
@ -76,3 +81,13 @@ func (d *DerivationCache) GetDeterministicTransactionKey(seed types.Hash, prevId
|
||||||
return data
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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) {
|
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
|
return ephemeralPubKey.AsBytes(), viewTag
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
"git.gammaspectra.live/P2Pool/sha3"
|
"git.gammaspectra.live/P2Pool/sha3"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
"log"
|
"log"
|
||||||
"lukechampine.com/uint128"
|
|
||||||
"math"
|
"math"
|
||||||
|
"math/bits"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetByMainIdFunc func(h types.Hash) *PoolBlock
|
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
|
// 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) {
|
func ShuffleShares[T any](shares []T, shareVersion ShareVersion, privateKeySeed types.Hash) {
|
||||||
n := len(shares)
|
n := uint64(len(shares))
|
||||||
if shareVersion > ShareVersion_V1 && n > 1 {
|
if shareVersion > ShareVersion_V1 && n > 1 {
|
||||||
h := crypto.PooledKeccak256(privateKeySeed[:])
|
h := crypto.PooledKeccak256(privateKeySeed[:])
|
||||||
seed := binary.LittleEndian.Uint64(h[:])
|
seed := binary.LittleEndian.Uint64(h[:])
|
||||||
|
@ -265,9 +265,9 @@ func ShuffleShares[T any](shares []T, shareVersion ShareVersion, privateKeySeed
|
||||||
seed = 1
|
seed = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < (n - 1); i++ {
|
for i := uint64(0); i < (n - 1); i++ {
|
||||||
seed = utils.XorShift64Star(seed)
|
seed = utils.XorShift64Star(seed)
|
||||||
k := int(uint128.From64(seed).Mul64(uint64(n - i)).Hi)
|
k, _ := bits.Mul64(seed, n-i)
|
||||||
//swap
|
//swap
|
||||||
shares[i], shares[i+k] = shares[i+k], shares[i]
|
shares[i], shares[i+k] = shares[i+k], shares[i]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package utils
|
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 {
|
func XorShift64Star(x uint64) uint64 {
|
||||||
x ^= x >> 12
|
x ^= x >> 12
|
||||||
x ^= x << 25
|
x ^= x << 25
|
||||||
|
|
Loading…
Reference in a new issue