Rename `IState` and refactor it
MODIFY
WalletWasabi.Tests/UnitTests/WabiSabi/Client/ArenaClientTests.cs
WalletWasabi.Tests/UnitTests/WabiSabi/Client/ArenaClientTests.cs
@@ -192,7 +192,7 @@ namespace WalletWasabi.Tests.UnitTests.WabiSabi.Client
var emptyState = round.CoinjoinState.AssertConstruction();
// We can't use ``emptyState.Finalize()` because this is not a valid transaction so we fake it
- var finalizedEmptyState = new SigningState(emptyState.Parameters, emptyState.Inputs.ToImmutableArray(), emptyState.Outputs.ToImmutableArray());
+ var finalizedEmptyState = new SigningState(emptyState);
// No inputs in the CoinJoin.
await Assert.ThrowsAsync<ArgumentException>(async () =>

MODIFY
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
WalletWasabi/WabiSabi/Backend/Rounds/Round.cs
@@ -30,7 +30,7 @@ namespace WalletWasabi.WabiSabi.Backend.Rounds
Id = CalculateHash();
}
- public IState CoinjoinState { get; set; }
+ public MultipartyTransactionState CoinjoinState { get; set; }
public uint256 Id { get; }
public Network Network => RoundParameters.Network;
public uint MaxInputCountByAlice => RoundParameters.MaxInputCountByAlice;

MODIFY
WalletWasabi/WabiSabi/Models/MultipartyTransaction/ConstructionState.cs
WalletWasabi/WabiSabi/Models/MultipartyTransaction/ConstructionState.cs
using NBitcoin;
using System;
-using System.Collections.Immutable;
using System.Linq;
using WalletWasabi.WabiSabi.Backend.Models;
namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
{
// This class represents actions of the BIP 370 creator and constructor roles
- public record ConstructionState(MultipartyTransactionParameters Parameters) : IState
+ public record ConstructionState(MultipartyTransactionParameters Parameters) : MultipartyTransactionState
{
- public ImmutableList<Coin> Inputs { get; init; } = ImmutableList<Coin>.Empty;
- public ImmutableList<TxOut> Outputs { get; init; } = ImmutableList<TxOut>.Empty;
-
- public Money Balance => Inputs.Sum(x => x.Amount) - Outputs.Sum(x => x.Value);
- public int EstimatedInputsVsize => Inputs.Sum(x => x.TxOut.ScriptPubKey.EstimateInputVsize());
- public int OutputsVsize => Outputs.Sum(x => x.ScriptPubKey.EstimateOutputVsize());
-
- public int EstimatedVsize => MultipartyTransactionParameters.SharedOverhead + EstimatedInputsVsize + OutputsVsize;
- // With no coordinator fees we can't ensure that the shared overhead
- // of the transaction also pays at the nominal feerate so this will have
- // to do for now, but in the future EstimatedVsize should be used
- // including the shared overhead
- public FeeRate EffectiveFeeRate => new(Balance, EstimatedInputsVsize + OutputsVsize);
-
// TODO ownership proofs and spend status also in scope
public ConstructionState AddInput(Coin coin)
{
@@ -119,7 +104,7 @@ namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
throw new WabiSabiProtocolException(WabiSabiProtocolErrorCode.InsufficientFees);
}
- return new SigningState(Parameters, Inputs.ToImmutableArray(), Outputs.ToImmutableArray());
+ return new SigningState(this);
}
}
}

DELETE
WalletWasabi/WabiSabi/Models/MultipartyTransaction/IState.cs
-using NBitcoin;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
-{
- public interface IState
- {
- public Money Balance { get; }
- public int EstimatedInputsVsize { get; }
- public int OutputsVsize { get; }
- public int EstimatedVsize { get; }
- public FeeRate EffectiveFeeRate { get; }
- }
-}

DELETE
WalletWasabi/WabiSabi/Models/MultipartyTransaction/IStateExtensions.cs
-namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
-{
- public static class IStateExtensions
- {
- public static ConstructionState AssertConstruction(this IState state) => (ConstructionState)state;
- public static SigningState AssertSigning(this IState state) => (SigningState)state;
- }
-}

MODIFY
WalletWasabi/WabiSabi/Models/MultipartyTransaction/MultipartyTransactionParameters.cs
WalletWasabi/WabiSabi/Models/MultipartyTransaction/MultipartyTransactionParameters.cs
@@ -6,20 +6,38 @@ namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
{
// This represents parameters all clients must agree on to produce a valid &
// standard transaction subject to constraints.
- public record MultipartyTransactionParameters(FeeRate FeeRate, MoneyRange AllowedInputAmounts, MoneyRange AllowedOutputAmounts, Network Network)
+ public record MultipartyTransactionParameters
{
- public static int SharedOverhead = 4*(4 + 4 + 3 + 3) + 1 + 1; // version, locktime, two 3 byte varints are non-witness data, marker and flags are witness data
+ // version, locktime, two 3 byte varints are non-witness data, marker and flags are witness data.
+ public static int SharedOverhead = 4 * (4 + 4 + 3 + 3) + 1 + 1;
public static ImmutableSortedSet<ScriptType> OnlyP2WPKH = ImmutableSortedSet.Create<ScriptType>(ScriptType.P2WPKH);
- public ImmutableSortedSet<ScriptType> AllowedInputTypes { get; init; } = OnlyP2WPKH;
- public ImmutableSortedSet<ScriptType> AllowedOutputTypes { get; init; } = OnlyP2WPKH;
+ public MultipartyTransactionParameters(
+ FeeRate feeRate,
+ MoneyRange allowedInputAmounts,
+ MoneyRange allowedOutputAmounts,
+ Network network)
+ {
+ FeeRate = feeRate;
+ AllowedInputAmounts = allowedInputAmounts;
+ AllowedOutputAmounts = allowedOutputAmounts;
+ Network = network;
+ }
// These parameters need to be committed to the transcript, but we want
// the NBitcoin supplied default values, hence the private static property
private static StandardTransactionPolicy StandardTransactionPolicy { get; } = new();
- public int MaxTransactionSize { get; init; } = (int)StandardTransactionPolicy.MaxTransactionSize;
+
+ public ImmutableSortedSet<ScriptType> AllowedInputTypes { get; init; } = OnlyP2WPKH;
+ public ImmutableSortedSet<ScriptType> AllowedOutputTypes { get; init; } = OnlyP2WPKH;
+
+ public int MaxTransactionSize { get; init; } = StandardTransactionPolicy.MaxTransactionSize!.Value;
public FeeRate MinRelayTxFee { get; init; } = StandardTransactionPolicy.MinRelayTxFee;
+ public FeeRate FeeRate { get; init; }
+ public MoneyRange AllowedInputAmounts { get; init; }
+ public MoneyRange AllowedOutputAmounts { get; init; }
+ public Network Network { get; }
// implied:
// segwit transaction

ADD
WalletWasabi/WabiSabi/Models/MultipartyTransaction/MultipartyTransactionState.cs
+using NBitcoin;
+using System.Collections.Immutable;
+using System.Linq;
+
+namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
+{
+ public record MultipartyTransactionState
+ {
+ public ImmutableList<Coin> Inputs { get; init; } = ImmutableList<Coin>.Empty;
+ public ImmutableList<TxOut> Outputs { get; init; } = ImmutableList<TxOut>.Empty;
+
+ public Money Balance => Inputs.Sum(x => x.Amount) - Outputs.Sum(x => x.Value);
+ public int EstimatedInputsVsize => Inputs.Sum(x => x.TxOut.ScriptPubKey.EstimateInputVsize());
+ public int OutputsVsize => Outputs.Sum(x => x.ScriptPubKey.EstimateOutputVsize());
+
+ public int EstimatedVsize => MultipartyTransactionParameters.SharedOverhead + EstimatedInputsVsize + OutputsVsize;
+
+ // With no coordinator fees we can't ensure that the shared overhead
+ // of the transaction also pays at the nominal feerate so this will have
+ // to do for now, but in the future EstimatedVsize should be used
+ // including the shared overhead
+ public FeeRate EffectiveFeeRate => new(Balance, EstimatedInputsVsize + OutputsVsize);
+ }
+}
\ No newline at end of file

ADD
WalletWasabi/WabiSabi/Models/MultipartyTransaction/MultipartyTransactionStateExtensions.cs
+namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
+{
+ public static class MultipartyTransactionStateExtensions
+ {
+ public static ConstructionState AssertConstruction(this MultipartyTransactionState state) => (ConstructionState)state;
+ public static SigningState AssertSigning(this MultipartyTransactionState state) => (SigningState)state;
+ }
+}
\ No newline at end of file

MODIFY
WalletWasabi/WabiSabi/Models/MultipartyTransaction/SigningState.cs
WalletWasabi/WabiSabi/Models/MultipartyTransaction/SigningState.cs
@@ -6,18 +6,20 @@ using WalletWasabi.WabiSabi.Backend.Models;
namespace WalletWasabi.WabiSabi.Models.MultipartyTransaction
{
- public record SigningState(MultipartyTransactionParameters Parameters, ImmutableArray<Coin> Inputs, ImmutableArray<TxOut> Outputs) : IState
+ public record SigningState : MultipartyTransactionState
{
- public ImmutableDictionary<int, WitScript> Witnesses { get; init; } = ImmutableDictionary<int, WitScript>.Empty;
+ public SigningState(ConstructionState state)
+ {
+ Parameters = state.Parameters;
+ Inputs = state.Inputs;
+ Outputs = state.Outputs;
+ }
- public bool IsFullySigned => Witnesses.Count == Inputs.Length;
+ public MultipartyTransactionParameters Parameters { get; }
- public Money Balance => Inputs.Sum(x => x.Amount) - Outputs.Sum(x => x.Value);
- public int EstimatedInputsVsize => Inputs.Sum(x => x.TxOut.ScriptPubKey.EstimateInputVsize());
- public int OutputsVsize => Outputs.Sum(x => x.ScriptPubKey.EstimateOutputVsize());
+ public ImmutableDictionary<int, WitScript> Witnesses { get; init; } = ImmutableDictionary<int, WitScript>.Empty;
- public int EstimatedVsize => MultipartyTransactionParameters.SharedOverhead + EstimatedInputsVsize + OutputsVsize;
- public FeeRate EffectiveFeeRate => new(Balance, EstimatedVsize);
+ public bool IsFullySigned => Witnesses.Count == Inputs.Count;
public IEnumerable<Coin> UnsignedInputs => Inputs.Where((_, i) => !IsInputSigned(i));

MODIFY
WalletWasabi/WabiSabi/Models/RoundState.cs
WalletWasabi/WabiSabi/Models/RoundState.cs
@@ -10,7 +10,7 @@ namespace WalletWasabi.WabiSabi.Models
CredentialIssuerParameters AmountCredentialIssuerParameters,
CredentialIssuerParameters VsizeCredentialIssuerParameters,
FeeRate FeeRate,
- IState CoinjoinState)
+ MultipartyTransactionState CoinjoinState)
{
public static RoundState FromRound(Round round) =>
new RoundState(round.Id, round.AmountCredentialIssuerParameters, round.VsizeCredentialIssuerParameters, round.FeeRate, round.CoinjoinState);

MODIFY
WalletWasabi/WabiSabi/Models/Serialization/JsonSerializationOptions.cs
WalletWasabi/WabiSabi/Models/Serialization/JsonSerializationOptions.cs
@@ -22,7 +22,7 @@ namespace WalletWasabi.WabiSabi.Models.Serialization
new FeeRateJsonConverter(),
new MoneySatoshiJsonConverter(),
new Uint256JsonConverter(),
- new IStateJsonConverter()
+ new MultipartyTransactionStateJsonConverter()
}
};
public static readonly JsonSerializationOptions Default = new();

RENAME
WalletWasabi/WabiSabi/Models/Serialization/IStateJsonConverter.cs
WalletWasabi/WabiSabi/Models/Serialization/MultipartyTransactionStateJsonConverter.cs
@@ -5,7 +5,7 @@ using WalletWasabi.WabiSabi.Models.MultipartyTransaction;
namespace WalletWasabi.WabiSabi.Models.Serialization
{
- public class IStateJsonConverter : JsonConverter
+ public class MultipartyTransactionStateJsonConverter : JsonConverter
{
// This converter is a bit unusual because we need to add a new property to the
// serialized json string but the converter is called recursively and fails with
@@ -49,7 +49,7 @@ namespace WalletWasabi.WabiSabi.Models.Serialization
public override bool CanConvert(Type objectType)
{
- return typeof(IState).IsAssignableFrom(objectType);
+ return typeof(MultipartyTransactionState).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)

Rename `IState` and refactor it