The Selector Service (token/services/selector) implements strategic token selection algorithms to ensure that Panurus can efficiently and correctly select the best set of unspent tokens (UTXOs) for any given transaction.
The Selector Service is responsible for:
The Selector Service bridges the gap between the high-level TTX Service and the internal TokenDB.
graph LR
TTX[TTX Service] --> Selector[Selector Service]
subgraph "Token Fetcher"
Fetcher[Fetcher Logic]
Fetcher -->|Cache Hit| Cache[Cache]
Fetcher -->|Cache Miss| TokenDB[Token Store - TokenDB]
end
subgraph "Selection Logic"
Query[Query Spendable Tokens]
Strategy[Apply Selection Strategy]
Lock[Acquire Temporary Lock]
end
Selector --> Fetcher
Selector --> Query
Query --> Strategy
Strategy --> Lock
How the components interact:
The SelectorManager is the entry point for obtaining a Selector instance anchored to a specific transaction. It ensures that the selection process is consistent and tied to the lifecycle of a single token request.
The service supports various strategies for picking tokens (see “Strategy” box in diagram above). A common strategy is to pick the smallest number of tokens that cover the requested amount to minimize the transaction size and the associated verification overhead on the ledger.
How it works in the flow (see “Selection Logic” subgraph in diagram):
To prevent double-spending before the transaction is committed to the ledger, the Selector Service uses a local TokenLocks table in the Storage Service (see “TokenLocks” box in diagram above).
Lock lifecycle:
TokenLocks table.The selector uses a Token Fetcher to retrieve available tokens from the database. The fetcher uses a Ristretto LRU cache to improve performance by caching token queries (keyed by wallet+currency).
Flow: Selector.Select() → Fetcher.UnspentTokensIteratorBy(wallet, currency) → Token Iterator
How it works:
Adaptive refresh strategy with two triggers:
fetcherCacheRefreshfetcherCacheMaxQueries queries to prevent serving stale data in high-throughput scenariosConfigure the selector service in your core.yaml:
token:
selector:
driver: sherdlock # Selection strategy (default: sherdlock)
numRetries: 3 # Retry attempts for token selection (default: 3)
retryInterval: 5s # Wait time between retries (default: 5s)
leaseExpiry: 3m # Lock expiration time (default: 3m)
leaseCleanupTickPeriod: 1m # Lock cleanup interval (default: 1m)
fetcherCacheSize: 1000 # Cache size in entries (default: 0 = use fetcher default)
fetcherCacheRefresh: 30s # Cache refresh interval (default: 0 = use fetcher default)
fetcherCacheMaxQueries: 100 # Max queries before cache refresh (default: 0 = use fetcher default)
The fetcher cache improves performance by caching token queries:
Example: With fetcherCacheSize: 1000, fetcherCacheRefresh: 30s, and fetcherCacheMaxQueries: 100, the cache stores up to 1000 query results, refreshes data every 30 seconds, and forces a refresh after 100 queries.