Speed improvements on partial crypto derivation
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
2ad5e1ba38
commit
951b1105ff
|
@ -66,8 +66,7 @@ func BenchmarkCoinbaseDerivation(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkCoinbaseDerivationInline(b *testing.B) {
|
||||
packed := testAddress3.ToPackedAddress()
|
||||
spendPub, viewPub := packed.SpendPublicKey().AsPoint().Point(), packed.ViewPublicKey().AsPoint().Point()
|
||||
spendPub, viewPub := testAddress3.SpendPublicKey().AsPoint().Point(), testAddress3.ViewPublicKey().AsPoint().Point()
|
||||
|
||||
var i atomic.Uint64
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
|
@ -79,9 +78,8 @@ func BenchmarkCoinbaseDerivationInline(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkCoinbaseDerivationNoAllocate(b *testing.B) {
|
||||
packed := testAddress3.ToPackedAddress()
|
||||
|
||||
spendPub, viewPub := packed.SpendPublicKey().AsPoint().Point(), packed.ViewPublicKey().AsPoint().Point()
|
||||
spendPub, viewPub := testAddress3.SpendPublicKey().AsPoint().Point(), testAddress3.ViewPublicKey().AsPoint().Point()
|
||||
|
||||
txKey := privateKey
|
||||
|
||||
|
@ -90,7 +88,7 @@ func BenchmarkCoinbaseDerivationNoAllocate(b *testing.B) {
|
|||
hasher := crypto.GetKeccak256Hasher()
|
||||
defer crypto.PutKeccak256Hasher(hasher)
|
||||
for pb.Next() {
|
||||
GetEphemeralPublicKeyAndViewTagNoAllocate(spendPub, viewPub, txKey, i.Add(1), hasher)
|
||||
GetEphemeralPublicKeyAndViewTagNoAllocate(spendPub, GetDerivationNoAllocate(viewPub, txKey), txKey, i.Add(1), hasher)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -42,12 +42,9 @@ func GetEphemeralPublicKeyAndViewTag(a Interface, txKey crypto.PrivateKey, outpu
|
|||
}
|
||||
|
||||
// GetEphemeralPublicKeyAndViewTagNoAllocate Special version of GetEphemeralPublicKeyAndViewTag
|
||||
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)
|
||||
|
||||
derivationSharedData, viewTag := crypto.GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(crypto.PublicKeyBytes(cofactor.Bytes()), outputIndex, hasher)
|
||||
func GetEphemeralPublicKeyAndViewTagNoAllocate(spendPublicKeyPoint *edwards25519.Point, derivation crypto.PublicKeyBytes, txKey *edwards25519.Scalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
|
||||
var intermediatePublicKey, ephemeralPublicKey edwards25519.Point
|
||||
derivationSharedData, viewTag := crypto.GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(derivation, outputIndex, hasher)
|
||||
|
||||
intermediatePublicKey.ScalarBaseMult(&derivationSharedData)
|
||||
ephemeralPublicKey.Add(&intermediatePublicKey, spendPublicKeyPoint)
|
||||
|
@ -58,6 +55,15 @@ func GetEphemeralPublicKeyAndViewTagNoAllocate(spendPublicKeyPoint, viewPublicKe
|
|||
return ephemeralPublicKeyBytes, viewTag
|
||||
}
|
||||
|
||||
// GetDerivationNoAllocate Special version
|
||||
func GetDerivationNoAllocate(viewPublicKeyPoint *edwards25519.Point, txKey *edwards25519.Scalar) crypto.PublicKeyBytes {
|
||||
var point, derivation edwards25519.Point
|
||||
point.UnsafeVarTimeScalarMult(txKey, viewPublicKeyPoint)
|
||||
derivation.MultByCofactor(&point)
|
||||
|
||||
return crypto.PublicKeyBytes(derivation.Bytes())
|
||||
}
|
||||
|
||||
func GetTxProofV2(a Interface, txId types.Hash, txKey crypto.PrivateKey, message string) string {
|
||||
prefixHash := crypto.Keccak256(txId[:], []byte(message))
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
|
||||
type deterministicTransactionCacheKey [crypto.PublicKeySize + types.HashSize]byte
|
||||
type ephemeralPublicKeyCacheKey [crypto.PrivateKeySize + crypto.PublicKeySize*2 + 8]byte
|
||||
type derivationCacheKey [crypto.PrivateKeySize + crypto.PublicKeySize]byte
|
||||
|
||||
type ephemeralPublicKeyWithViewTag struct {
|
||||
PublicKey crypto.PublicKeyBytes
|
||||
|
@ -25,6 +26,7 @@ type DerivationCacheInterface interface {
|
|||
|
||||
type DerivationCache struct {
|
||||
deterministicKeyCache utils.Cache[deterministicTransactionCacheKey, *crypto.KeyPair]
|
||||
derivationCache utils.Cache[derivationCacheKey, crypto.PublicKeyBytes]
|
||||
ephemeralPublicKeyCache utils.Cache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag]
|
||||
pubKeyToPointCache utils.Cache[crypto.PublicKeyBytes, *edwards25519.Point]
|
||||
}
|
||||
|
@ -33,6 +35,7 @@ func NewDerivationLRUCache() *DerivationCache {
|
|||
d := &DerivationCache{
|
||||
deterministicKeyCache: utils.NewLRUCache[deterministicTransactionCacheKey, *crypto.KeyPair](32),
|
||||
ephemeralPublicKeyCache: utils.NewLRUCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000),
|
||||
derivationCache: utils.NewLRUCache[derivationCacheKey, crypto.PublicKeyBytes](2000),
|
||||
pubKeyToPointCache: utils.NewLRUCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
|
||||
}
|
||||
return d
|
||||
|
@ -42,7 +45,8 @@ 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),
|
||||
derivationCache: utils.NewMapCache[derivationCacheKey, crypto.PublicKeyBytes](2000),
|
||||
pubKeyToPointCache: utils.NewMapCache[crypto.PublicKeyBytes, *edwards25519.Point](2000),
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
@ -50,6 +54,7 @@ func NewDerivationMapCache() *DerivationCache {
|
|||
func (d *DerivationCache) Clear() {
|
||||
d.deterministicKeyCache.Clear()
|
||||
d.ephemeralPublicKeyCache.Clear()
|
||||
d.derivationCache.Clear()
|
||||
d.pubKeyToPointCache.Clear()
|
||||
}
|
||||
|
||||
|
@ -62,7 +67,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(d.getPublicKeyPoint(*a.SpendPublicKey()), d.getPublicKeyPoint(*a.ViewPublicKey()), txKeyScalar.Scalar(), outputIndex, hasher)
|
||||
pKB, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(d.getPublicKeyPoint(*a.SpendPublicKey()), d.getDerivation(*a.ViewPublicKey(), txKeySlice, d.getPublicKeyPoint(*a.ViewPublicKey()), txKeyScalar.Scalar()), txKeyScalar.Scalar(), outputIndex, hasher)
|
||||
d.ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag})
|
||||
return pKB, viewTag
|
||||
}
|
||||
|
@ -82,6 +87,20 @@ func (d *DerivationCache) GetDeterministicTransactionKey(seed types.Hash, prevId
|
|||
}
|
||||
}
|
||||
|
||||
func (d *DerivationCache) getDerivation(viewPublicKeyBytes crypto.PublicKeyBytes, txKeySlice crypto.PrivateKeySlice, viewPublicKeyPoint *edwards25519.Point, txKey *edwards25519.Scalar) crypto.PublicKeyBytes {
|
||||
var key derivationCacheKey
|
||||
copy(key[:], viewPublicKeyBytes[:])
|
||||
copy(key[crypto.PublicKeySize:], txKeySlice[:])
|
||||
|
||||
if derivation, ok := d.derivationCache.Get(key); ok {
|
||||
return derivation
|
||||
} else {
|
||||
derivation = address.GetDerivationNoAllocate(viewPublicKeyPoint, txKey)
|
||||
d.derivationCache.Set(key, derivation)
|
||||
return derivation
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DerivationCache) getPublicKeyPoint(publicKey crypto.PublicKeyBytes) *edwards25519.Point {
|
||||
if point, ok := d.pubKeyToPointCache.Get(publicKey); ok {
|
||||
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) {
|
||||
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a.SpendPublicKey().AsPoint().Point(), a.ViewPublicKey().AsPoint().Point(), txKeyScalar.Scalar(), outputIndex, hasher)
|
||||
ephemeralPubKey, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a.SpendPublicKey().AsPoint().Point(), address.GetDerivationNoAllocate(a.ViewPublicKey().AsPoint().Point(), txKeyScalar.Scalar()), txKeyScalar.Scalar(), outputIndex, hasher)
|
||||
|
||||
return ephemeralPubKey.AsBytes(), viewTag
|
||||
}
|
||||
|
|
|
@ -147,6 +147,14 @@ func TestSideChainMini(t *testing.T) {
|
|||
hits, misses = s.DerivationCache().deterministicKeyCache.Stats()
|
||||
total = hits + misses
|
||||
log.Printf("Deterministic Key Cache hits = %d (%.02f%%), misses = %d (%.02f%%), total = %d", hits, (float64(hits)/float64(total))*100, misses, (float64(misses)/float64(total))*100, total)
|
||||
|
||||
hits, misses = s.DerivationCache().derivationCache.Stats()
|
||||
total = hits + misses
|
||||
log.Printf("Derivation Cache hits = %d (%.02f%%), misses = %d (%.02f%%), total = %d", hits, (float64(hits)/float64(total))*100, misses, (float64(misses)/float64(total))*100, total)
|
||||
|
||||
hits, misses = s.DerivationCache().pubKeyToPointCache.Stats()
|
||||
total = hits + misses
|
||||
log.Printf("PubKeyToPoint Key Cache hits = %d (%.02f%%), misses = %d (%.02f%%), total = %d", hits, (float64(hits)/float64(total))*100, misses, (float64(misses)/float64(total))*100, total)
|
||||
}
|
||||
|
||||
type fakeServer struct {
|
||||
|
|
Loading…
Reference in a new issue