consensus/p2pool/sidechain/cache.go

80 lines
3.2 KiB
Go
Raw Normal View History

2022-11-03 11:32:07 +00:00
package sidechain
import (
"encoding/binary"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/address"
"git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto"
"git.gammaspectra.live/P2Pool/p2pool-observer/types"
"git.gammaspectra.live/P2Pool/sha3"
2022-11-03 11:32:07 +00:00
"github.com/floatdrop/lru"
"sync/atomic"
2022-11-03 11:32:07 +00:00
)
type deterministicTransactionCacheKey [crypto.PublicKeySize + types.HashSize]byte
type ephemeralPublicKeyCacheKey [crypto.PrivateKeySize + crypto.PublicKeySize*2 + 8]byte
2022-11-03 11:32:07 +00:00
type ephemeralPublicKeyWithViewTag struct {
PublicKey crypto.PublicKeyBytes
ViewTag uint8
2022-11-03 11:32:07 +00:00
}
type DerivationCacheInterface interface {
GetEphemeralPublicKey(a *address.PackedAddress, txKeySlice crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8)
GetDeterministicTransactionKey(seed types.Hash, prevId types.Hash) *crypto.KeyPair
}
2022-11-03 11:32:07 +00:00
type DerivationCache struct {
deterministicKeyCache atomic.Pointer[lru.LRU[deterministicTransactionCacheKey, *crypto.KeyPair]]
deterministicKeyCacheHits atomic.Uint64
deterministicKeyCacheMisses atomic.Uint64
ephemeralPublicKeyCache atomic.Pointer[lru.LRU[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag]]
ephemeralPublicKeyCacheHits atomic.Uint64
ephemeralPublicKeyCacheMisses atomic.Uint64
2022-11-03 11:32:07 +00:00
}
func NewDerivationCache() *DerivationCache {
d := &DerivationCache{}
d.Clear()
return d
}
func (d *DerivationCache) Clear() {
d.deterministicKeyCache.Store(lru.New[deterministicTransactionCacheKey, *crypto.KeyPair](32))
d.ephemeralPublicKeyCache.Store(lru.New[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000))
2022-11-03 11:32:07 +00:00
}
func (d *DerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, txKeySlice crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) {
var key ephemeralPublicKeyCacheKey
copy(key[:], txKeySlice)
copy(key[crypto.PrivateKeySize:], a.ToPackedAddress().Bytes())
binary.LittleEndian.PutUint64(key[crypto.PrivateKeySize+crypto.PublicKeySize*2:], outputIndex)
ephemeralPublicKeyCache := d.ephemeralPublicKeyCache.Load()
if ephemeralPubKey := ephemeralPublicKeyCache.Get(key); ephemeralPubKey == nil {
d.ephemeralPublicKeyCacheMisses.Add(1)
pKB, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a, txKeyScalar, outputIndex, hasher)
ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag})
return pKB, viewTag
2022-11-03 11:32:07 +00:00
} else {
d.ephemeralPublicKeyCacheHits.Add(1)
return ephemeralPubKey.PublicKey, ephemeralPubKey.ViewTag
2022-11-03 11:32:07 +00:00
}
}
2023-03-07 17:57:06 +00:00
func (d *DerivationCache) GetDeterministicTransactionKey(seed types.Hash, prevId types.Hash) *crypto.KeyPair {
var key deterministicTransactionCacheKey
2023-03-07 17:57:06 +00:00
copy(key[:], seed[:])
2022-11-03 11:32:07 +00:00
copy(key[types.HashSize:], prevId[:])
deterministicKeyCache := d.deterministicKeyCache.Load()
if kp := deterministicKeyCache.Get(key); kp == nil {
d.deterministicKeyCacheMisses.Add(1)
2023-03-07 17:57:06 +00:00
data := crypto.NewKeyPairFromPrivate(address.GetDeterministicTransactionPrivateKey(seed, prevId))
deterministicKeyCache.Set(key, data)
2022-11-03 11:32:07 +00:00
return data
} else {
d.deterministicKeyCacheHits.Add(1)
2022-11-03 11:32:07 +00:00
return *kp
}
}