@@ -2,14 +2,12 @@ package tapdb
22
33import (
44 "bytes"
5- "crypto/sha256"
65 "slices"
76 "sort"
87 "sync"
98 "sync/atomic"
109
1110 "github.com/lightninglabs/neutrino/cache/lru"
12- "github.com/lightninglabs/taproot-assets/fn"
1311 "github.com/lightninglabs/taproot-assets/universe"
1412 "github.com/lightningnetwork/lnd/lnutils"
1513)
@@ -67,26 +65,6 @@ func DefaultMultiverseCacheConfig() MultiverseCacheConfig {
6765 }
6866}
6967
70- // ProofKey is used to uniquely identify a proof within a universe. This is
71- // used for the LRU cache for the proofs themselves, which are considered to be
72- // immutable.
73- type ProofKey [32 ]byte
74-
75- // NewProofKey takes a universe identifier and leaf key, and returns a proof
76- // key.
77- func NewProofKey (id universe.Identifier , key universe.LeafKey ) ProofKey {
78- idBytes := id .Bytes ()
79- leafKeyBytes := key .UniverseKey ()
80-
81- // The proof key maps down the ID and the leaf key into a single
82- // 32-byte value: sha256(id || leaf_key)..
83- h := sha256 .New ()
84- h .Write (idBytes [:])
85- h .Write (leafKeyBytes [:])
86-
87- return fn.ToArray [ProofKey ](h .Sum (nil ))
88- }
89-
9068// cachedProofs is a list of cached proof leaves.
9169type cachedProofs []* universe.Proof
9270
@@ -95,52 +73,81 @@ type cachedProofs []*universe.Proof
9573// if the universe key's script key isn't set. But we only want a certain number
9674// of different keys stored in the cache.
9775func (c * cachedProofs ) Size () (uint64 , error ) {
98- return 1 , nil
76+ if c == nil {
77+ return 0 , nil
78+ }
79+
80+ totalBytes := uint64 (0 )
81+ for _ , proof := range * c {
82+ if proof == nil {
83+ continue
84+ }
85+
86+ totalBytes += proof .LowerBoundByteSize ()
87+ }
88+
89+ return totalBytes , nil
9990}
10091
10192// newProofCache creates a new leaf proof cache.
102- func newProofCache (proofCacheSize uint64 ) * lru.Cache [ProofKey , * cachedProofs ] {
103- return lru.NewCache [ProofKey , * cachedProofs ](proofCacheSize )
93+ //
94+ // nolint: lll
95+ func newProofCache (totalCacheBytesSize uint64 ) * lru.Cache [UniverseProofKey , * cachedProofs ] {
96+ return lru.NewCache [UniverseProofKey , * cachedProofs ](
97+ totalCacheBytesSize ,
98+ )
10499}
105100
106101// universeIDKey is a cache key used to uniquely identify a universe within a
107102// multiverse tree cache.
108103type universeIDKey = string
109104
105+ // UniverseProofKey houses the components of a universe proof key. All fields
106+ // must be comparable.
107+ type UniverseProofKey struct {
108+ // uniIDKey is the universe ID key to which the proof belongs.
109+ uniIDKey universe.IdentifierKey
110+
111+ // leafKey is the leaf key of the proof.
112+ leafKeyBytes [32 ]byte
113+ }
114+
115+ // NewUniverseProofKey creates a new universe proof key.
116+ func NewUniverseProofKey (uniID universe.Identifier ,
117+ leafKey universe.LeafKey ) UniverseProofKey {
118+
119+ return UniverseProofKey {
120+ uniIDKey : uniID .Key (),
121+ leafKeyBytes : leafKey .UniverseKey (),
122+ }
123+ }
124+
110125// universeProofCache a map of proof caches for each proof type.
111126type universeProofCache struct {
112- proofsPerUniverse uint64
127+ // maxCacheByteSize is the maximum size of the cache in bytes.
128+ maxCacheByteSize uint64
113129
114- lnutils.SyncMap [universeIDKey , * lru.Cache [ProofKey , * cachedProofs ]]
130+ // cache is the LRU cache for the proofs themselves.
131+ cache * lru.Cache [UniverseProofKey , * cachedProofs ]
115132
116133 * cacheLogger
117134}
118135
119136// newUniverseProofCache creates a new proof cache.
120- func newUniverseProofCache (proofsPerUniverse uint64 ) * universeProofCache {
137+ func newUniverseProofCache (maxCacheByteSize uint64 ) * universeProofCache {
121138 return & universeProofCache {
122- proofsPerUniverse : proofsPerUniverse ,
123- SyncMap : lnutils.SyncMap [
124- universeIDKey , * lru.Cache [ProofKey , * cachedProofs ],
125- ]{},
126- cacheLogger : newCacheLogger ("universe_proofs" ),
139+ maxCacheByteSize : maxCacheByteSize ,
140+ cache : newProofCache (maxCacheByteSize ),
141+ cacheLogger : newCacheLogger ("universe_proofs" ),
127142 }
128143}
129144
130145// fetchProof reads the cached proof for the given ID and leaf key.
131146func (p * universeProofCache ) fetchProof (id universe.Identifier ,
132147 leafKey universe.LeafKey ) []* universe.Proof {
133148
134- // First, get the sub-cache for this universe ID from the map of
135- // caches.
136- assetProofCache , _ := p .LoadOrStore (
137- id .String (), newProofCache (p .proofsPerUniverse ),
138- )
139-
140- // With that lower level cache obtained, we can check to see if we have
141- // a hit or not.
142- proofKey := NewProofKey (id , leafKey )
143- proofFromCache , err := assetProofCache .Get (proofKey )
149+ uniProofKey := NewUniverseProofKey (id , leafKey )
150+ proofFromCache , err := p .cache .Get (uniProofKey )
144151 if err == nil {
145152 p .Hit ()
146153 return * proofFromCache
@@ -155,28 +162,52 @@ func (p *universeProofCache) fetchProof(id universe.Identifier,
155162func (p * universeProofCache ) insertProofs (id universe.Identifier ,
156163 leafKey universe.LeafKey , proofs []* universe.Proof ) {
157164
158- assetProofCache , _ := p .LoadOrStore (
159- id .String (), newProofCache (p .proofsPerUniverse ),
160- )
161-
162- proofKey := NewProofKey (id , leafKey )
165+ uniProofKey := NewUniverseProofKey (id , leafKey )
163166
164167 log .Debugf ("Storing proof(s) in cache (universe_id=%v, leaf_key=%v, " +
165- "proof_key=%x, count=%d)" , id .StringForLog (), leafKey ,
166- proofKey [:], len (proofs ))
168+ "count=%d)" , id .StringForLog (), leafKey , len (proofs ))
167169
168170 proofVal := cachedProofs (proofs )
169- if _ , err := assetProofCache . Put (proofKey , & proofVal ); err != nil {
171+ if _ , err := p . cache . Put (uniProofKey , & proofVal ); err != nil {
170172 log .Errorf ("Unable to insert proof into universe proof " +
171173 "cache: %v" , err )
172174 }
173175}
174176
175- // delProofsForAsset deletes all the proofs for the given asset.
176- func (p * universeProofCache ) delProofsForAsset (id universe.Identifier ) {
177- log .Debugf ("Wiping universe proof cache (universe_id=%v)" , id )
177+ // RemoveUniverseProofs deletes all the proofs for the given universe ID.
178+ func (p * universeProofCache ) RemoveUniverseProofs (id universe.Identifier ) {
179+ log .Debugf ("Removing universe proofs (universe_id=%s)" ,
180+ id .StringForLog ())
178181
179- p .Delete (id .String ())
182+ targetIDKey := id .Key ()
183+ p .cache .Range (
184+ func (key UniverseProofKey , proofs * cachedProofs ) bool {
185+ if key .uniIDKey == targetIDKey {
186+ p .cache .Delete (key )
187+ }
188+ return true
189+ },
190+ )
191+ }
192+
193+ // RemoveLeafKeyProofs deletes all the proofs for the given universe ID and leaf
194+ // key.
195+ func (p * universeProofCache ) RemoveLeafKeyProofs (id universe.Identifier ,
196+ leafKey universe.LeafKey ) {
197+
198+ log .Debugf ("Removing leaf key proofs (universe_id=%s, leaf_key=%v)" ,
199+ id .StringForLog (), leafKey )
200+
201+ targetCacheKey := NewUniverseProofKey (id , leafKey )
202+
203+ p .cache .Range (
204+ func (key UniverseProofKey , proofs * cachedProofs ) bool {
205+ if key == targetCacheKey {
206+ p .cache .Delete (key )
207+ }
208+ return true
209+ },
210+ )
180211}
181212
182213// rootPageQueryKey is a cache key that wraps around a query to fetch all the
0 commit comments