Commit 8c4ab891 authored by Jeremy Bokobza's avatar Jeremy Bokobza

Modofied the GetUnusedAddress a bit for Wallet recovery work

parent e125985c
......@@ -173,6 +173,34 @@ namespace Breeze.Wallet
/// </summary>
[JsonProperty(PropertyName = "internalAddresses")]
public IEnumerable<HdAddress> InternalAddresses { get; set; }
/// <summary>
/// Gets the type of coin this account is for.
/// </summary>
/// <returns>A <see cref="CoinType"/>.</returns>
public CoinType GetCoinType()
{
string[] pathElements = this.HdPath.Split('/');
int coinType = int.Parse(pathElements[2].Replace("'", string.Empty));
return (CoinType)coinType;
}
/// <summary>
/// Gets the first receiving address that contains no transaction.
/// </summary>
/// <returns>An unused address</returns>
public HdAddress GetFirstUnusedExternalAddress()
{
var unusedAddresses = this.ExternalAddresses.Where(acc => !acc.Transactions.Any()).ToList();
if (!unusedAddresses.Any())
{
return null;
}
// gets the unused address with the lowest index
var index = unusedAddresses.Min(a => a.Index);
return unusedAddresses.Single(a => a.Index == index);
}
}
/// <summary>
......
......@@ -18,7 +18,7 @@ namespace Breeze.Wallet
{
public List<Wallet> Wallets { get; }
public HashSet<Script> PubKeys { get; }
public HashSet<Script> PubKeys { get; set; }
public HashSet<TransactionDetails> TrackedTransactions { get; }
......@@ -142,7 +142,7 @@ namespace Breeze.Wallet
// get the extended pub key used to generate addresses for this account
var privateKey = Key.Parse(wallet.EncryptedSeed, password, wallet.Network);
var seedExtKey = new ExtKey(privateKey, wallet.ChainCode);
var accountHdPath = $"m/44'/{(int) coinType}'/{newAccountIndex}'";
var accountHdPath = $"m/44'/{(int)coinType}'/{newAccountIndex}'";
KeyPath keyPath = new KeyPath(accountHdPath);
ExtKey accountExtKey = seedExtKey.Derive(keyPath);
ExtPubKey accountExtPubKey = accountExtKey.Neuter();
......@@ -180,8 +180,6 @@ namespace Breeze.Wallet
throw new Exception($"No account with name {accountName} could be found.");
}
int newAddressIndex = 0;
// validate address creation
if (account.ExternalAddresses.Any())
{
......@@ -192,30 +190,63 @@ namespace Breeze.Wallet
{
return lastAddress.Address;
}
}
// creates an address
this.CreateAddressesInAccount(account, wallet.Network, 1);
// persists the address to the wallet file
this.SaveToFile(wallet);
newAddressIndex = lastAddressIndex + 1;
// adds the address to the list of tracked addresses
this.PubKeys = this.LoadKeys(coinType);
return account.GetFirstUnusedExternalAddress().Address;
}
/// <summary>
/// Creates a number of addresses in the provided account.
/// </summary>
/// <param name="account">The account.</param>
/// <param name="network">The network.</param>
/// <param name="addressesQuantity">The addresses quantity.</param>
/// <returns>A list of addresses in Base58.</returns>
private List<string> CreateAddressesInAccount(HdAccount account, Network network, int addressesQuantity)
{
List<string> addressesCreated = new List<string>();
// gets the index of the last address with transactions
int indexOfLastUsedAddress = 0;
if (account.ExternalAddresses.Any())
{
indexOfLastUsedAddress = account.ExternalAddresses.Where(a => a.Transactions.Any()).Max(add => add.Index);
}
for (int i = indexOfLastUsedAddress + 1; i <= indexOfLastUsedAddress + addressesQuantity; i++)
{
// skip over addresses that already exist
if (account.ExternalAddresses.ElementAtOrDefault(i) != null)
{
continue;
}
// generate new receiving address
BitcoinPubKeyAddress address = this.GenerateAddress(account.ExtendedPubKey, newAddressIndex, false, wallet.Network);
BitcoinPubKeyAddress address = this.GenerateAddress(account.ExtendedPubKey, i, false, network);
// add address details
account.ExternalAddresses = account.ExternalAddresses.Concat(new[] {new HdAddress
{
Index = newAddressIndex,
HdPath = CreateBip44Path(coinType, account.Index, newAddressIndex, false),
Index = i,
HdPath = CreateBip44Path(account.GetCoinType(), account.Index, i, false),
ScriptPubKey = address.ScriptPubKey,
Address = address.ToString(),
Transactions = new List<TransactionData>(),
CreationTime = DateTimeOffset.Now
}});
// persists the address to the wallet file
this.SaveToFile(wallet);
addressesCreated.Add(address.ToString());
}
// adds the address to the list of tracked addresses
this.PubKeys.Add(address.ScriptPubKey);
return address.ToString();
return addressesCreated;
}
public WalletGeneralInfoModel GetGeneralInfo(string name)
......@@ -318,7 +349,7 @@ namespace Breeze.Wallet
{
foreach (var account in accountRoot.Accounts)
{
foreach (var address in account.ExternalAddresses)//.Where(a => a.ScriptPubKey == script))
foreach (var address in account.ExternalAddresses.Where(a => a.ScriptPubKey == script))
{
address.Transactions = address.Transactions.Concat(new[]
{
......@@ -498,9 +529,9 @@ namespace Breeze.Wallet
SelectMany(w => w.AccountsRoot.Where(a => a.CoinType == coinType)).
SelectMany(a => a.Accounts).
SelectMany(a => a.ExternalAddresses).
//Select(s => s.ScriptPubKey));
Select(s => s.ScriptPubKey));
// uncomment the following for testing on a random address
Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
//Select(t => (new BitcoinPubKeyAddress(t.Address, Network.Main)).ScriptPubKey));
}
/// <summary>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment