Implement pubkey change
MODIFY
WalletWasabi.Backend/Config.cs
WalletWasabi.Backend/Config.cs
@@ -52,14 +52,6 @@ namespace WalletWasabi.Backend
[JsonConverter(typeof(EndPointJsonConverter), Constants.DefaultRegTestBitcoinCoreRpcPort)]
public EndPoint RegTestBitcoinCoreRpcEndPoint { get; internal set; } = new IPEndPoint(IPAddress.Loopback, Constants.DefaultRegTestBitcoinCoreRpcPort);
- [JsonProperty(PropertyName = "CoordinatorExtPubKey")]
- [JsonConverter(typeof(ExtPubKeyJsonConverter))]
- public ExtPubKey CoordinatorExtPubKey { get; private set; } = Constants.FallBackCoordinatorExtPubKey;
-
- [DefaultValue(0)]
- [JsonProperty(PropertyName = "CoordinatorExtPubKeyCurrentDepth", DefaultValueHandling = DefaultValueHandling.Populate)]
- public int CoordinatorExtPubKeyCurrentDepth { get; private set; }
-
public EndPoint GetBitcoinP2pEndPoint()
{
if (Network == Network.Main)

MODIFY
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
WalletWasabi.Backend/Controllers/ChaumianCoinJoinController.cs
@@ -536,11 +536,6 @@ namespace WalletWasabi.Backend.Controllers
}
}
- if (request.OutputAddress == Constants.GetCoordinatorAddress(Network))
- {
- Logger.LogWarning($"Bob is registering the coordinator's address. Address: {request.OutputAddress}, Level: {request.Level}, Signature: {request.UnblindedSignature}.");
- }
-
if (request.Level > round.MixingLevels.GetMaxLevel())
{
return BadRequest($"Invalid mixing level is provided. Provided: {request.Level}. Maximum: {round.MixingLevels.GetMaxLevel()}.");

MODIFY
WalletWasabi/CoinJoin/Coordinator/Rounds/CoordinatorRound.cs
WalletWasabi/CoinJoin/Coordinator/Rounds/CoordinatorRound.cs
@@ -144,6 +144,7 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
public TimeSpan SigningTimeout { get; }
public UtxoReferee UtxoReferee { get; }
+ public CoordinatorRoundConfig RoundConfig { get; }
public CoordinatorRound(RPCClient rpc, UtxoReferee utxoReferee, CoordinatorRoundConfig config, int adjustedConfirmationTarget, int configuredConfirmationTarget, double configuredConfirmationTargetReductionRate)
{
@@ -153,7 +154,7 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
RpcClient = Guard.NotNull(nameof(rpc), rpc);
UtxoReferee = Guard.NotNull(nameof(utxoReferee), utxoReferee);
- Guard.NotNull(nameof(config), config);
+ RoundConfig = Guard.NotNull(nameof(config), config);
AdjustedConfirmationTarget = adjustedConfirmationTarget;
ConfiguredConfirmationTarget = configuredConfirmationTarget;
@@ -297,7 +298,7 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
}
}
- BitcoinWitPubKeyAddress coordinatorAddress = Constants.GetCoordinatorAddress(Network);
+ var coordinatorScript = await RoundConfig.GetNewCoordinatorScriptAsync();
// 3. If there are less Bobs than Alices, then add our own address. The malicious Alice, who will refuse to sign.
for (int i = 0; i < MixingLevels.Count(); i++)
{
@@ -306,7 +307,7 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
for (int j = 0; j < missingBobCount; j++)
{
var denomination = MixingLevels.GetLevel(i).Denomination;
- transaction.Outputs.AddWithOptimize(denomination, coordinatorAddress);
+ transaction.Outputs.AddWithOptimize(denomination, coordinatorScript);
}
}
@@ -386,7 +387,7 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
// 6. Add Coordinator fee only if > about $3, else just let it to be miner fee.
if (coordinatorFee > Money.Coins(0.0003m))
{
- transaction.Outputs.AddWithOptimize(coordinatorFee, coordinatorAddress);
+ transaction.Outputs.AddWithOptimize(coordinatorFee, coordinatorScript);
}
// 7. Try optimize fees.
@@ -1073,7 +1074,6 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
Coin[] spentCoins = Alices.SelectMany(x => x.Inputs).ToArray();
Money networkFee = CoinJoin.GetFee(spentCoins);
Logger.LogInfo($"Round ({RoundId}): Network Fee: {networkFee.ToString(false, false)} BTC.");
- Logger.LogInfo($"Round ({RoundId}): Coordinator Fee: {CoinJoin.Outputs.SingleOrDefault(x => x.ScriptPubKey == Constants.GetCoordinatorAddress(Network).ScriptPubKey)?.Value?.ToString(false, false) ?? "0"} BTC.");
FeeRate feeRate = CoinJoin.GetFeeRate(spentCoins);
Logger.LogInfo($"Round ({RoundId}): Network Fee Rate: {feeRate.FeePerK.ToDecimal(MoneyUnit.Satoshi) / 1000} sat/vByte.");
Logger.LogInfo($"Round ({RoundId}): Number of inputs: {CoinJoin.Inputs.Count}.");

MODIFY
WalletWasabi/CoinJoin/Coordinator/Rounds/CoordinatorRoundConfig.cs
WalletWasabi/CoinJoin/Coordinator/Rounds/CoordinatorRoundConfig.cs
@@ -69,6 +69,24 @@ namespace WalletWasabi.CoinJoin.Coordinator.Rounds
[JsonProperty(PropertyName = "MaximumMixingLevelCount", DefaultValueHandling = DefaultValueHandling.Populate)]
public int MaximumMixingLevelCount { get; internal set; }
+ [JsonProperty(PropertyName = "CoordinatorExtPubKey")]
+ [JsonConverter(typeof(ExtPubKeyJsonConverter))]
+ public ExtPubKey CoordinatorExtPubKey { get; private set; } = Constants.FallBackCoordinatorExtPubKey;
+
+ [DefaultValue(0)]
+ [JsonProperty(PropertyName = "CoordinatorExtPubKeyCurrentDepth", DefaultValueHandling = DefaultValueHandling.Populate)]
+ public int CoordinatorExtPubKeyCurrentDepth { get; private set; }
+
+ public async Task<Script> GetNewCoordinatorScriptAsync()
+ {
+ var ret = CoordinatorExtPubKey.Derive(0, false).Derive(CoordinatorExtPubKeyCurrentDepth, false).PubKey.WitHash.ScriptPubKey;
+
+ CoordinatorExtPubKeyCurrentDepth++;
+ await ToFileAsync().ConfigureAwait(false);
+
+ return ret;
+ }
+
public CoordinatorRoundConfig() : base()
{
}

MODIFY
WalletWasabi/Helpers/Constants.cs
WalletWasabi/Helpers/Constants.cs
@@ -58,32 +58,6 @@ namespace WalletWasabi.Helpers
// There are a maximum of 2,099,999,997,690,000 Bitcoin elements (called satoshis), which are currently most commonly measured in units of 100,000,000 known as BTC. Stated another way, no more than 21 million BTC can ever be created.
public const long MaximumNumberOfSatoshis = 2099999997690000;
- private static readonly BitcoinWitPubKeyAddress MainNetCoordinatorAddress = new BitcoinWitPubKeyAddress("bc1qa24tsgchvuxsaccp8vrnkfd85hrcpafg20kmjw", Network.Main);
- private static readonly BitcoinWitPubKeyAddress TestNetCoordinatorAddress = new BitcoinWitPubKeyAddress("tb1qecaheev3hjzs9a3w9x33wr8n0ptu7txp359exs", Network.TestNet);
- private static readonly BitcoinWitPubKeyAddress RegTestCoordinatorAddress = new BitcoinWitPubKeyAddress("bcrt1qangxrwyej05x9mnztkakk29s4yfdv4n586gs8l", Network.RegTest);
-
- public static BitcoinWitPubKeyAddress GetCoordinatorAddress(Network network)
- {
- Guard.NotNull(nameof(network), network);
-
- if (network == Network.Main)
- {
- return MainNetCoordinatorAddress;
- }
- else if (network == Network.TestNet)
- {
- return TestNetCoordinatorAddress;
- }
- else if (network == Network.RegTest)
- {
- return RegTestCoordinatorAddress;
- }
- else
- {
- throw new NotSupportedNetworkException(network);
- }
- }
-
public const int TwentyMinutesConfirmationTarget = 2;
public const int OneDayConfirmationTarget = 144;
public const int SevenDaysConfirmationTarget = 1008;
@@ -111,7 +85,6 @@ namespace WalletWasabi.Helpers
public const long MaxSatoshisSupply = 2_100_000_000_000_000L;
- public const string FallBackCoordinatorExtPubKeyString = "xpub6D2PqhWBAbF3xgfaAUW73KnaCXUroArcgMTzNkNzfVX7ykkSzQGbqaXZeaNyxKbZojAAqDwsne6B7NcVhiTrXbGYrQNq1yF76NkgdonGrEa";
- public static readonly ExtPubKey FallBackCoordinatorExtPubKey = NBitcoinHelpers.BetterParseExtPubKey(FallBackCoordinatorExtPubKeyString);
+ public static readonly ExtPubKey FallBackCoordinatorExtPubKey = NBitcoinHelpers.BetterParseExtPubKey("xpub6D2PqhWBAbF3xgfaAUW73KnaCXUroArcgMTzNkNzfVX7ykkSzQGbqaXZeaNyxKbZojAAqDwsne6B7NcVhiTrXbGYrQNq1yF76NkgdonGrEa");
}
}

Implement pubkey change