From e9eb5915ed5c5bcf54e86bdd3ee4f9a65902da75 Mon Sep 17 00:00:00 2001 From: WeebDataHoarder <57538841+WeebDataHoarder@users.noreply.github.com> Date: Sat, 20 May 2023 10:49:05 +0200 Subject: [PATCH] Optimize address sorting, crypto cache, use unsafe VarTimeScalarMult for sidechain operations --- cmd/archivetoarchive/archivetoarchive.go | 2 +- cmd/archivetoindex/archivetoindex.go | 2 +- cmd/legacytoarchive/legacytoarchive.go | 2 +- cmd/recoverpoolblock/recoverpoolblock.go | 2 +- go.mod | 2 +- go.sum | 28 +----- index/index.go | 2 +- monero/address/address.go | 15 +++- monero/address/address_test.go | 19 +++- monero/address/crypto.go | 6 +- monero/address/interface.go | 4 +- monero/address/packed.go | 84 ++++-------------- monero/crypto/constants.go | 2 +- monero/crypto/crypto.go | 44 ++++++++++ monero/crypto/derivations.go | 2 +- monero/crypto/derivations_test.go | 2 +- monero/crypto/hash.go | 2 +- monero/crypto/pool.go | 2 +- monero/crypto/private.go | 2 +- monero/crypto/public.go | 2 +- monero/crypto/random.go | 2 +- monero/crypto/signature.go | 2 +- p2pool/api/p2poolapi.go | 2 +- p2pool/cache/archive/archive.go | 2 +- p2pool/crypto/crypto_test.go | 2 +- p2pool/mainchain/mainchain.go | 5 ++ p2pool/sidechain/cache.go | 57 ++++++------ p2pool/sidechain/sidechain.go | 2 +- p2pool/sidechain/sidechain_test.go | 5 +- p2pool/sidechain/utils.go | 2 +- utils/cache.go | 105 +++++++++++++++++++++++ 31 files changed, 257 insertions(+), 155 deletions(-) create mode 100644 utils/cache.go diff --git a/cmd/archivetoarchive/archivetoarchive.go b/cmd/archivetoarchive/archivetoarchive.go index d475cd0..acd4169 100644 --- a/cmd/archivetoarchive/archivetoarchive.go +++ b/cmd/archivetoarchive/archivetoarchive.go @@ -59,7 +59,7 @@ func main() { } defer outputCache.Close() - derivationCache := sidechain.NewDerivationCache() + derivationCache := sidechain.NewDerivationLRUCache() blockCache := lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 4)) diff --git a/cmd/archivetoindex/archivetoindex.go b/cmd/archivetoindex/archivetoindex.go index c849ee8..cf399ae 100644 --- a/cmd/archivetoindex/archivetoindex.go +++ b/cmd/archivetoindex/archivetoindex.go @@ -101,7 +101,7 @@ func main() { blockCache := lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 4)) - derivationCache := sidechain.NewDerivationCache() + derivationCache := sidechain.NewDerivationLRUCache() getByTemplateIdDirect := func(h types.Hash) *sidechain.PoolBlock { if v := blockCache.Get(h); v == nil { if bs := archiveCache.LoadByTemplateId(h); len(bs) != 0 { diff --git a/cmd/legacytoarchive/legacytoarchive.go b/cmd/legacytoarchive/legacytoarchive.go index 822c15c..9fd60ff 100644 --- a/cmd/legacytoarchive/legacytoarchive.go +++ b/cmd/legacytoarchive/legacytoarchive.go @@ -39,7 +39,7 @@ func main() { totalStored := 0 - derivationCache := sidechain.NewDerivationCache() + derivationCache := sidechain.NewDerivationLRUCache() blockCache := lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 4 * 60)) diff --git a/cmd/recoverpoolblock/recoverpoolblock.go b/cmd/recoverpoolblock/recoverpoolblock.go index 3fe1f8e..3f6df89 100644 --- a/cmd/recoverpoolblock/recoverpoolblock.go +++ b/cmd/recoverpoolblock/recoverpoolblock.go @@ -109,7 +109,7 @@ func main() { blockCache := lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 4)) - derivationCache := sidechain.NewDerivationCache() + derivationCache := sidechain.NewDerivationLRUCache() getByTemplateIdDirect := func(h types.Hash) *sidechain.PoolBlock { if v := blockCache.Get(h); v == nil { if bs := archiveCache.LoadByTemplateId(h); len(bs) != 0 { diff --git a/go.mod b/go.mod index 957d7b2..a0bb2e7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.gammaspectra.live/P2Pool/p2pool-observer go 1.20 require ( - filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550 + git.gammaspectra.live/P2Pool/edwards25519 v0.0.0-20230520084036-0f06fa066019 git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 git.gammaspectra.live/P2Pool/moneroutil v0.0.0-20230516052049-a566889a4d3b diff --git a/go.sum b/go.sum index 977e661..585d3c0 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550 h1:Mqu6Q2e//30TWeP5bM9Th5KEzWdFAFd80Y2ZXN9fmeE= -filippo.io/edwards25519 v1.0.1-0.20220803165937-8c58ed0e3550/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= +git.gammaspectra.live/P2Pool/edwards25519 v0.0.0-20230520084036-0f06fa066019 h1:A256rPumLHvYEJdgOQQAHZX7zOZTSYiGcsT5rykpcH4= +git.gammaspectra.live/P2Pool/edwards25519 v0.0.0-20230520084036-0f06fa066019/go.mod h1:336HUKX25mQ1qUtzkwV9Wrqi153tTgUOKcIhpYuF2ts= git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523 h1:oIJzm7kQyASS0xlJ79VSWRvvfXp2Qt7M05+E20o9gwE= git.gammaspectra.live/P2Pool/go-monero v0.0.0-20230410011208-910450c4a523/go.mod h1:TAOAAV972JNDkCzyV5SkbYkKCRvcfhvvFa8LHH4Dg6g= git.gammaspectra.live/P2Pool/go-randomx v0.0.0-20221027085532-f46adfce03a7 h1:bzHDuu1IgETKqPBOlIdCE2LaZIJ+ZpROSprNn+fnzd8= @@ -14,22 +14,17 @@ github.com/ake-persson/mapslice-json v0.0.0-20210720081907-22c8edf57807 h1:w3nrG github.com/ake-persson/mapslice-json v0.0.0-20210720081907-22c8edf57807/go.mod h1:fGnnfniJiO/ajHAVHqMSUSL8sE9LmU9rzclCtoeB+y8= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/floatdrop/lru v1.3.0 h1:83abtaKjXcWrPmtzTAk2Ggq8DUKqI29YzrTrB8+vu0c= github.com/floatdrop/lru v1.3.0/go.mod h1:83zlXKA06Bm32JImNINCiTr0ldadvdAjUe5jSwIaw0s= -github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -52,23 +47,18 @@ github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= -github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/gordonklaus/ineffassign v0.0.0-20210522101830-0589229737b2 h1:hC4RAQwLzbDbHsa+CwwGBm1uG2oX9o3Frx9G73duPi8= github.com/gordonklaus/ineffassign v0.0.0-20210522101830-0589229737b2/go.mod h1:M9mZEtGIsR1oDaZagNPNG9iq9n2HrhZ17dsXk73V3Lw= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/holiman/uint256 v1.2.2 h1:TXKcSGc2WaxPD2+bmzAsVthL4+pEN0YwXcL5qED83vk= github.com/holiman/uint256 v1.2.2/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw= github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc= -github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6RlY= github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= @@ -78,10 +68,8 @@ github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= @@ -89,16 +77,12 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -114,11 +98,9 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= -go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -126,13 +108,11 @@ golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -158,13 +138,11 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -172,11 +150,9 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= diff --git a/index/index.go b/index/index.go index 636c655..11bcb74 100644 --- a/index/index.go +++ b/index/index.go @@ -60,7 +60,7 @@ func OpenIndex(connStr string, consensus *sidechain.Consensus, difficultyByHeigh getDifficultyByHeight: difficultyByHeight, getSeedByHeight: getSeedByHeight, getByTemplateId: getByTemplateId, - derivationCache: sidechain.NewDerivationCache(), + derivationCache: sidechain.NewDerivationLRUCache(), blockCache: lru.New[types.Hash, *sidechain.PoolBlock](int(consensus.ChainWindowSize * 4)), } if index.handle, err = sql.Open("postgres", connStr); err != nil { diff --git a/monero/address/address.go b/monero/address/address.go index cf82375..e4bfd6d 100644 --- a/monero/address/address.go +++ b/monero/address/address.go @@ -16,19 +16,26 @@ type Address struct { } func (a *Address) Compare(b Interface) int { - //TODO - return a.ToPackedAddress().Reference().Compare(b) + //compare spend key + + resultSpendKey := crypto.CompareConsensusPublicKeyBytes(a.SpendPub, *b.SpendPublicKey()) + if resultSpendKey != 0 { + return resultSpendKey + } + + // compare view key + return crypto.CompareConsensusPublicKeyBytes(a.ViewPub, *b.ViewPublicKey()) } func (a *Address) PublicKeys() (spend, view crypto.PublicKey) { return &a.SpendPub, &a.ViewPub } -func (a *Address) SpendPublicKey() crypto.PublicKey { +func (a *Address) SpendPublicKey() *crypto.PublicKeyBytes { return &a.SpendPub } -func (a *Address) ViewPublicKey() crypto.PublicKey { +func (a *Address) ViewPublicKey() *crypto.PublicKeyBytes { return &a.ViewPub } diff --git a/monero/address/address_test.go b/monero/address/address_test.go index 59182ea..98cf684 100644 --- a/monero/address/address_test.go +++ b/monero/address/address_test.go @@ -3,7 +3,7 @@ package address import ( "bytes" "encoding/hex" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "log" @@ -60,7 +60,7 @@ func BenchmarkCoinbaseDerivation(b *testing.B) { var i atomic.Uint64 b.RunParallel(func(pb *testing.PB) { for pb.Next() { - GetEphemeralPublicKey(&packed, txKey, i.Load()) + GetEphemeralPublicKeyAndViewTag(&packed, txKey, i.Load()) } }) } @@ -77,3 +77,18 @@ func BenchmarkCoinbaseDerivationInline(b *testing.B) { } }) } + +func BenchmarkCoinbaseDerivationNoAllocate(b *testing.B) { + packed := testAddress3.ToPackedAddress() + + txKey := (*crypto.PrivateKeyScalar)(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) + } + }) +} diff --git a/monero/address/crypto.go b/monero/address/crypto.go index 9da8df6..4da4ab6 100644 --- a/monero/address/crypto.go +++ b/monero/address/crypto.go @@ -2,7 +2,7 @@ package address import ( "encoding/binary" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/moneroutil" "git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto" p2poolcrypto "git.gammaspectra.live/P2Pool/p2pool-observer/p2pool/crypto" @@ -25,7 +25,7 @@ func GetEphemeralPublicKey(a Interface, txKey crypto.PrivateKey, outputIndex uin func getEphemeralPublicKeyInline(spendPub, viewPub *edwards25519.Point, txKey *edwards25519.Scalar, outputIndex uint64, p *edwards25519.Point) { //derivation - p.ScalarMult(txKey, viewPub).MultByCofactor(p) + p.UnsafeVarTimeScalarMult(txKey, viewPub).MultByCofactor(p) derivationAsBytes := p.Bytes() var varIntBuf [binary.MaxVarintLen64]byte @@ -47,7 +47,7 @@ func GetEphemeralPublicKeyAndViewTagNoAllocate(a *PackedAddress, txKey *crypto.P var spendPublicKeyPoint, viewPublicKeyPoint, point, cofactor, intermediatePublicKey, ephemeralPublicKey edwards25519.Point _, _ = spendPublicKeyPoint.SetBytes((*a)[0][:]) _, _ = viewPublicKeyPoint.SetBytes((*a)[1][:]) - point.ScalarMult(scalar, &viewPublicKeyPoint) + point.UnsafeVarTimeScalarMult(scalar, &viewPublicKeyPoint) cofactor.MultByCofactor(&point) pK, viewTag := crypto.GetDerivationSharedDataAndViewTagForOutputIndexNoAllocate(crypto.PublicKeyBytes(cofactor.Bytes()), outputIndex, hasher) diff --git a/monero/address/interface.go b/monero/address/interface.go index 5044f5e..8bf98c0 100644 --- a/monero/address/interface.go +++ b/monero/address/interface.go @@ -9,8 +9,8 @@ type Interface interface { PublicKeys() (spend, view crypto.PublicKey) - SpendPublicKey() crypto.PublicKey - ViewPublicKey() crypto.PublicKey + SpendPublicKey() *crypto.PublicKeyBytes + ViewPublicKey() *crypto.PublicKeyBytes ToAddress(network uint8, err ...error) *Address ToPackedAddress() PackedAddress diff --git a/monero/address/packed.go b/monero/address/packed.go index 4fc6688..e19f9fb 100644 --- a/monero/address/packed.go +++ b/monero/address/packed.go @@ -2,7 +2,6 @@ package address import ( "git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto" - "runtime" "unsafe" ) @@ -22,11 +21,11 @@ func (p *PackedAddress) PublicKeys() (spend, view crypto.PublicKey) { return &(*p)[0], &(*p)[1] } -func (p *PackedAddress) SpendPublicKey() crypto.PublicKey { +func (p *PackedAddress) SpendPublicKey() *crypto.PublicKeyBytes { return &(*p)[0] } -func (p *PackedAddress) ViewPublicKey() crypto.PublicKey { +func (p *PackedAddress) ViewPublicKey() *crypto.PublicKeyBytes { return &(*p)[1] } @@ -35,75 +34,28 @@ func (p *PackedAddress) ToPackedAddress() PackedAddress { } // Compare special consensus comparison -func (p *PackedAddress) Compare(otherI Interface) int { - other := otherI.ToPackedAddress() - //golang might free other otherwise - defer runtime.KeepAlive(other) - defer runtime.KeepAlive(p) - a := (*[(2 * crypto.PublicKeySize) / 8]uint64)(unsafe.Pointer(p)) - b := (*[(2 * crypto.PublicKeySize) / 8]uint64)(unsafe.Pointer(&other)) - +func (p *PackedAddress) Compare(b Interface) int { //compare spend key - if a[3] < b[3] { - return -1 - } - if a[3] > b[3] { - return 1 + resultSpendKey := crypto.CompareConsensusPublicKeyBytes(p[0], *b.SpendPublicKey()) + if resultSpendKey != 0 { + return resultSpendKey } - if a[2] < b[2] { - return -1 - } - if a[2] > b[2] { - return 1 + // compare view key + return crypto.CompareConsensusPublicKeyBytes(p[1], *b.ViewPublicKey()) +} + +func (p PackedAddress) ComparePacked(other PackedAddress) int { + //compare spend key + + resultSpendKey := crypto.CompareConsensusPublicKeyBytes(p[0], other[0]) + if resultSpendKey != 0 { + return resultSpendKey } - if a[1] < b[1] { - return -1 - } - if a[1] > b[1] { - return 1 - } - - if a[0] < b[0] { - return -1 - } - if a[0] > b[0] { - return 1 - } - - //compare view key - - if a[4+3] < b[4+3] { - return -1 - } - if a[4+3] > b[4+3] { - return 1 - } - - if a[4+2] < b[4+2] { - return -1 - } - if a[4+2] > b[4+2] { - return 1 - } - - if a[4+1] < b[4+1] { - return -1 - } - if a[4+1] > b[4+1] { - return 1 - } - - if a[4+0] < b[4+0] { - return -1 - } - if a[4+0] > b[4+0] { - return 1 - } - - return 0 + // compare view key + return crypto.CompareConsensusPublicKeyBytes(p[1], other[1]) } func (p *PackedAddress) ToAddress(network uint8, err ...error) *Address { diff --git a/monero/crypto/constants.go b/monero/crypto/constants.go index ac046a9..b9ab0d9 100644 --- a/monero/crypto/constants.go +++ b/monero/crypto/constants.go @@ -1,6 +1,6 @@ package crypto -import "filippo.io/edwards25519" +import "git.gammaspectra.live/P2Pool/edwards25519" var infinityPoint = edwards25519.NewIdentityPoint() var zeroScalar = edwards25519.NewScalar() diff --git a/monero/crypto/crypto.go b/monero/crypto/crypto.go index 5871506..9d2fc09 100644 --- a/monero/crypto/crypto.go +++ b/monero/crypto/crypto.go @@ -1 +1,45 @@ package crypto + +import ( + "runtime" + "unsafe" +) + +// CompareConsensusPublicKeyBytes Compares public keys in a special consensus specific way +func CompareConsensusPublicKeyBytes(a, b PublicKeyBytes) int { + aUint64 := (*[PublicKeySize / 8]uint64)(unsafe.Pointer(&a)) + bUint64 := (*[PublicKeySize / 8]uint64)(unsafe.Pointer(&b)) + + if aUint64[3] < bUint64[3] { + return -1 + } + if aUint64[3] > bUint64[3] { + return 1 + } + + if aUint64[2] < bUint64[2] { + return -1 + } + if aUint64[2] > bUint64[2] { + return 1 + } + + if aUint64[1] < bUint64[1] { + return -1 + } + if aUint64[1] > bUint64[1] { + return 1 + } + + if aUint64[0] < bUint64[0] { + return -1 + } + if aUint64[0] > bUint64[0] { + return 1 + } + + //golang might free other otherwise + runtime.KeepAlive(aUint64) + runtime.KeepAlive(bUint64) + return 0 +} diff --git a/monero/crypto/derivations.go b/monero/crypto/derivations.go index 7dcdb59..b858629 100644 --- a/monero/crypto/derivations.go +++ b/monero/crypto/derivations.go @@ -2,7 +2,7 @@ package crypto import ( "encoding/binary" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "git.gammaspectra.live/P2Pool/sha3" ) diff --git a/monero/crypto/derivations_test.go b/monero/crypto/derivations_test.go index 07fb9ab..ff09481 100644 --- a/monero/crypto/derivations_test.go +++ b/monero/crypto/derivations_test.go @@ -2,7 +2,7 @@ package crypto import ( "encoding/hex" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "testing" ) diff --git a/monero/crypto/hash.go b/monero/crypto/hash.go index 4ecd578..b6b9b7a 100644 --- a/monero/crypto/hash.go +++ b/monero/crypto/hash.go @@ -1,7 +1,7 @@ package crypto import ( - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/moneroutil" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "git.gammaspectra.live/P2Pool/sha3" diff --git a/monero/crypto/pool.go b/monero/crypto/pool.go index b1e2e83..a302270 100644 --- a/monero/crypto/pool.go +++ b/monero/crypto/pool.go @@ -1,7 +1,7 @@ package crypto import ( - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "git.gammaspectra.live/P2Pool/sha3" "runtime" diff --git a/monero/crypto/private.go b/monero/crypto/private.go index fabb047..2d8f1ba 100644 --- a/monero/crypto/private.go +++ b/monero/crypto/private.go @@ -6,7 +6,7 @@ import ( "encoding/hex" "encoding/json" "errors" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" ) type PrivateKey interface { diff --git a/monero/crypto/public.go b/monero/crypto/public.go index 935ca9b..5e7a676 100644 --- a/monero/crypto/public.go +++ b/monero/crypto/public.go @@ -6,7 +6,7 @@ import ( "encoding/hex" "encoding/json" "errors" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" ) type PublicKey interface { diff --git a/monero/crypto/random.go b/monero/crypto/random.go index 4b5cbcb..fb52260 100644 --- a/monero/crypto/random.go +++ b/monero/crypto/random.go @@ -3,7 +3,7 @@ package crypto import ( "crypto/rand" "encoding/binary" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "unsafe" ) diff --git a/monero/crypto/signature.go b/monero/crypto/signature.go index c42c0bb..a73b008 100644 --- a/monero/crypto/signature.go +++ b/monero/crypto/signature.go @@ -1,7 +1,7 @@ package crypto import ( - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/types" ) diff --git a/p2pool/api/p2poolapi.go b/p2pool/api/p2poolapi.go index 3e8314b..a9bcd86 100644 --- a/p2pool/api/p2poolapi.go +++ b/p2pool/api/p2poolapi.go @@ -34,7 +34,7 @@ func NewP2PoolApi(host string) *P2PoolApi { Client: &http.Client{ Timeout: time.Second * 15, }, - derivationCache: sidechain.NewDerivationCache(), + derivationCache: sidechain.NewDerivationLRUCache(), difficultyByHeightCache: lru.New[uint64, types.Difficulty](1024), } } diff --git a/p2pool/cache/archive/archive.go b/p2pool/cache/archive/archive.go index 854a1c4..222f925 100644 --- a/p2pool/cache/archive/archive.go +++ b/p2pool/cache/archive/archive.go @@ -54,7 +54,7 @@ func NewCache(path string, consensus *sidechain.Consensus, difficultyByHeight bl consensus: consensus, difficultyByHeight: difficultyByHeight, preAllocatedSharesPool: sidechain.NewPreAllocatedSharesPool(consensus.ChainWindowSize * 2), - derivationCache: sidechain.NewDerivationCache(), + derivationCache: sidechain.NewDerivationLRUCache(), }, nil } } diff --git a/p2pool/crypto/crypto_test.go b/p2pool/crypto/crypto_test.go index f985534..140859e 100644 --- a/p2pool/crypto/crypto_test.go +++ b/p2pool/crypto/crypto_test.go @@ -2,7 +2,7 @@ package crypto import ( "encoding/hex" - "filippo.io/edwards25519" + "git.gammaspectra.live/P2Pool/edwards25519" "git.gammaspectra.live/P2Pool/p2pool-observer/monero/crypto" "git.gammaspectra.live/P2Pool/p2pool-observer/types" "os" diff --git a/p2pool/mainchain/mainchain.go b/p2pool/mainchain/mainchain.go index 2c90912..4c9f9c0 100644 --- a/p2pool/mainchain/mainchain.go +++ b/p2pool/mainchain/mainchain.go @@ -463,6 +463,11 @@ func (c *MainChain) HandleMinerData(minerData *p2pooltypes.MinerData) { log.Printf("[MainChain] new miner data: major_version = %d, height = %d, prev_id = %s, seed_hash = %s, difficulty = %s", minerData.MajorVersion, minerData.Height, minerData.PrevId.String(), minerData.SeedHash.String(), minerData.Difficulty.StringNumeric()) + // Tx secret keys from all miners change every block, so cache can be cleared here + if c.sidechain.PreCalcFinished() { + c.sidechain.DerivationCache().Clear() + } + if c.p2pool.Started() { for h := minerData.Height; h > 0 && (h+BlockHeadersRequired) > minerData.Height; h-- { if d, ok := c.mainchainByHeight[h]; !ok || d.Difficulty.Equals(types.ZeroDifficulty) { diff --git a/p2pool/sidechain/cache.go b/p2pool/sidechain/cache.go index a4aaf77..934a1b8 100644 --- a/p2pool/sidechain/cache.go +++ b/p2pool/sidechain/cache.go @@ -5,9 +5,8 @@ import ( "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/p2pool-observer/utils" "git.gammaspectra.live/P2Pool/sha3" - "github.com/floatdrop/lru" - "sync/atomic" ) type deterministicTransactionCacheKey [crypto.PublicKeySize + types.HashSize]byte @@ -24,23 +23,29 @@ type DerivationCacheInterface interface { } 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 + deterministicKeyCache utils.Cache[deterministicTransactionCacheKey, *crypto.KeyPair] + ephemeralPublicKeyCache utils.Cache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag] } -func NewDerivationCache() *DerivationCache { - d := &DerivationCache{} - d.Clear() +func NewDerivationLRUCache() *DerivationCache { + d := &DerivationCache{ + deterministicKeyCache: utils.NewLRUCache[deterministicTransactionCacheKey, *crypto.KeyPair](32), + ephemeralPublicKeyCache: utils.NewLRUCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000), + } + return d +} + +func NewDerivationMapCache() *DerivationCache { + d := &DerivationCache{ + deterministicKeyCache: utils.NewMapCache[deterministicTransactionCacheKey, *crypto.KeyPair](32), + ephemeralPublicKeyCache: utils.NewMapCache[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000), + } return d } func (d *DerivationCache) Clear() { - d.deterministicKeyCache.Store(lru.New[deterministicTransactionCacheKey, *crypto.KeyPair](32)) - d.ephemeralPublicKeyCache.Store(lru.New[ephemeralPublicKeyCacheKey, ephemeralPublicKeyWithViewTag](2000)) + d.deterministicKeyCache.Clear() + d.ephemeralPublicKeyCache.Clear() } func (d *DerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, txKeySlice crypto.PrivateKeySlice, txKeyScalar *crypto.PrivateKeyScalar, outputIndex uint64, hasher *sha3.HasherState) (crypto.PublicKeyBytes, uint8) { @@ -49,15 +54,12 @@ func (d *DerivationCache) GetEphemeralPublicKey(a *address.PackedAddress, txKeyS 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 - } else { - d.ephemeralPublicKeyCacheHits.Add(1) + if ephemeralPubKey, ok := d.ephemeralPublicKeyCache.Get(key); ok { return ephemeralPubKey.PublicKey, ephemeralPubKey.ViewTag + } else { + pKB, viewTag := address.GetEphemeralPublicKeyAndViewTagNoAllocate(a, txKeyScalar, outputIndex, hasher) + d.ephemeralPublicKeyCache.Set(key, ephemeralPublicKeyWithViewTag{PublicKey: pKB, ViewTag: viewTag}) + return pKB, viewTag } } @@ -66,14 +68,11 @@ func (d *DerivationCache) GetDeterministicTransactionKey(seed types.Hash, prevId copy(key[:], seed[:]) copy(key[types.HashSize:], prevId[:]) - deterministicKeyCache := d.deterministicKeyCache.Load() - if kp := deterministicKeyCache.Get(key); kp == nil { - d.deterministicKeyCacheMisses.Add(1) - data := crypto.NewKeyPairFromPrivate(address.GetDeterministicTransactionPrivateKey(seed, prevId)) - deterministicKeyCache.Set(key, data) - return data + if kp, ok := d.deterministicKeyCache.Get(key); ok { + return kp } else { - d.deterministicKeyCacheHits.Add(1) - return *kp + data := crypto.NewKeyPairFromPrivate(address.GetDeterministicTransactionPrivateKey(seed, prevId)) + d.deterministicKeyCache.Set(key, data) + return data } } diff --git a/p2pool/sidechain/sidechain.go b/p2pool/sidechain/sidechain.go index b948756..8203bec 100644 --- a/p2pool/sidechain/sidechain.go +++ b/p2pool/sidechain/sidechain.go @@ -82,7 +82,7 @@ type SideChain struct { func NewSideChain(server P2PoolInterface) *SideChain { s := &SideChain{ - derivationCache: NewDerivationCache(), + derivationCache: NewDerivationMapCache(), server: server, blocksByTemplateId: make(map[types.Hash]*PoolBlock), blocksByHeight: make(map[uint64][]*PoolBlock), diff --git a/p2pool/sidechain/sidechain_test.go b/p2pool/sidechain/sidechain_test.go index 4f89d02..b4698a3 100644 --- a/p2pool/sidechain/sidechain_test.go +++ b/p2pool/sidechain/sidechain_test.go @@ -140,14 +140,13 @@ func TestSideChainMini(t *testing.T) { t.Fatal() } - hits, misses := s.DerivationCache().ephemeralPublicKeyCacheHits.Load(), s.DerivationCache().ephemeralPublicKeyCacheMisses.Load() + hits, misses := s.DerivationCache().ephemeralPublicKeyCache.Stats() total := hits + misses log.Printf("Ephemeral Public 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().deterministicKeyCacheHits.Load(), s.DerivationCache().deterministicKeyCacheMisses.Load() + 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) - } type fakeServer struct { diff --git a/p2pool/sidechain/utils.go b/p2pool/sidechain/utils.go index 8dad708..65aa1db 100644 --- a/p2pool/sidechain/utils.go +++ b/p2pool/sidechain/utils.go @@ -228,7 +228,7 @@ func GetShares(tip *PoolBlock, consensus *Consensus, difficultyByHeight block.Ge // Sort shares based on address slices.SortFunc(shares, func(a *Share, b *Share) bool { - return a.Address.Compare(&b.Address) < 0 + return a.Address.ComparePacked(b.Address) < 0 }) //remove dupes diff --git a/utils/cache.go b/utils/cache.go new file mode 100644 index 0000000..ee9e00f --- /dev/null +++ b/utils/cache.go @@ -0,0 +1,105 @@ +package utils + +import ( + "github.com/floatdrop/lru" + "sync" + "sync/atomic" +) + +type Cache[K comparable, T any] interface { + Get(key K) (value T, ok bool) + Set(key K, value T) + Delete(key K) + Clear() + Stats() (hits, misses uint64) +} + +type LRUCache[K comparable, T any] struct { + values atomic.Pointer[lru.LRU[K, T]] + hits, misses atomic.Uint64 + size int +} + +func NewLRUCache[K comparable, T any](size int) *LRUCache[K, T] { + c := &LRUCache[K, T]{ + size: size, + } + c.Clear() + return c +} + +func (c *LRUCache[K, T]) Get(key K) (value T, ok bool) { + if v := c.values.Load().Get(key); v != nil { + c.hits.Add(1) + return *v, true + } else { + c.misses.Add(1) + return value, false + } +} + +func (c *LRUCache[K, T]) Set(key K, value T) { + c.values.Load().Set(key, value) +} + +func (c *LRUCache[K, T]) Delete(key K) { + c.values.Load().Remove(key) +} + +func (c *LRUCache[K, T]) Clear() { + c.values.Store(lru.New[K, T](c.size)) +} + +func (c *LRUCache[K, T]) Stats() (hits, misses uint64) { + return c.hits.Load(), c.misses.Load() +} + +type MapCache[K comparable, T any] struct { + lock sync.RWMutex + values map[K]T + hits, misses atomic.Uint64 + size int +} + +func NewMapCache[K comparable, T any](preAllocateSize int) *MapCache[K, T] { + return &MapCache[K, T]{ + values: make(map[K]T, preAllocateSize), + size: preAllocateSize, + } +} + +func (m *MapCache[K, T]) Get(key K) (value T, ok bool) { + m.lock.RLock() + defer m.lock.RUnlock() + value, ok = m.values[key] + if ok { + m.hits.Add(1) + } else { + m.misses.Add(1) + } + return value, ok +} + +func (m *MapCache[K, T]) Set(key K, value T) { + m.lock.Lock() + defer m.lock.Unlock() + m.values[key] = value +} + +func (m *MapCache[K, T]) Delete(key K) { + m.lock.Lock() + defer m.lock.Unlock() + delete(m.values, key) +} + +func (m *MapCache[K, T]) Clear() { + m.lock.Lock() + defer m.lock.Unlock() + m.values = make(map[K]T, m.size) +} + +func (m *MapCache[K, T]) Stats() (hits, misses uint64) { + m.lock.Lock() + defer m.lock.Unlock() + return m.hits.Load(), m.misses.Load() +}