Remove TxoRef from protocol message
MODIFY
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
@@ -158,7 +158,7 @@ namespace WalletWasabi.Backend.Controllers
var uniqueInputs = new HashSet<OutPoint>();
foreach (InputProofModel inputProof in request.Inputs)
{
- var outpoint = inputProof.Input.ToOutPoint();
+ var outpoint = inputProof.Input;
if (uniqueInputs.Contains(outpoint))
{
return BadRequest("Cannot register an input twice.");
@@ -173,11 +173,11 @@ namespace WalletWasabi.Backend.Controllers
foreach (InputProofModel inputProof in request.Inputs)
{
- if (round.ContainsInput(inputProof.Input.ToOutPoint(), out List<Alice> tr))
+ if (round.ContainsInput(inputProof.Input, out List<Alice> tr))
{
alicesToRemove.UnionWith(tr.Select(x => x.UniqueId)); // Input is already registered by this alice, remove it later if all the checks are completed fine.
}
- if (Coordinator.AnyRunningRoundContainsInput(inputProof.Input.ToOutPoint(), out List<Alice> tnr))
+ if (Coordinator.AnyRunningRoundContainsInput(inputProof.Input, out List<Alice> tnr))
{
if (tr.Union(tnr).Count() > tr.Count)
{
@@ -185,14 +185,14 @@ namespace WalletWasabi.Backend.Controllers
}
}
- OutPoint outpoint = inputProof.Input.ToOutPoint();
+ OutPoint outpoint = inputProof.Input;
var bannedElem = await Coordinator.UtxoReferee.TryGetBannedAsync(outpoint, notedToo: false);
if (bannedElem != null)
{
- return BadRequest($"Input is banned from participation for {(int)bannedElem.BannedRemaining.TotalMinutes} minutes: {inputProof.Input.Index}:{inputProof.Input.TransactionId}.");
+ return BadRequest($"Input is banned from participation for {(int)bannedElem.BannedRemaining.TotalMinutes} minutes: {inputProof.Input.N}:{inputProof.Input.Hash}.");
}
- var txOutResponseTask = batch.GetTxOutAsync(inputProof.Input.TransactionId, (int)inputProof.Input.Index, includeMempool: true);
+ var txOutResponseTask = batch.GetTxOutAsync(inputProof.Input.Hash, (int)inputProof.Input.N, includeMempool: true);
getTxOutResponses.Add((inputProof, txOutResponseTask));
}
@@ -214,21 +214,21 @@ namespace WalletWasabi.Backend.Controllers
// Check if inputs are unspent.
if (getTxOutResponse is null)
{
- return BadRequest($"Provided input is not unspent: {inputProof.Input.Index}:{inputProof.Input.TransactionId}.");
+ return BadRequest($"Provided input is not unspent: {inputProof.Input.N}:{inputProof.Input.Hash}.");
}
// Check if unconfirmed.
if (getTxOutResponse.Confirmations <= 0)
{
// If it spends a CJ then it may be acceptable to register.
- if (!await Coordinator.ContainsUnconfirmedCoinJoinAsync(inputProof.Input.TransactionId))
+ if (!await Coordinator.ContainsUnconfirmedCoinJoinAsync(inputProof.Input.Hash))
{
return BadRequest("Provided input is neither confirmed, nor is from an unconfirmed coinjoin.");
}
// Check if mempool would accept a fake transaction created with the registered inputs.
// This will catch ascendant/descendant count and size limits for example.
- var result = await RpcClient.TestMempoolAcceptAsync(new[] { new Coin(inputProof.Input.ToOutPoint(), getTxOutResponse.TxOut) });
+ var result = await RpcClient.TestMempoolAcceptAsync(new[] { new Coin(inputProof.Input, getTxOutResponse.TxOut) });
if (!result.accept)
{
return BadRequest($"Provided input is from an unconfirmed coinjoin, but a limit is reached: {result.rejectReason}");
@@ -259,7 +259,7 @@ namespace WalletWasabi.Backend.Controllers
return BadRequest("Provided proof is invalid.");
}
- inputs.Add(new Coin(inputProof.Input.ToOutPoint(), txOut));
+ inputs.Add(new Coin(inputProof.Input, txOut));
}
var acceptedBlindedOutputScripts = new List<uint256>();

MODIFY
WalletWasabi.Tests/RegressionTests/CoinJoinTests.cs
WalletWasabi.Tests/RegressionTests/CoinJoinTests.cs
@@ -170,19 +170,19 @@ namespace WalletWasabi.Tests.RegressionTests
inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() + 1).Select(x => uint256.One);
inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network);
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new OutPoint(uint256.One, 0), Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nToo many blinded output was provided", httpRequestException.Message);
inputsRequest.BlindedOutputScripts = Enumerable.Range(0, round.MixingLevels.Count() - 2).Select(x => uint256.One);
inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network);
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new OutPoint(uint256.One, 0), Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nDuplicate blinded output found", httpRequestException.Message);
inputsRequest.BlindedOutputScripts = new[] { uint256.Zero };
inputsRequest.ChangeOutputAddress = new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network);
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(uint256.One, 0), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new OutPoint(uint256.One, 0), Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is not unspent", httpRequestException.Message);
@@ -191,7 +191,7 @@ namespace WalletWasabi.Tests.RegressionTests
var tx = await rpc.GetRawTransactionAsync(hash);
var coin = tx.Outputs.GetCoins(addr.ScriptPubKey).Single();
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint, Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is neither confirmed, nor is from an unconfirmed coinjoin.", httpRequestException.Message);
@@ -202,7 +202,7 @@ namespace WalletWasabi.Tests.RegressionTests
var blockHash = blocks.Single();
var block = await rpc.GetBlockAsync(blockHash);
var coinbase = block.Transactions.First();
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new TxoRef(coinbase.GetHash(), 0), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = new OutPoint(coinbase.GetHash(), 0), Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.Equal($"{HttpStatusCode.BadRequest.ToReasonString()}\nProvided input is immature.", httpRequestException.Message);
@@ -212,7 +212,7 @@ namespace WalletWasabi.Tests.RegressionTests
await rpc.GenerateAsync(1);
tx = await rpc.GetRawTransactionAsync(hash);
coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
- inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = dummySignature } };
+ inputsRequest.Inputs = new List<InputProofModel> { new InputProofModel { Input = coin.Outpoint, Proof = dummySignature } };
httpRequestException = await Assert.ThrowsAsync<HttpRequestException>(async () => await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, inputsRequest, baseUri, null));
Assert.StartsWith($"{HttpStatusCode.BadRequest.ToReasonString()}", httpRequestException.Message);
@@ -346,7 +346,7 @@ namespace WalletWasabi.Tests.RegressionTests
tx = await rpc.GetRawTransactionAsync(hash);
coin = tx.Outputs.GetCoins(witnessAddress.ScriptPubKey).Single();
proof = key.SignCompact(blindedOutputScriptsHash);
- inputProofs.Add(new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = proof });
+ inputProofs.Add(new InputProofModel { Input = coin.Outpoint, Proof = proof });
}
var blockHashed = await rpc.GenerateAsync(1);
@@ -404,13 +404,13 @@ namespace WalletWasabi.Tests.RegressionTests
var spendingTx = network.Consensus.ConsensusFactory.CreateTransaction();
var bannedCoin = inputsRequest.Inputs.First().Input;
var utxos = coordinator.UtxoReferee;
- Assert.NotNull(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
- spendingTx.Inputs.Add(new TxIn(bannedCoin.ToOutPoint()));
+ Assert.NotNull(await utxos.TryGetBannedAsync(bannedCoin, false));
+ spendingTx.Inputs.Add(new TxIn(bannedCoin));
spendingTx.Outputs.Add(new TxOut(Money.Coins(1), new Key().PubKey.GetSegwitAddress(network)));
await coordinator.ProcessConfirmedTransactionAsync(spendingTx);
Assert.NotNull(await utxos.TryGetBannedAsync(new OutPoint(spendingTx.GetHash(), 0), false));
- Assert.Null(await utxos.TryGetBannedAsync(bannedCoin.ToOutPoint(), false));
+ Assert.Null(await utxos.TryGetBannedAsync(bannedCoin, false));
states = await satoshiClient.GetAllRoundStatesAsync();
foreach (var rs in states.Where(x => x.Phase == RoundPhase.InputRegistration))
@@ -441,7 +441,7 @@ namespace WalletWasabi.Tests.RegressionTests
blindedData = requester.BlindScript(round.MixingLevels.GetBaseLevel().Signer.Key.PubKey, round.MixingLevels.GetBaseLevel().Signer.R.PubKey, script);
blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedData.ToBytes()));
- using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blindedData }, new InputProofModel[] { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = key.SignCompact(blindedOutputScriptsHash) } }, baseUri, null))
+ using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blindedData }, new InputProofModel[] { new InputProofModel { Input = coin.Outpoint, Proof = key.SignCompact(blindedOutputScriptsHash) } }, baseUri, null))
{
Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
Assert.True(aliceClient.RoundId > 0);
@@ -481,7 +481,7 @@ namespace WalletWasabi.Tests.RegressionTests
Assert.Equal($"{HttpStatusCode.Gone.ToReasonString()}\nRound is not running.", httpRequestException.Message);
}
- using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blindedData }, new InputProofModel[] { new InputProofModel { Input = coin.Outpoint.ToTxoRef(), Proof = key.SignCompact(blindedOutputScriptsHash) } }, baseUri, null))
+ using (var aliceClient = await AliceClient.CreateNewAsync(roundId, registeredAddresses, schnorrPubKeys, requesters, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blindedData }, new InputProofModel[] { new InputProofModel { Input = coin.Outpoint, Proof = key.SignCompact(blindedOutputScriptsHash) } }, baseUri, null))
{
Assert.NotEqual(Guid.Empty, aliceClient.UniqueId);
Assert.True(aliceClient.RoundId > 0);
@@ -543,8 +543,8 @@ namespace WalletWasabi.Tests.RegressionTests
var input1 = new OutPoint(hash1, index1);
var input2 = new OutPoint(hash2, index2);
- using (var aliceClient1 = await AliceClient.CreateNewAsync(roundId, new[] { outputAddress1 }, schnorrPubKeys, new[] { requester1 }, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blinded1 }, new InputProofModel[] { new InputProofModel { Input = input1.ToTxoRef(), Proof = key1.SignCompact(blindedOutputScriptsHash1) } }, baseUri, null))
- using (var aliceClient2 = await AliceClient.CreateNewAsync(roundId, new[] { outputAddress2 }, schnorrPubKeys, new[] { requester2 }, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blinded2 }, new InputProofModel[] { new InputProofModel { Input = input2.ToTxoRef(), Proof = key2.SignCompact(blindedOutputScriptsHash2) } }, baseUri, null))
+ using (var aliceClient1 = await AliceClient.CreateNewAsync(roundId, new[] { outputAddress1 }, schnorrPubKeys, new[] { requester1 }, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blinded1 }, new InputProofModel[] { new InputProofModel { Input = input1, Proof = key1.SignCompact(blindedOutputScriptsHash1) } }, baseUri, null))
+ using (var aliceClient2 = await AliceClient.CreateNewAsync(roundId, new[] { outputAddress2 }, schnorrPubKeys, new[] { requester2 }, network, new Key().PubKey.GetAddress(ScriptPubKeyType.Segwit, network), new[] { blinded2 }, new InputProofModel[] { new InputProofModel { Input = input2, Proof = key2.SignCompact(blindedOutputScriptsHash2) } }, baseUri, null))
{
Assert.Equal(aliceClient2.RoundId, aliceClient1.RoundId);
Assert.NotEqual(aliceClient2.UniqueId, aliceClient1.UniqueId);
@@ -669,7 +669,7 @@ namespace WalletWasabi.Tests.RegressionTests
// important data for each of the participants in the coinjoin session.
var participants = new List<(AliceClient aliceClient,
List<(Requester requester, BitcoinWitPubKeyAddress outputAddress, uint256 blindedScript)> outouts,
- List<(TxoRef input, byte[] proof, Coin coin, Key key)> inputs)>();
+ List<(OutPoint input, byte[] proof, Coin coin, Key key)> inputs)>();
// INPUTS REGISTRATION PHASE --
for (var anosetIdx = 0; anosetIdx < anonymitySet; anosetIdx++)
@@ -692,7 +692,7 @@ namespace WalletWasabi.Tests.RegressionTests
var blindedOutputScriptsHash = new uint256(Hashes.SHA256(blindedOutputScriptListBytes));
// Create 4 new coins that we want to mix
- var inputs = new List<(TxoRef input, byte[] proof, Coin coin, Key key)>();
+ var inputs = new List<(OutPoint input, byte[] proof, Coin coin, Key key)>();
for (var inputIdx = 0; inputIdx < 4; inputIdx++)
{
var key = new Key();
@@ -704,7 +704,7 @@ namespace WalletWasabi.Tests.RegressionTests
var input = new OutPoint(hash, index);
inputs.Add((
- input.ToTxoRef(),
+ input,
key.SignCompact(blindedOutputScriptsHash),
new Coin(tx, (uint)index),
key
@@ -769,7 +769,7 @@ namespace WalletWasabi.Tests.RegressionTests
// Verify the inputs are the expected ones.
foreach (var input in inputs)
{
- Assert.Contains(input.input, unsignedTransaction.Inputs.Select(x => x.PrevOut.ToTxoRef()));
+ Assert.Contains(input.input, unsignedTransaction.Inputs.Select(x => x.PrevOut));
}
// Sign the transaction
@@ -840,7 +840,7 @@ namespace WalletWasabi.Tests.RegressionTests
spentCoins.Add(coin);
OutPoint input = coin.Outpoint;
- var inputProof = new InputProofModel { Input = input.ToTxoRef(), Proof = key.SignCompact(blindedOutputScriptsHash) };
+ var inputProof = new InputProofModel { Input = input, Proof = key.SignCompact(blindedOutputScriptsHash) };
inputProofModels.Add(inputProof);
GetTxOutResponse getTxOutResponse = await rpc.GetTxOutAsync(input.Hash, (int)input.N, includeMempool: true);

MODIFY
WalletWasabi.Tests/RegressionTests/DosTests.cs
WalletWasabi.Tests/RegressionTests/DosTests.cs
@@ -128,7 +128,7 @@ namespace WalletWasabi.Tests.RegressionTests
var coin = transaction.Outputs.GetCoins(inputAddress.ScriptPubKey).Single();
OutPoint input = coin.Outpoint;
- var inputProof = new InputProofModel { Input = input.ToTxoRef(), Proof = key.SignCompact(blindedOutputScriptsHash) };
+ var inputProof = new InputProofModel { Input = input, Proof = key.SignCompact(blindedOutputScriptsHash) };
inputProofModels.Add(inputProof);
GetTxOutResponse getTxOutResponse = await rpc.GetTxOutAsync(input.Hash, (int)input.N, includeMempool: true);
@@ -316,7 +316,7 @@ namespace WalletWasabi.Tests.RegressionTests
Coin coin = transaction.Outputs.GetCoins(inputAddress.ScriptPubKey).Single();
OutPoint input = coin.Outpoint;
- InputProofModel inputProof = new InputProofModel { Input = input.ToTxoRef(), Proof = inputKey.SignCompact(blindedOutputScriptsHash) };
+ InputProofModel inputProof = new InputProofModel { Input = input, Proof = inputKey.SignCompact(blindedOutputScriptsHash) };
InputProofModel[] inputsProofs = new InputProofModel[] { inputProof };
registerRequests.Add((changeOutputAddress, blinded, inputsProofs));
aliceClientBackup = await AliceClient.CreateNewAsync(round.RoundId, new[] { activeOutputAddress }, new[] { round.MixingLevels.GetBaseLevel().SchnorrKey.SchnorrPubKey }, new[] { requester }, network, changeOutputAddress, new[] { blinded }, inputsProofs, baseUri, null);

MODIFY
WalletWasabi/Blockchain/TransactionOutputs/SmartCoin.cs
WalletWasabi/Blockchain/TransactionOutputs/SmartCoin.cs
@@ -300,11 +300,6 @@ namespace WalletWasabi.Blockchain.TransactionOutputs
return new Coin(TransactionId, Index, Amount, ScriptPubKey);
}
- public TxoRef GetTxoRef()
- {
- return new TxoRef(TransactionId, Index);
- }
-
#endregion Methods
#region EqualityAndComparison

DELETE
WalletWasabi/Blockchain/TransactionOutputs/TxoRef.cs
-using NBitcoin;
-using Newtonsoft.Json;
-using System;
-using System.ComponentModel.DataAnnotations;
-using WalletWasabi.Helpers;
-using WalletWasabi.JsonConverters;
-
-namespace WalletWasabi.Blockchain.TransactionOutputs
-{
- /// <summary>
- /// The same functionality as Outpoint, but it's JsonSerializable
- /// </summary>
- [JsonObject(MemberSerialization.OptIn)]
- public class TxoRef : IEquatable<TxoRef>, IEquatable<OutPoint>
- {
- [Required]
- [JsonProperty(Order = 1)]
- [JsonConverter(typeof(Uint256JsonConverter))]
- public uint256 TransactionId { get; }
-
- [JsonProperty(Order = 2)]
- public uint Index { get; }
-
- [JsonConstructor]
- public TxoRef(uint256 transactionId, uint index)
- {
- TransactionId = Guard.NotNull(nameof(transactionId), transactionId);
- Index = Guard.NotNull(nameof(index), index);
- }
-
- public TxoRef(OutPoint outPoint)
- {
- Guard.NotNull(nameof(outPoint), outPoint);
- TransactionId = outPoint.Hash;
- Index = outPoint.N;
- }
-
- public OutPoint ToOutPoint() => new OutPoint(TransactionId, Index);
-
- #region EqualityAndComparison
-
- public override bool Equals(object obj) => Equals(obj as TxoRef);
-
- public bool Equals(TxoRef other) => this == other;
-
- public override int GetHashCode() => (TransactionId, Index).GetHashCode();
-
- public static bool operator ==(TxoRef x, TxoRef y) => y?.TransactionId == x?.TransactionId && y?.Index == x?.Index;
-
- public static bool operator !=(TxoRef x, TxoRef y) => !(x == y);
-
- public bool Equals(OutPoint other) => TransactionId == other?.Hash && Index == other?.N;
-
- public static bool operator ==(OutPoint x, TxoRef y) => y?.TransactionId == x?.Hash && y?.Index == x?.N;
-
- public static bool operator ==(TxoRef x, OutPoint y) => y?.Hash == x?.TransactionId && y?.N == x?.Index; // Hash first, index second is faster.
-
- public static bool operator !=(OutPoint x, TxoRef y) => !(x == y);
-
- public static bool operator !=(TxoRef x, OutPoint y) => !(x == y);
-
- #endregion EqualityAndComparison
- }
-}

MODIFY
WalletWasabi/CoinJoin/Client/Clients/CoinJoinClient.cs
WalletWasabi/CoinJoin/Client/Clients/CoinJoinClient.cs
@@ -530,7 +530,7 @@ namespace WalletWasabi.CoinJoin.Client.Clients
coin.Secret ??= KeyManager.GetSecrets(SaltSoup(), coin.ScriptPubKey).Single();
var inputProof = new InputProofModel
{
- Input = coin.GetTxoRef(),
+ Input = coin.OutPoint,
Proof = coin.Secret.PrivateKey.SignCompact(blindedOutputScriptsHash)
};
inputProofs.Add(inputProof);

MODIFY
WalletWasabi/CoinJoin/Common/Models/InputProofModel.cs
WalletWasabi/CoinJoin/Common/Models/InputProofModel.cs
+using NBitcoin;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;
-using WalletWasabi.Blockchain.TransactionOutputs;
using WalletWasabi.JsonConverters;
namespace WalletWasabi.CoinJoin.Common.Models
@@ -8,7 +8,8 @@ namespace WalletWasabi.CoinJoin.Common.Models
public class InputProofModel
{
[Required]
- public TxoRef Input { get; set; }
+ [JsonConverter(typeof(OutPointAsTxoRefJsonConverter))]
+ public OutPoint Input { get; set; }
[Required]
[MinLength(65, ErrorMessage = "Provided proof is invalid")] // Bitcoin compact signatures are 65 bytes length

MODIFY
WalletWasabi/Extensions/NBitcoinExtensions.cs
WalletWasabi/Extensions/NBitcoinExtensions.cs
@@ -52,8 +52,6 @@ namespace NBitcoin
}
}
- public static TxoRef ToTxoRef(this OutPoint me) => new TxoRef(me);
-
public static IEnumerable<OutPoint> ToOutPoints(this TxInList me)
{
foreach (var input in me)

ADD
WalletWasabi/JsonConverters/OutPointAsTxoRefJsonConverter.cs
+using NBitcoin;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+
+namespace WalletWasabi.JsonConverters
+{
+ public class OutPointAsTxoRefJsonConverter : JsonConverter
+ {
+ /// <inheritdoc />
+ public override bool CanConvert(Type objectType)
+ {
+ return objectType == typeof(OutPoint);
+ }
+
+ /// <inheritdoc />
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ {
+ JObject item = JObject.Load(reader);
+
+ var hash = item.Value<string>("TransactionId");
+ var n = item.Value<uint>("Index");
+ return new OutPoint(uint256.Parse(hash), n);
+ }
+
+ /// <inheritdoc />
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ var outpoint = value as OutPoint;
+ writer.WriteStartObject();
+ writer.WritePropertyName("TransactionId");
+ writer.WriteValue(outpoint.Hash.ToString());
+ writer.WritePropertyName("Index");
+ writer.WriteValue(outpoint.N);
+ writer.WriteEndObject();
+ }
+ }
+}

Remove TxoRef from protocol message