From 20208a696c1b0d16eefabfdfda368d8330f84a12 Mon Sep 17 00:00:00 2001 From: julian Date: Thu, 16 Nov 2023 12:15:28 -0600 Subject: [PATCH] WIP add spark electrumx calls --- lib/db/db_version_migration.dart | 2 +- .../cached_electrumx_client.dart | 4 +- lib/electrumx_rpc/electrumx_client.dart | 137 ++++++++++++++---- lib/services/coins/firo/firo_wallet.dart | 2 +- 4 files changed, 116 insertions(+), 29 deletions(-) diff --git a/lib/db/db_version_migration.dart b/lib/db/db_version_migration.dart index a239ed134..a75d97959 100644 --- a/lib/db/db_version_migration.dart +++ b/lib/db/db_version_migration.dart @@ -89,7 +89,7 @@ class DbVersionMigrator with WalletDB { ); try { - latestSetId = await client.getLatestCoinId(); + latestSetId = await client.getLelantusLatestCoinId(); } catch (e) { // default to 2 for now latestSetId = 2; diff --git a/lib/electrumx_rpc/cached_electrumx_client.dart b/lib/electrumx_rpc/cached_electrumx_client.dart index d42f01ef8..f86d865c3 100644 --- a/lib/electrumx_rpc/cached_electrumx_client.dart +++ b/lib/electrumx_rpc/cached_electrumx_client.dart @@ -55,7 +55,7 @@ class CachedElectrumXClient { set = Map.from(cachedSet); } - final newSet = await electrumXClient.getAnonymitySet( + final newSet = await electrumXClient.getLelantusAnonymitySet( groupId: groupId, blockhash: set["blockHash"] as String, ); @@ -170,7 +170,7 @@ class CachedElectrumXClient { final startNumber = cachedSerials.length - 10; // 10 being some arbitrary buffer - final serials = await electrumXClient.getUsedCoinSerials( + final serials = await electrumXClient.getLelantusUsedCoinSerials( startNumber: startNumber, ); Set newSerials = {}; diff --git a/lib/electrumx_rpc/electrumx_client.dart b/lib/electrumx_rpc/electrumx_client.dart index 4f0ee12ff..7a3e093ba 100644 --- a/lib/electrumx_rpc/electrumx_client.dart +++ b/lib/electrumx_rpc/electrumx_client.dart @@ -751,7 +751,7 @@ class ElectrumXClient { } } - /// Returns the whole anonymity set for denomination in the groupId. + /// Returns the whole Lelantus anonymity set for denomination in the groupId. /// /// ex: /// { @@ -765,7 +765,7 @@ class ElectrumXClient { /// [dynamic list of length 4], /// ] /// } - Future> getAnonymitySet({ + Future> getLelantusAnonymitySet({ String groupId = "1", String blockhash = "", String? requestID, @@ -792,8 +792,11 @@ class ElectrumXClient { //TODO add example to docs /// /// - /// Returns the block height and groupId of pubcoin. - Future getMintData({dynamic mints, String? requestID}) async { + /// Returns the block height and groupId of a Lelantus pubcoin. + Future getLelantusMintData({ + dynamic mints, + String? requestID, + }) async { try { final response = await request( requestID: requestID, @@ -809,8 +812,8 @@ class ElectrumXClient { } //TODO add example to docs - /// Returns the whole set of the used coin serials. - Future> getUsedCoinSerials({ + /// Returns the whole set of the used Lelantus coin serials. + Future> getLelantusUsedCoinSerials({ String? requestID, required int startNumber, }) async { @@ -830,10 +833,10 @@ class ElectrumXClient { } } - /// Returns the latest set id + /// Returns the latest Lelantus set id /// /// ex: 1 - Future getLatestCoinId({String? requestID}) async { + Future getLelantusLatestCoinId({String? requestID}) async { try { final response = await request( requestID: requestID, @@ -846,23 +849,107 @@ class ElectrumXClient { } } - // /// Returns about 13 megabytes of json data as of march 2, 2022 - // Future> getCoinsForRecovery( - // {dynamic setId, String requestID}) async { - // try { - // final response = await request( - // requestID: requestID, - // command: 'lelantus.getcoinsforrecovery', - // args: [ - // setId ?? 1, - // ], - // ); - // return response["result"]; - // } catch (e) { - // Logging.instance.log(e); - // throw e; - // } - // } + // ============== Spark ====================================================== + + // New Spark ElectrumX methods: + // > Functions provided by ElectrumX servers + // > // > + + /// Returns the whole Spark anonymity set for denomination in the groupId. + /// + /// Takes [coinGroupId] and [startBlockHash], if the last is empty it returns full set, + /// otherwise returns mint after that block, we need to call this to keep our + /// anonymity set data up to date. + /// + /// Returns blockHash (last block hash), + /// setHash (hash of current set) + /// and mints (the list of pairs serialized coin and tx hash) + Future> getSparkAnonymitySet({ + String coinGroupId = "1", + String startBlockHash = "", + String? requestID, + }) async { + try { + Logging.instance.log("attempting to fetch spark.getsparkanonymityset...", + level: LogLevel.Info); + final response = await request( + requestID: requestID, + command: 'spark.getsparkanonymityset', + args: [ + coinGroupId, + startBlockHash, + ], + ); + Logging.instance.log("Fetching spark.getsparkanonymityset finished", + level: LogLevel.Info); + return Map.from(response["result"] as Map); + } catch (e) { + rethrow; + } + } + + /// Takes [startNumber], if it is 0, we get the full set, + /// otherwise the used tags after that number + Future> getSparkUsedCoinsTags({ + String? requestID, + required int startNumber, + }) async { + try { + final response = await request( + requestID: requestID, + command: 'spark.getusedcoinstags', + args: [ + "$startNumber", + ], + requestTimeout: const Duration(minutes: 2), + ); + return Map.from(response["result"] as Map); + } catch (e) { + Logging.instance.log(e, level: LogLevel.Error); + rethrow; + } + } + + /// Takes [sparkCoinHashes] and returns the set id and block height + /// for each coin + Future> getSparkMintMetaData({ + String? requestID, + required List sparkCoinHashes, + }) async { + try { + final response = await request( + requestID: requestID, + command: 'spark.getsparkmintmetadata', + args: [ + sparkCoinHashes, + ], + ); + return Map.from(response["result"] as Map); + } catch (e) { + Logging.instance.log(e, level: LogLevel.Error); + rethrow; + } + } + + /// Returns the latest Spark set id + /// + /// ex: 1 + Future getSparkLatestCoinId({ + String? requestID, + }) async { + try { + final response = await request( + requestID: requestID, + command: 'getsparklatestcoinid', + ); + return response["result"] as int; + } catch (e) { + Logging.instance.log(e, level: LogLevel.Error); + rethrow; + } + } + + // =========================================================================== /// Get the current fee rate. /// diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index ba4effbe7..f10e07844 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -4763,7 +4763,7 @@ class FiroWallet extends CoinServiceAPI Future getLatestSetId() async { try { - final id = await electrumXClient.getLatestCoinId(); + final id = await electrumXClient.getLelantusLatestCoinId(); return id; } catch (e, s) { Logging.instance.log("Exception rethrown in firo_wallet.dart: $e\n$s",