Skip to content

Commit

Permalink
added import-key endpoint (stratisproject#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
bokobza authored and monsieurleberre committed Jun 13, 2018
1 parent 0c41a24 commit 1f5645d
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Logging;
using NBitcoin;
using Stratis.Bitcoin.Utilities;
using Stratis.Bitcoin.Utilities.JsonErrors;
Expand All @@ -20,15 +21,26 @@ namespace Stratis.FederatedPeg.Features.FederationGateway.Controllers
[Route("api/[controller]")]
public class FederationGatewayController : Controller
{
/// <summary>Instance logger.</summary>
private readonly ILogger logger;

private ICounterChainSessionManager counterChainSessionManager;

private IMonitorChainSessionManager monitorChainSessionManager;

public FederationGatewayController(ICounterChainSessionManager counterChainSessionManager,
IMonitorChainSessionManager monitorChainSessionManager)
/// <summary>Specification of the network the node runs on.</summary>
private readonly Network network;

public FederationGatewayController(
ILoggerFactory loggerFactory,
ICounterChainSessionManager counterChainSessionManager,
IMonitorChainSessionManager monitorChainSessionManager,
Network network)
{
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
this.monitorChainSessionManager = monitorChainSessionManager;
this.counterChainSessionManager = counterChainSessionManager;
this.network = network;
}

[Route("create-session-oncounterchain")]
Expand Down Expand Up @@ -89,6 +101,35 @@ public async Task<IActionResult> CreatePartialTransactionSession([FromBody] Crea
}
}

/// <summary>
/// Imports the federation member's mnemonic key.
/// </summary>
/// <param name="request">The object containing the parameters used to recover a wallet.</param>
/// <returns></returns>
[Route("import-key")]
[HttpPost]
public IActionResult ImportMemberKey([FromBody]ImportMemberKeyRequest request)
{
Guard.NotNull(request, nameof(request));

// checks the request is valid
if (!this.ModelState.IsValid)
{
return BuildErrorResponse(this.ModelState);
}

try
{
this.counterChainSessionManager.ImportMemberKey(request.Password, request.Mnemonic);
return this.Ok();
}
catch (Exception e)
{
this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}

/// <summary>
/// Builds an <see cref="IActionResult"/> containing errors contained in the <see cref="ControllerBase.ModelState"/>.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin;
using Stratis.Bitcoin;
using Stratis.Bitcoin.Configuration;
using Stratis.Bitcoin.Connection;
using Stratis.Bitcoin.Features.GeneralPurposeWallet;
using Stratis.Bitcoin.Features.GeneralPurposeWallet.Interfaces;
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Interfaces;
using Stratis.Bitcoin.P2P.Peer;
using Stratis.Bitcoin.Utilities;
using Stratis.FederatedPeg.Features.FederationGateway.Models;
using CoinType = Stratis.Bitcoin.Features.GeneralPurposeWallet.CoinType;
using Recipient = Stratis.Bitcoin.Features.GeneralPurposeWallet.Recipient;
using TransactionBuildContext = Stratis.Bitcoin.Features.GeneralPurposeWallet.TransactionBuildContext;

namespace Stratis.FederatedPeg.Features.FederationGateway.CounterChain
{
Expand Down Expand Up @@ -43,18 +51,45 @@ internal class CounterChainSessionManager : ICounterChainSessionManager
// The logger. It's the logger.
private readonly ILogger logger;

/// <summary>Provider of time functions.</summary>
private readonly IDateTimeProvider dateTimeProvider;

// The shoulders we stand on.
private IFullNode fullnode;

/// <summary>An object capable of storing <see cref="MemberDetails"/>s to the file system.</summary>
private readonly FileStorage<MemberDetails> fileStorage;

/// <summary>
/// The name of the member details file.
/// </summary>
private const string MemberDetailsFileName = "member_details.json";

public MemberDetails MemberDetails { get; }

// The sessions are stored here.
private ConcurrentDictionary<uint256, CounterChainSession> sessions = new ConcurrentDictionary<uint256, CounterChainSession>();

// Get everything together before we get going.
public CounterChainSessionManager(ILoggerFactory loggerFactory, IGeneralPurposeWalletManager generalPurposeWalletManager,
IGeneralPurposeWalletTransactionHandler generalPurposeWalletTransactionHandler, IConnectionManager connectionManager, Network network,
FederationGatewaySettings federationGatewaySettings, IInitialBlockDownloadState initialBlockDownloadState, IFullNode fullnode,
IGeneralPurposeWalletBroadcasterManager broadcastManager, ConcurrentChain concurrentChain, ICrossChainTransactionAuditor crossChainTransactionAuditor = null)
public CounterChainSessionManager(
ILoggerFactory loggerFactory,
IGeneralPurposeWalletManager generalPurposeWalletManager,
IGeneralPurposeWalletTransactionHandler generalPurposeWalletTransactionHandler,
IConnectionManager connectionManager,
Network network,
FederationGatewaySettings federationGatewaySettings,
IInitialBlockDownloadState initialBlockDownloadState,
IFullNode fullnode,
IGeneralPurposeWalletBroadcasterManager broadcastManager,
ConcurrentChain concurrentChain,
DataFolder dataFolder,
IDateTimeProvider dateTimeProvider,
ICrossChainTransactionAuditor crossChainTransactionAuditor = null)
{
Guard.NotNull(loggerFactory, nameof(loggerFactory));
Guard.NotNull(network, nameof(network));
Guard.NotNull(dataFolder, nameof(dataFolder));

this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
this.network = network;
this.connectionManager = connectionManager;
Expand All @@ -65,6 +100,12 @@ public CounterChainSessionManager(ILoggerFactory loggerFactory, IGeneralPurposeW
this.generalPurposeWalletManager = generalPurposeWalletManager;
this.generalPurposeWalletTransactionHandler = generalPurposeWalletTransactionHandler;
this.federationGatewaySettings = federationGatewaySettings;
this.dateTimeProvider = dateTimeProvider;
this.fileStorage = new FileStorage<MemberDetails>(dataFolder.RootPath);

if (this.fileStorage.Exists(MemberDetailsFileName))
this.MemberDetails = this.fileStorage.LoadByFileName(MemberDetailsFileName);

}

///<inheritdoc/>
Expand Down Expand Up @@ -289,5 +330,54 @@ public void MarkSessionAsSigned(CounterChainSession session)
this.logger.LogInformation($"{this.federationGatewaySettings.MemberName} has signed session {session.SessionId}.");
session.HaveISigned = true;
}

/// <inheritdoc />
public void ImportMemberKey(string password, string mnemonic)
{
Guard.NotEmpty(password, nameof(password));
Guard.NotEmpty(mnemonic, nameof(mnemonic));

// Get the extended key.
ExtKey extendedKey;
try
{
extendedKey = HdOperations.GetExtendedKey(mnemonic, password);
}
catch (NotSupportedException ex)
{
this.logger.LogTrace("Exception occurred: {0}", ex.ToString());
this.logger.LogTrace("(-)[EXCEPTION]");

if (ex.Message == "Unknown")
throw new WalletException("Please make sure you enter valid mnemonic words.");

throw;
}

// Create a wallet file.
string encryptedSeed = extendedKey.PrivateKey.GetEncryptedBitcoinSecret(password, this.network).ToWif();

MemberDetails memberDetails = new MemberDetails
{
EncryptedSeed = encryptedSeed,
CreationTime = this.dateTimeProvider.GetTimeOffset()
};

// Save the changes to the file and add addresses to be tracked.
this.SaveMemberDetails(memberDetails);

this.logger.LogTrace("(-)");
}

public void SaveMemberDetails(MemberDetails memberDetails)
{
Guard.NotNull(memberDetails, nameof(memberDetails));
this.logger.LogTrace("({0}:'{1}')", nameof(memberDetails), memberDetails);

this.fileStorage.SaveToFile(memberDetails, MemberDetailsFileName);

this.logger.LogTrace("(-)");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,12 @@ public interface ICounterChainSessionManager
/// </summary>
/// <param name="session">The session.</param>
void MarkSessionAsSigned(CounterChainSession session);

/// <summary>
/// Imports the federation member's mnemonic key.
/// </summary>
/// <param name="password">The user's password.</param>
/// <param name="mnemonic">The user's mnemonic.</param>
void ImportMemberKey(string password, string mnemonic);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using Stratis.Bitcoin.Utilities.JsonConverters;

namespace Stratis.FederatedPeg.Features.FederationGateway.Models
{
public class MemberDetails
{
/// <summary>
/// The seed for this wallet, password encrypted.
/// </summary>
[JsonProperty(PropertyName = "encryptedSeed")]
public string EncryptedSeed { get; set; }

/// <summary>
/// The time this was created.
/// </summary>
[JsonProperty(PropertyName = "creationTime")]
[JsonConverter(typeof(DateTimeOffsetConverter))]
public DateTimeOffset CreationTime { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,13 @@ public class CreateCounterChainSessionRequest : RequestModel
[Required(ErrorMessage = "Destination Address required.")]
public string DestinationAddress { get; set; }
}

public class ImportMemberKeyRequest : RequestModel
{
[Required(ErrorMessage = "A mnemonic is required.")]
public string Mnemonic { get; set; }

[Required(ErrorMessage = "A password is required.")]
public string Password { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<ItemGroup>
<PackageReference Include="Stratis.Bitcoin" Version="1.1.11-beta" />
<PackageReference Include="Stratis.Bitcoin.Features.Notifications" Version="1.1.11-beta" />
<PackageReference Include="Stratis.Bitcoin.Features.Wallet" Version="1.1.11-beta" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 1f5645d

Please sign in to comment.