Skip to content

Commit

Permalink
add shameful payjoin implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
Kukks committed Mar 3, 2020
1 parent fb57c90 commit 56bba9d
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@
<behaviors:PasteAddressOnClickBehavior Command="{Binding OnAddressPasteCommand}" />
</i:Interaction.Behaviors>
</controls:ExtendedTextBox>

<controls:ExtendedTextBox Classes="monospaceFont" Text="{Binding BIP79Url}" Watermark="Payjoin endpoint" UseFloatingWatermark="True">
<i:Interaction.Behaviors>
<behaviors:PasteAddressOnClickBehavior Command="{Binding OnAddressPasteCommand}" />
</i:Interaction.Behaviors>
</controls:ExtendedTextBox>
<controls:SuggestLabelView DataContext="{Binding LabelSuggestion}" />

<StackPanel Orientation="Horizontal" Spacing="10">
Expand Down
32 changes: 31 additions & 1 deletion WalletWasabi.Gui/Controls/WalletExplorer/SendControlViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public abstract class SendControlViewModel : WasabiDocumentTabViewModel
private bool _isBusy;
private bool _isHardwareBusy;
private bool _isCustomFee;
private string _bip79;

private const string WaitingForHardwareWalletButtonTextString = "Waiting for Hardware Wallet...";

Expand Down Expand Up @@ -231,6 +232,15 @@ protected SendControlViewModel(WalletService walletService, string title)
{
AmountText = url.Amount.ToString(false, true);
}
if (url.UnknowParameters.ContainsKey("bpu"))
{
BIP79Url = url.UnknowParameters["bpu"];
}
else
{
BIP79Url = "";
}
});

BuildTransactionCommand = ReactiveCommand.CreateFromTask(async () =>
Expand Down Expand Up @@ -341,7 +351,7 @@ protected SendControlViewModel(WalletService walletService, string title)
}
}
BuildTransactionResult result = await Task.Run(() => WalletService.BuildTransaction(Password, intent, feeStrategy, allowUnconfirmed: true, allowedInputs: selectedCoinReferences));
BuildTransactionResult result = await Task.Run(() => WalletService.BuildTransaction(Password, intent, feeStrategy, allowUnconfirmed: true, allowedInputs: selectedCoinReferences, BIP79Url));
await DoAfterBuildTransaction(result);
}
Expand Down Expand Up @@ -785,13 +795,33 @@ public ErrorDescriptors ValidateAddress()

return new ErrorDescriptors(new ErrorDescriptor(ErrorSeverity.Error, "Invalid address."));
}

public ErrorDescriptors ValidateBIP79Url()
{
if (string.IsNullOrEmpty(BIP79Url))
{
return ErrorDescriptors.Empty;
}
if (Uri.TryCreate(BIP79Url, UriKind.Absolute, out _))
{
return ErrorDescriptors.Empty;
}
return new ErrorDescriptors(new ErrorDescriptor(ErrorSeverity.Error, "Invalid url."));
}

[ValidateMethod(nameof(ValidateAddress))]
public string Address
{
get => _address;
set => this.RaiseAndSetIfChanged(ref _address, value);
}

[ValidateMethod(nameof(ValidateBIP79Url))]
public string BIP79Url
{
get => _bip79;
set => this.RaiseAndSetIfChanged(ref _bip79, value);
}

public string LabelToolTip
{
Expand Down
43 changes: 42 additions & 1 deletion WalletWasabi/Blockchain/Transactions/TransactionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using WalletWasabi.Blockchain.Analysis.Clustering;
using WalletWasabi.Blockchain.Keys;
using WalletWasabi.Blockchain.TransactionBuilding;
Expand All @@ -11,6 +12,7 @@
using WalletWasabi.Helpers;
using WalletWasabi.Logging;
using WalletWasabi.Models;
using WalletWasabi.TorSocks5;

namespace WalletWasabi.Blockchain.Transactions
{
Expand Down Expand Up @@ -48,7 +50,9 @@ public BuildTransactionResult BuildTransaction(
PaymentIntent payments,
Func<FeeRate> feeRateFetcher,
IEnumerable<TxoRef> allowedInputs = null,
Func<LockTime> lockTimeSelector = null)
Func<LockTime> lockTimeSelector = null,
ITorHttpClient httpClient = null,
string uri= null)
{
payments = Guard.NotNull(nameof(payments), payments);
lockTimeSelector ??= () => LockTime.Zero;
Expand Down Expand Up @@ -222,6 +226,43 @@ public BuildTransactionResult BuildTransaction(
builder.SetLockTime(lockTimeSelector());
builder.SignPSBT(psbt);
psbt.Finalize();
if (uri != null && httpClient!= null)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = new StringContent(psbt.ToBase64())
};
var response = httpClient.SendAsync(httpRequestMessage).Result;
if (response.IsSuccessStatusCode && PSBT.TryParse( response.Content.ReadAsStringAsync().Result, Network, out var payjoinPSBT))
{
bool valid = false;
var existingInputs = psbt.Inputs.Select(input => input.PrevOut).ToList();
foreach (var input in payjoinPSBT.Inputs)
{
var existingInput = existingInputs.SingleOrDefault(point => point == input.PrevOut);
if (existingInput != null)
{
existingInputs.Remove(existingInput);
continue;
}

if (!input.TryFinalizeInput(out _))
{
valid = false;
break;
}
// a new signed input was provided
valid = true;
}

if (valid && !existingInputs.Any())
{
builder.SignPSBT(payjoinPSBT);
payjoinPSBT.Finalize();
psbt = payjoinPSBT;
}
}
}
tx = psbt.ExtractTransaction();

var checkResults = builder.Check(tx).ToList();
Expand Down
7 changes: 5 additions & 2 deletions WalletWasabi/Services/WalletService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,8 @@ public BuildTransactionResult BuildTransaction(
PaymentIntent payments,
FeeStrategy feeStrategy,
bool allowUnconfirmed = false,
IEnumerable<TxoRef> allowedInputs = null)
IEnumerable<TxoRef> allowedInputs = null,
string bip79 = null)
{
var builder = new TransactionFactory(Network, KeyManager, Coins, password, allowUnconfirmed);
return builder.BuildTransaction(
Expand All @@ -717,7 +718,9 @@ public BuildTransactionResult BuildTransaction(
}
},
allowedInputs,
SelectLockTimeForTransaction);
SelectLockTimeForTransaction,
Synchronizer.WasabiClient.TorClient,
bip79);
}

public void RenameLabel(SmartCoin coin, SmartLabel newLabel)
Expand Down

0 comments on commit 56bba9d

Please sign in to comment.