Commit 8094747b authored by Pieterjan Vanhoof's avatar Pieterjan Vanhoof Committed by GitHub

Merge pull request #41 from bokobza/feature/wallet-recovery

Feature/wallet recovery
parents 0952f0cc 3e8b0a9f
......@@ -22,7 +22,7 @@ namespace Breeze.Api.Tests
var mockWalletCreate = new Mock<IWalletManager>();
mockWalletCreate.Setup(wallet => wallet.CreateWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null)).Returns(mnemonic);
var controller = new WalletController(mockWalletCreate.Object);
var controller = new WalletController(mockWalletCreate.Object, new Mock<ITracker>().Object);
// Act
var result = controller.Create(new WalletCreationRequest
......@@ -50,9 +50,9 @@ namespace Breeze.Api.Tests
};
var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null, null)).Returns(wallet);
mockWalletWrapper.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), null, It.IsAny<DateTime>())).Returns(wallet);
var controller = new WalletController(mockWalletWrapper.Object);
var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act
var result = controller.Recover(new WalletRecoveryRequest
......@@ -85,7 +85,7 @@ namespace Breeze.Api.Tests
var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(w => w.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Returns(wallet);
var controller = new WalletController(mockWalletWrapper.Object);
var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act
var result = controller.Load(new WalletLoadRequest
......@@ -111,7 +111,7 @@ namespace Breeze.Api.Tests
var mockWalletWrapper = new Mock<IWalletManager>();
mockWalletWrapper.Setup(wallet => wallet.LoadWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())).Throws<FileNotFoundException>();
var controller = new WalletController(mockWalletWrapper.Object);
var controller = new WalletController(mockWalletWrapper.Object, new Mock<ITracker>().Object);
// Act
var result = controller.Load(new WalletLoadRequest
......
......@@ -39,5 +39,39 @@ namespace Breeze.Wallet
throw new Exception("No support for this coin.");
}
}
/// <summary>
/// Gets the height of the first block created after this date.
/// </summary>
/// <param name="chain">The chain of blocks.</param>
/// <param name="date">The date.</param>
/// <returns>The height of the first block created after the date.</returns>
public static int GetHeightAtTime(this ConcurrentChain chain, DateTime date)
{
int blockSyncStart = 0;
int upperLimit = chain.Tip.Height;
int lowerLimit = 0;
bool found = false;
while (!found)
{
int check = lowerLimit + (upperLimit - lowerLimit) / 2;
if (chain.GetBlock(check).Header.BlockTime >= date)
{
upperLimit = check;
}
else if (chain.GetBlock(check).Header.BlockTime < date)
{
lowerLimit = check;
}
if (upperLimit - lowerLimit <= 1)
{
blockSyncStart = upperLimit;
found = true;
}
}
return blockSyncStart;
}
}
}
\ No newline at end of file
......@@ -19,9 +19,12 @@ namespace Breeze.Wallet.Controllers
{
private readonly IWalletManager walletManager;
public WalletController(IWalletManager walletManager)
private readonly ITracker tracker;
public WalletController(IWalletManager walletManager, ITracker tracker)
{
this.walletManager = walletManager;
this.tracker = tracker;
}
/// <summary>
......@@ -120,9 +123,10 @@ namespace Breeze.Wallet.Controllers
// get the wallet folder
DirectoryInfo walletFolder = GetWalletFolder(request.FolderPath);
Wallet wallet = this.walletManager.RecoverWallet(request.Password, walletFolder.FullName, request.Name, request.Network, request.Mnemonic);
Wallet wallet = this.walletManager.RecoverWallet(request.Password, walletFolder.FullName, request.Name, request.Network, request.Mnemonic, null, request.CreationDate);
// TODO give the tracker the date at which this wallet was originally created so that it can start syncing blocks for it
// start syncing the wallet from the creation date
this.tracker.SyncFrom(request.CreationDate);
return this.Json(new WalletModel
{
......
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
using NBitcoin;
namespace Breeze.Wallet
......@@ -16,5 +17,12 @@ namespace Breeze.Wallet
/// </summary>
/// <returns></returns>
Task WaitForChainDownloadAsync();
/// <summary>
/// Synchronize the wallet starting from the date passed as a parameter.
/// </summary>
/// <param name="date">The date from which to start the sync process.</param>
/// <returns></returns>
void SyncFrom(DateTime date);
}
}
......@@ -39,9 +39,9 @@ namespace Breeze.Wallet
/// <param name="network">The network in which to creae this wallet</param>
/// <param name="mnemonic">The user's mnemonic for the wallet.</param>
/// <param name="passphrase">The passphrase used in the seed.</param>
/// <param name="creationTime">The time this wallet was created.</param>
/// <param name="creationTime">The date and time this wallet was created.</param>
/// <returns>The recovered wallet.</returns>
Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTimeOffset? creationTime = null);
Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTime? creationTime = null);
/// <summary>
/// Deletes a wallet.
......
using System.Collections;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace Breeze.Wallet.Models
{
......@@ -45,6 +48,9 @@ namespace Breeze.Wallet.Models
public string Name { get; set; }
public string Network { get; set; }
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime CreationDate { get; set; }
}
public class WalletHistoryRequest
......
......@@ -84,6 +84,15 @@ namespace Breeze.Wallet
repeatEvery: TimeSpans.FiveSeconds);
}
/// <inheritdoc />
public void SyncFrom(DateTime date)
{
int blockSyncStart = this.chain.GetHeightAtTime(date);
// start syncing blocks
this.blockNotification.SyncFrom(this.chain.GetBlock(blockSyncStart).HashBlock);
}
private bool BlocksSynced()
{
return this.walletManager.Wallets.All(w => w.AccountsRoot.Single(a => a.CoinType == this.coinType).LastBlockSyncedHeight == this.chain.Tip.Height);
......
......@@ -76,7 +76,7 @@ namespace Breeze.Wallet
}
/// <inheritdoc />
public Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTimeOffset? creationTime = null)
public Wallet RecoverWallet(string password, string folderPath, string name, string network, string mnemonic, string passphrase = null, DateTime? creationTime = null)
{
// for now the passphrase is set to be the password by default.
if (passphrase == null)
......
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