Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,29 @@ public IActionResult GetColdStakingAddress([FromQuery]GetColdStakingAddressReque
[Route("setup-cold-staking")]
[HttpPost]
public IActionResult SetupColdStaking([FromBody]SetupColdStakingRequest request)
{
return this.SetupColdStakingInternal(request, true);
}

/// <summary>
/// Spends funds from a normal wallet addresses to the cold staking script. It is expected that this
/// spend will be detected by both the hot wallet and cold wallet and allow cold staking to occur using this
/// transaction's output as input.
/// </summary>
/// <param name="request">A <see cref="SetupColdStakingRequest"/> object containing the cold staking setup parameters.</param>
/// <returns>A <see cref="SetupColdStakingResponse"/> object containing the hex representation of the transaction.</returns>
/// <seealso cref="ColdStakingManager.GetColdStakingScript(ScriptId, ScriptId)"/>
[Route("setup-offline-staking")]
[HttpPost]
public IActionResult SetupOfflineStaking([FromBody] SetupColdStakingRequest request)
{
return this.SetupColdStakingInternal(request, false);
}

private IActionResult SetupColdStakingInternal(SetupColdStakingRequest request, bool createHotAccount)
{
Guard.NotNull(request, nameof(request));

// Checks the request is valid.
if (!this.ModelState.IsValid)
{
Expand All @@ -193,7 +213,7 @@ public IActionResult SetupColdStaking([FromBody]SetupColdStakingRequest request)

Transaction transaction = this.ColdStakingManager.GetColdStakingSetupTransaction(
this.walletTransactionHandler, request.ColdWalletAddress, request.HotWalletAddress,
request.WalletName, request.WalletAccount, request.WalletPassword, amount, feeAmount, request.SegwitChangeAddress, request.PayToScript);
request.WalletName, request.WalletAccount, request.WalletPassword, amount, feeAmount, request.SegwitChangeAddress, request.PayToScript, createHotAccount);

var model = new SetupColdStakingResponse
{
Expand Down
15 changes: 13 additions & 2 deletions src/Features/Blockcore.Features.ColdStaking/ColdStakingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,11 @@ internal HdAddress GetFirstUnusedColdStakingAddress(string walletName, bool isCo
/// <param name="payToScript">Indicate script staking (P2SH or P2WSH outputs).</param>
/// <returns>The <see cref="Transaction"/> for setting up cold staking.</returns>
/// <exception cref="WalletException">Thrown if any of the rules listed in the remarks section of this method are broken.</exception>
///

internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler walletTransactionHandler,
string coldWalletAddress, string hotWalletAddress, string walletName, string walletAccount,
string walletPassword, Money amount, Money feeAmount, bool useSegwitChangeAddress = false, bool payToScript = false)
string walletPassword, Money amount, Money feeAmount, bool useSegwitChangeAddress = false, bool payToScript = false, bool createHotAccount = true)
{
Guard.NotNull(walletTransactionHandler, nameof(walletTransactionHandler));
Guard.NotEmpty(coldWalletAddress, nameof(coldWalletAddress));
Expand All @@ -344,7 +346,16 @@ internal Transaction GetColdStakingSetupTransaction(IWalletTransactionHandler wa

// Get/create the cold staking accounts.
HdAccount coldAccount = this.GetOrCreateColdStakingAccount(walletName, true, walletPassword);
HdAccount hotAccount = this.GetOrCreateColdStakingAccount(walletName, false, walletPassword);
HdAccount hotAccount;

if (createHotAccount)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait the problem is only with hot accounts?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is having both active at the same time, there is no need for the reversed.

{
hotAccount = this.GetOrCreateColdStakingAccount(walletName, false, walletPassword);
}
else
{
hotAccount = this.GetColdStakingAccount(this.GetWalletByName(walletName), false);
}

HdAddress coldAddress = coldAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == coldWalletAddress || s.Bech32Address == coldWalletAddress);
HdAddress hotAddress = hotAccount?.ExternalAddresses.FirstOrDefault(s => s.Address == hotWalletAddress || s.Bech32Address == hotWalletAddress);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ public void RecoverWalletSuccessfullyReturnsWalletModel()
};

var mockWalletManager = new Mock<IWalletManager>();
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, true)).Returns(wallet);
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, null)).Returns(wallet);

Mock<IWalletSyncManager> walletSyncManager = new Mock<IWalletSyncManager>();
walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3));
Expand Down Expand Up @@ -368,7 +368,7 @@ public void RecoverWalletWithDatedAfterCurrentSyncHeightDoesNotMoveSyncHeight()
DateTime lastBlockDateTime = chainIndexer.Tip.Header.BlockTime.DateTime;

var mockWalletManager = new Mock<IWalletManager>();
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, true)).Returns(wallet);
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, null)).Returns(wallet);

Mock<IWalletSyncManager> walletSyncManager = new Mock<IWalletSyncManager>();
walletSyncManager.Setup(w => w.WalletTip).Returns(new ChainedHeader(this.Network.GetGenesis().Header, this.Network.GetGenesis().Header.GetHash(), 3));
Expand Down Expand Up @@ -419,7 +419,7 @@ public void RecoverWalletWithInvalidOperationExceptionReturnsConflict()
{
string errorMessage = "An error occurred.";
var mockWalletManager = new Mock<IWalletManager>();
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, true))
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, null))
.Throws(new WalletException(errorMessage));

var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock<IWalletTransactionHandler>().Object, new Mock<IWalletSyncManager>().Object, It.IsAny<ConnectionManager>(), this.Network, this.chainIndexer, new Mock<IBroadcasterManager>().Object, DateTimeProvider.Default);
Expand All @@ -445,7 +445,7 @@ public void RecoverWalletWithInvalidOperationExceptionReturnsConflict()
public void RecoverWalletWithFileNotFoundExceptionReturnsNotFound()
{
var mockWalletManager = new Mock<IWalletManager>();
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, true))
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, null))
.Throws(new FileNotFoundException("File not found."));

var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock<IWalletTransactionHandler>().Object, new Mock<IWalletSyncManager>().Object, It.IsAny<ConnectionManager>(), this.Network, this.chainIndexer, new Mock<IBroadcasterManager>().Object, DateTimeProvider.Default);
Expand All @@ -472,7 +472,7 @@ public void RecoverWalletWithFileNotFoundExceptionReturnsNotFound()
public void RecoverWalletWithExceptionReturnsBadRequest()
{
var mockWalletManager = new Mock<IWalletManager>();
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, true))
mockWalletManager.Setup(w => w.RecoverWallet(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<DateTime>(), null, null, null))
.Throws(new FormatException("Formatting failed."));

var controller = new WalletController(this.LoggerFactory.Object, mockWalletManager.Object, new Mock<IWalletTransactionHandler>().Object, new Mock<IWalletSyncManager>().Object, It.IsAny<ConnectionManager>(), this.Network, this.chainIndexer, new Mock<IBroadcasterManager>().Object, DateTimeProvider.Default);
Expand Down