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 14, 2020
1 parent 825cb68 commit 5f3c816
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 4 deletions.
6 changes: 6 additions & 0 deletions WalletWasabi.Gui/Controls/WalletExplorer/SendControlView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
</controls:ExtendedTextBox>

<suggestions:SuggestLabelView DataContext="{Binding LabelSuggestion}" />
<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">
<Button Content="{Binding IsMax, Converter={StaticResource BooleanStringConverter}, ConverterParameter=Clear:Max}" Command="{Binding MaxCommand}" VerticalAlignment="Top" Height="40" />
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 @@ -71,6 +71,7 @@ public abstract class SendControlViewModel : WasabiDocumentTabViewModel
private bool _isHardwareBusy;
private bool _isCustomFee;
private bool _isCustomChangeAddress;
private string _bip79;

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

Expand Down Expand Up @@ -235,6 +236,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 @@ -371,7 +381,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 @@ -820,6 +830,19 @@ public ErrorDescriptors ValidateActiveAddress()

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."));
}

public ErrorDescriptors ValidateCustomChangeAddress()
{
Expand Down Expand Up @@ -859,6 +882,13 @@ public string CustomChangeAddress
get => _customChangeAddress;
set => this.RaiseAndSetIfChanged(ref _customChangeAddress, value?.Trim());
}

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

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

namespace WalletWasabi.Blockchain.Transactions
{
Expand Down Expand Up @@ -48,7 +51,9 @@ public TransactionFactory(Network network, KeyManager keyManager, ICoinsView coi
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 +227,43 @@ public TransactionFactory(Network network, KeyManager keyManager, ICoinsView coi
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(), Encoding.UTF8, "text/plain")
};
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 async Task<int> CountBlocksAsync()
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 async Task<int> CountBlocksAsync()
}
},
allowedInputs,
SelectLockTimeForTransaction);
SelectLockTimeForTransaction,
Synchronizer.WasabiClient.TorClient,
bip79);
}

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

0 comments on commit 5f3c816

Please sign in to comment.