Skip to content

Commit

Permalink
Fix outputs for sweep transactions (#399)
Browse files Browse the repository at this point in the history
* Added consts for sweep min tx amount in sats, conf target

* Fix creating dust utxos and 100K utxos, now we require a min amount to be swept out of the LND hot wallet, this shall ensure that there's more than a 100K utxo in the wallet

* bump to 25M sats minimum default sweep tx
  • Loading branch information
Jossec101 authored Oct 28, 2024
1 parent 208bb35 commit d3cbf59
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
13 changes: 13 additions & 0 deletions src/Helpers/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public class Constants
public static readonly decimal MAXIMUM_WITHDRAWAL_BTC_AMOUNT = 21_000_000;
public static readonly int TRANSACTION_CONFIRMATION_MINIMUM_BLOCKS;
public static readonly long ANCHOR_CLOSINGS_MINIMUM_SATS;
public static readonly long MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS = 25_000_000; //25M sats
public static readonly string DEFAULT_DERIVATION_PATH = "48'/1'";
public static readonly int SESSION_TIMEOUT_MILLISECONDS = 3_600_000;

Expand All @@ -86,6 +87,11 @@ public class Constants
/// </summary>
public static decimal MAX_TX_FEE_RATIO = 0.5m;

/// <summary>
/// The target number of confirmations blocks (fee rate) for the sweep transaction
/// </summary>
public static int SWEEP_CONF_TARGET = 6;

public const string IsFrozenTag = "frozen";
public const string IsManuallyFrozenTag = "manually_frozen";

Expand Down Expand Up @@ -217,6 +223,13 @@ static Constants()
var anchorClosingMinSats = GetEnvironmentalVariableOrThrowIfNotTesting("ANCHOR_CLOSINGS_MINIMUM_SATS");
if (anchorClosingMinSats != null) ANCHOR_CLOSINGS_MINIMUM_SATS = long.Parse(anchorClosingMinSats); // Check https://github.com/lightningnetwork/lnd/issues/6505#issuecomment-1120364460 to understand, we need 100K+ to support anchor channel closings

var sweepConfTarget = Environment.GetEnvironmentVariable("SWEEP_CONF_TARGET");
if (sweepConfTarget != null) SWEEP_CONF_TARGET = int.Parse(sweepConfTarget);

var minSweepTransactionAmount = Environment.GetEnvironmentVariable("MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS");
if (minSweepTransactionAmount != null) MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS = long.Parse(minSweepTransactionAmount);


DEFAULT_DERIVATION_PATH = GetEnvironmentalVariableOrThrowIfNotTesting("DEFAULT_DERIVATION_PATH") ?? DEFAULT_DERIVATION_PATH;

var timeout = Environment.GetEnvironmentVariable("SESSION_TIMEOUT_MILLISECONDS");
Expand Down
34 changes: 17 additions & 17 deletions src/Jobs/SweepNodeWalletsJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public SweepNodeWalletsJob(ILogger<SweepNodeWalletsJob> logger,
INBXplorerService nbXplorerService,
ILightningClientService lightningClientService)
{

_logger = logger;
_nodeRepository = nodeRepository;
_walletRepository = walletRepository;
Expand All @@ -66,7 +66,7 @@ public async Task Execute(IJobExecutionContext context)
#region Local functions

async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightningClient
,List<Utxo> utxos)
, List<Utxo> utxos)
{
if (node == null) throw new ArgumentNullException(nameof(node));
if (wallet == null) throw new ArgumentNullException(nameof(wallet));
Expand All @@ -81,9 +81,9 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn
if (node.ChannelAdminMacaroon != null)
{
var lndChangeAddress = await lightningClient.NewAddressAsync(new NewAddressRequest
{
Type = AddressType.UnusedWitnessPubkeyHash
},
{
Type = AddressType.UnusedWitnessPubkeyHash
},
new Metadata
{
{
Expand All @@ -92,21 +92,21 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn
});
var totalSatsAvailable = utxos.Sum(x => x.AmountSat);

if (returningAddress != null && lndChangeAddress != null && utxos.Any() && totalSatsAvailable > requiredAnchorChannelClosingAmount)
if (returningAddress != null && lndChangeAddress != null && utxos.Any() && totalSatsAvailable > Constants.MINIMUM_SWEEP_TRANSACTION_AMOUNT_SATS)
{
var sweepedFundsAmount = (long)((totalSatsAvailable - requiredAnchorChannelClosingAmount) * 0.9); // We should let requiredAnchorChannelClosingAmount sats as a UTXO in in the hot wallet for channel closings
// We need to maintain onchain balance to be at least RequiredAnchorChannelClosingAmount but also we apply a 10% buffer to pay for this sweep fees and let some more money on the wallet
var sweepedFundsAmount = (long)((totalSatsAvailable - requiredAnchorChannelClosingAmount) * 0.9);
var sendManyResponse = await lightningClient.SendManyAsync(new SendManyRequest()
{
AddrToAmount =
{
AddrToAmount =
{
{returningAddress.Address.ToString(), sweepedFundsAmount}, //Sweeped funds
{lndChangeAddress.Address, requiredAnchorChannelClosingAmount},
},
MinConfs = 1,
Label = $"Hot wallet Sweep tx on {DateTime.UtcNow.ToString("O")} to walletId:{wallet.Id}",
SpendUnconfirmed = false,
TargetConf = 1 // 1 for now TODO Maybe this can be set as a global env var for all the Target blocks of the FM..
},
MinConfs = 6,
Label = $"Hot wallet Sweep tx on {DateTime.UtcNow.ToString("O")} to walletId:{wallet.Id}",
SpendUnconfirmed = false,
TargetConf = Constants.SWEEP_CONF_TARGET
},
new Metadata
{
{
Expand Down Expand Up @@ -157,9 +157,9 @@ async Task SweepFunds(Node node, Wallet wallet, Lightning.LightningClient lightn

try
{

var client = _lightningClientService.GetLightningClient(node.Endpoint);

var unspentResponse = await client.ListUnspentAsync(new ListUnspentRequest { MinConfs = 1, MaxConfs = Int32.MaxValue }, new Metadata
{
{
Expand Down

0 comments on commit d3cbf59

Please sign in to comment.