diff --git a/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCache.java b/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCache.java index 468e8b7..8ee45f0 100644 --- a/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCache.java +++ b/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCache.java @@ -38,6 +38,8 @@ static LookupTableCache createCache(final ExecutorService executorService, AddressLookupTable getTable(final PublicKey lookupTableKey); + AddressLookupTable putTable(final AddressLookupTable lookupTable); + AddressLookupTable getOrFetchTable(final PublicKey lookupTableKey); LookupTableAccountMeta[] getOrFetchTables(final List lookupTableKeys); diff --git a/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCacheMap.java b/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCacheMap.java index 510bdf3..34f05b8 100644 --- a/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCacheMap.java +++ b/solana/src/main/java/software/sava/services/solana/accounts/lookup/LookupTableCacheMap.java @@ -82,6 +82,11 @@ private AddressLookupTable cacheTable(final AddressLookupTable lookupTable) { return cacheTable(lookupTable, System.currentTimeMillis()); } + @Override + public AddressLookupTable putTable(final AddressLookupTable lookupTable) { + return cacheTable(lookupTable); + } + private Call> createFetchLookupTableCall(final PublicKey lookupTableKey) { return Call.createCall( rpcClients, rpcClient -> rpcClient.getAccountInfo(lookupTableKey, tableFactory), diff --git a/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/DiscoverTablesHandler.java b/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/DiscoverTablesHandler.java index 9718896..65a609f 100644 --- a/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/DiscoverTablesHandler.java +++ b/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/DiscoverTablesHandler.java @@ -16,9 +16,9 @@ abstract class DiscoverTablesHandler extends LookupTableDiscoveryServiceHandler super(tableService, tableCache); } - record QueryParams(boolean accountsOnly, boolean stats, boolean reRank) { + record QueryParams(boolean accountsOnly, boolean stats, boolean reRank, boolean includeProvidedTables) { - static final QueryParams DEFAULT = new QueryParams(false, false, false); + static final QueryParams DEFAULT = new QueryParams(false, false, false, false); } protected final QueryParams queryParams(final HttpExchange exchange) { @@ -27,6 +27,7 @@ protected final QueryParams queryParams(final HttpExchange exchange) { boolean accountsOnly = false; boolean stats = false; boolean reRank = false; + boolean includeProvidedTables = false; for (int from = 0, equals, and, keyLen; ; from = and + 1) { equals = query.indexOf('=', from); if (equals < 0) { @@ -43,12 +44,14 @@ protected final QueryParams queryParams(final HttpExchange exchange) { stats = Boolean.parseBoolean(value); } else if (query.regionMatches(true, from, "reRank", 0, keyLen)) { reRank = Boolean.parseBoolean(value); + } else if (query.regionMatches(true, from, "includeProvidedTables", 0, keyLen)) { + includeProvidedTables = Boolean.parseBoolean(value); } if (and < 1) { break; } } - return new QueryParams(accountsOnly, stats, reRank); + return new QueryParams(accountsOnly, stats, reRank, includeProvidedTables); } else { return DEFAULT; } diff --git a/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/FromRawTxHandler.java b/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/FromRawTxHandler.java index 3ad6c3d..d04373b 100644 --- a/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/FromRawTxHandler.java +++ b/solana/src/main/java/software/sava/services/solana/accounts/lookup/http/FromRawTxHandler.java @@ -192,10 +192,10 @@ protected void handle(final HttpExchange exchange, final int numTableAccounts = lookupTableAccounts.length; final var lookupTables = HashMap.newHashMap(numTableAccounts); List notCached = null; - for (final var key : lookupTableAccounts) { - var lookupTable = tableCache.getTable(key); - if (lookupTable == null) { - lookupTable = tableService.scanForTable(key); + final boolean includeTables = queryParams.includeProvidedTables(); + if (includeTables) { + for (final var key : lookupTableAccounts) { + var lookupTable = tableService.scanForTable(key); if (lookupTable == null) { if (notCached == null) { notCached = new ArrayList<>(numTableAccounts); @@ -203,11 +203,34 @@ protected void handle(final HttpExchange exchange, notCached.add(key); continue; } else { - lookupTable = lookupTable.withReverseLookup(); + final var cachedTable = tableCache.getTable(key); + if (cachedTable == null) { + lookupTable = lookupTable.withReverseLookup(); + tableCache.putTable(lookupTable); + } else { + lookupTable = cachedTable; + } } lookupTables.put(lookupTable.address(), lookupTable); - } else { - lookupTables.put(lookupTable.address(), lookupTable); + } + } else { + for (final var key : lookupTableAccounts) { + var lookupTable = tableCache.getTable(key); + if (lookupTable == null) { + lookupTable = tableService.scanForTable(key); + if (lookupTable == null) { + if (notCached == null) { + notCached = new ArrayList<>(numTableAccounts); + } + notCached.add(key); + continue; + } else { + lookupTable = lookupTable.withReverseLookup(); + } + lookupTables.put(lookupTable.address(), lookupTable); + } else { + lookupTables.put(lookupTable.address(), lookupTable); + } } } @@ -216,14 +239,24 @@ protected void handle(final HttpExchange exchange, if (notCached.size() == 1) { final var table = tableCache.getOrFetchTable(notCached.getFirst()); lookupTables.put(table.address(), table); - includeInDiscovery = new AddressLookupTable[]{table}; + includeInDiscovery = includeTables + ? new AddressLookupTable[]{table} + : NO_INCLUDES; } else { final var tables = tableCache.getOrFetchTables(notCached); - includeInDiscovery = new AddressLookupTable[tables.length]; - for (int i = 0; i < tables.length; ++i) { - final var table = tables[i].lookupTable(); - includeInDiscovery[i] = table; - lookupTables.put(table.address(), table); + if (includeTables) { + includeInDiscovery = new AddressLookupTable[tables.length]; + for (int i = 0; i < tables.length; ++i) { + final var table = tables[i].lookupTable(); + includeInDiscovery[i] = table; + lookupTables.put(table.address(), table); + } + } else { + includeInDiscovery = NO_INCLUDES; + for (final var lookupTableAccountMeta : tables) { + final var table = lookupTableAccountMeta.lookupTable(); + lookupTables.put(table.address(), table); + } } } if (lookupTables.size() != numTableAccounts) { @@ -241,10 +274,9 @@ protected void handle(final HttpExchange exchange, final var accounts = skeleton.parseAccounts(lookupTables); final var instructions = skeleton.parseInstructions(accounts); final long start = System.currentTimeMillis(); - // TODO: Consider adding query param to include given tables or not. final var discoveredTables = queryParams.reRank() ? tableService.discoverTablesWithReRank(instructions, includeInDiscovery) - : tableService.discoverTables(instructions); + : tableService.discoverTables(instructions, includeInDiscovery); if (queryParams.stats()) { final var nonSignerAccounts = Arrays.stream(accounts, skeleton.numSignatures(), accounts.length)