Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create ReservedUtxoService #2

Merged
merged 19 commits into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -28,6 +28,7 @@
using Stratis.Bitcoin.Features.MemoryPool.Rules;
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.Features.Wallet.Services;
using Stratis.Bitcoin.Signals;
using Stratis.Bitcoin.Tests.Common;
using Stratis.Bitcoin.Utilities;
Expand Down Expand Up @@ -217,15 +218,18 @@ private void Initialize([System.Runtime.CompilerServices.CallerMemberName] strin

var scriptDestinationReader = new ColdStakingDestinationReader(new ScriptAddressReader());

IWalletRepository walletRepository = new SQLiteWalletRepository(this.loggerFactory, this.nodeSettings.DataFolder, this.Network, DateTimeProvider.Default, scriptDestinationReader);
walletRepository.TestMode = true;
IWalletRepository walletRepository = new SQLiteWalletRepository(this.loggerFactory, this.nodeSettings.DataFolder, this.Network, DateTimeProvider.Default, scriptDestinationReader)
{
TestMode = true
};

this.coldStakingManager = new ColdStakingManager(this.Network, new ChainIndexer(this.Network), walletSettings, this.nodeSettings.DataFolder,
new Mock<IWalletFeePolicy>().Object, new Mock<IAsyncProvider>().Object, new NodeLifetime(), scriptDestinationReader,
this.loggerFactory, DateTimeProvider.Default, walletRepository);

var walletTransactionHandler = new WalletTransactionHandler(this.loggerFactory, this.coldStakingManager,
new Mock<IWalletFeePolicy>().Object, this.Network, new StandardTransactionPolicy(this.Network));
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var walletTransactionHandler = new WalletTransactionHandler(this.loggerFactory, this.coldStakingManager, new Mock<IWalletFeePolicy>().Object, this.Network, new StandardTransactionPolicy(this.Network), reserveUtxoService);

this.coldStakingController = new ColdStakingController(this.loggerFactory, this.coldStakingManager, walletTransactionHandler);

Expand Down Expand Up @@ -281,9 +285,6 @@ public void ColdStakingVerifyWalletAddresses()
this.coldStakingManager.GetOrCreateColdStakingAccount(walletName2, true, walletPassword);
this.coldStakingManager.GetOrCreateColdStakingAccount(walletName2, false, walletPassword);

var wallet1 = this.coldStakingManager.GetWallet(walletName1);
var wallet2 = this.coldStakingManager.GetWallet(walletName2);

HdAddress coldAddress1 = this.coldStakingManager.GetFirstUnusedColdStakingAddress(walletName1, true);
HdAddress hotAddress1 = this.coldStakingManager.GetFirstUnusedColdStakingAddress(walletName1, false);
HdAddress coldAddress2 = this.coldStakingManager.GetFirstUnusedColdStakingAddress(walletName2, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Stratis.Bitcoin.Features.MemoryPool
/// <summary>
/// Event that is executed when a transaction is removed from the mempool.
/// </summary>
/// <seealso cref="Stratis.Bitcoin.EventBus.EventBase" />
/// <seealso cref="EventBase" />
public class TransactionAddedToMemoryPool : EventBase
{
public Transaction AddedTransaction { get; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
using System.Collections.Generic;
using System.Linq;
using CSharpFunctionalExtensions;
using Microsoft.Extensions.Logging;
using Moq;
using NBitcoin;
using Stratis.Bitcoin.Features.SmartContracts.Models;
using Stratis.Bitcoin.Features.SmartContracts.Wallet;
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.Features.Wallet.Models;
using Stratis.Sidechains.Networks;
using Stratis.Bitcoin.Features.Wallet.Services;
using Stratis.Bitcoin.Signals;
using Stratis.SmartContracts.CLR;
using Stratis.SmartContracts.CLR.Serialization;
using Stratis.SmartContracts.Core.State;
Expand Down Expand Up @@ -113,18 +115,21 @@ public void CanChooseInputsForCall()
this.walletManager.Setup(x => x.GetWallet(request.WalletName))
.Returns(wallet);

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

BuildCallContractTransactionResponse result = service.BuildCallTx(request);

this.walletTransactionHandler.Verify(x=>x.BuildTransaction(It.Is<TransactionBuildContext>(y =>y.SelectedInputs.Count == 1)));
this.walletTransactionHandler.Verify(x => x.BuildTransaction(It.Is<TransactionBuildContext>(y => y.SelectedInputs.Count == 1)));
}

[Fact]
Expand Down Expand Up @@ -193,14 +198,17 @@ public void ChoosingInvalidInputFails()
}
});

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

BuildCallContractTransactionResponse result = service.BuildCallTx(request);
Assert.False(result.Success);
Expand Down Expand Up @@ -274,23 +282,26 @@ public void CanChooseInputsForCreate()

var wallet = new Features.Wallet.Wallet();
wallet.AccountsRoot.Add(new AccountRoot(wallet));
var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts) { Name = request.AccountName };;
var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts) { Name = request.AccountName }; ;
account0.ExternalAddresses.Add(new HdAddress() { Address = senderAddress });

this.walletManager.Setup(x => x.GetWallet(request.WalletName))
.Returns(wallet);

this.callDataSerializer.Setup(x => x.Deserialize(It.IsAny<byte[]>()))
.Returns(Result.Ok(new ContractTxData(1, 100, (Gas) 100_000, new byte[0])));
.Returns(Result.Ok(new ContractTxData(1, 100, (Gas)100_000, new byte[0])));

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

BuildCreateContractTransactionResponse result = service.BuildCreateTx(request);

Expand All @@ -302,14 +313,17 @@ public void BuildTransferContext_SenderNotInWallet_Fails()
{
string senderAddress = uint160.Zero.ToBase58Address(this.network);

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

var request = new BuildContractTransactionRequest
{
Expand Down Expand Up @@ -339,14 +353,17 @@ public void BuildTransferContext_AccountNotInWallet_Fails()
{
string senderAddress = uint160.Zero.ToBase58Address(this.network);

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

var request = new BuildContractTransactionRequest
{
Expand Down Expand Up @@ -376,14 +393,17 @@ public void BuildTransferContext_SenderHasNoBalance_Fails()
{
string senderAddress = uint160.Zero.ToBase58Address(this.network);

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

var request = new BuildContractTransactionRequest
{
Expand Down Expand Up @@ -420,14 +440,17 @@ public void BuildTransferContext_RecipientIsKnownContract_Fails()
string senderAddress = uint160.Zero.ToBase58Address(this.network);
string recipientAddress = uint160.One.ToBase58Address(this.network);

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

var request = new BuildContractTransactionRequest
{
Expand Down Expand Up @@ -635,14 +658,17 @@ public void BuildTransferContextCorrectly()
}
};

SmartContractTransactionService service = new SmartContractTransactionService(
var reserveUtxoService = new ReserveUtxoService(new Mock<ILoggerFactory>().Object, new Mock<ISignals>().Object);

var service = new SmartContractTransactionService(
this.network,
this.walletManager.Object,
this.walletTransactionHandler.Object,
this.stringSerializer.Object,
this.callDataSerializer.Object,
this.addressGenerator.Object,
this.stateRepository.Object);
this.stateRepository.Object,
reserveUtxoService);

var senderHdAddress = new HdAddress { Address = senderAddress };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.Features.Wallet.Models;
using Stratis.Bitcoin.Features.Wallet.Services;
using Stratis.SmartContracts.CLR;
using Stratis.SmartContracts.CLR.Serialization;
using Stratis.SmartContracts.Core;
Expand Down Expand Up @@ -35,6 +36,7 @@ public class SmartContractTransactionService : ISmartContractTransactionService
private readonly ICallDataSerializer callDataSerializer;
private readonly IAddressGenerator addressGenerator;
private readonly IStateRepositoryRoot stateRoot;
private readonly IReserveUtxoService reserveUtxoService;

public SmartContractTransactionService(
Network network,
Expand All @@ -43,7 +45,9 @@ public SmartContractTransactionService(
IMethodParameterStringSerializer methodParameterStringSerializer,
ICallDataSerializer callDataSerializer,
IAddressGenerator addressGenerator,
IStateRepositoryRoot stateRoot)
IStateRepositoryRoot stateRoot,
IReserveUtxoService reserveUtxoService
)
{
this.network = network;
this.walletManager = walletManager;
Expand All @@ -52,6 +56,7 @@ public SmartContractTransactionService(
this.callDataSerializer = callDataSerializer;
this.addressGenerator = addressGenerator;
this.stateRoot = stateRoot;
this.reserveUtxoService = reserveUtxoService;
}

public EstimateFeeResult EstimateFee(ScTxFeeEstimateRequest request)
Expand Down Expand Up @@ -81,7 +86,7 @@ public EstimateFeeResult EstimateFee(ScTxFeeEstimateRequest request)
var recipients = new List<Recipient>();
foreach (RecipientModel recipientModel in request.Recipients)
{
BitcoinAddress bitcoinAddress = BitcoinAddress.Create(recipientModel.DestinationAddress, this.network);
var bitcoinAddress = BitcoinAddress.Create(recipientModel.DestinationAddress, this.network);

// If it's a potential SC address, check if it's a contract.
if (bitcoinAddress is BitcoinPubKeyAddress bitcoinPubKeyAddress)
Expand Down Expand Up @@ -359,11 +364,28 @@ private bool CheckBalance(string address)
return !(addressBalance.AmountConfirmed == 0 && addressBalance.AmountUnconfirmed == 0);
}

private List<OutPoint> SelectInputs(string walletName, string sender, List<OutpointRequest> outpoints)
private List<OutPoint> SelectInputs(string walletName, string sender, List<OutpointRequest> requestedOutpoints)
{
List<OutPoint> selectedInputs = this.walletManager.GetSpendableInputsForAddress(walletName, sender);

return this.ReduceToRequestedInputs(outpoints, selectedInputs);
if (requestedOutpoints != null && requestedOutpoints.Any())
selectedInputs = this.ReduceToRequestedInputs(requestedOutpoints, selectedInputs);

FilterReservedInputs(selectedInputs);

return selectedInputs;
}

private List<OutPoint> FilterReservedInputs(List<OutPoint> selectedInputs)
{
var result = new List<OutPoint>();
foreach (OutPoint input in selectedInputs)
{
if (!this.reserveUtxoService.IsUtxoReserved(input))
result.Add(input);
}

return result;
}

/// <summary>
Expand All @@ -374,16 +396,13 @@ private List<OutPoint> ReduceToRequestedInputs(IReadOnlyList<OutpointRequest> re
{
var result = new List<OutPoint>(selectedInputs);

if (requestedOutpoints != null && requestedOutpoints.Any())
{
//Convert outpointRequest to OutPoint
IEnumerable<OutPoint> requestedOutPoints = requestedOutpoints.Select(outPointRequest => new OutPoint(new uint256(outPointRequest.TransactionId), outPointRequest.Index));
//Convert outpointRequest to OutPoint
fassadlr marked this conversation as resolved.
Show resolved Hide resolved
IEnumerable<OutPoint> requestedOutPoints = requestedOutpoints.Select(outPointRequest => new OutPoint(new uint256(outPointRequest.TransactionId), outPointRequest.Index));

for (int i = result.Count - 1; i >= 0; i--)
{
if (!requestedOutPoints.Contains(result[i]))
result.RemoveAt(i);
}
for (int i = result.Count - 1; i >= 0; i--)
{
if (!requestedOutPoints.Contains(result[i]))
result.RemoveAt(i);
}

return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using NBitcoin.Policy;
using Stratis.Bitcoin.Features.Wallet;
using Stratis.Bitcoin.Features.Wallet.Interfaces;
using Stratis.Bitcoin.Features.Wallet.Services;
using Stratis.Bitcoin.Utilities;
using Stratis.SmartContracts.Core;

Expand All @@ -17,8 +18,9 @@ public SmartContractWalletTransactionHandler(
IWalletManager walletManager,
IWalletFeePolicy walletFeePolicy,
Network network,
StandardTransactionPolicy transactionPolicy) :
base(loggerFactory, walletManager, walletFeePolicy, network, transactionPolicy)
StandardTransactionPolicy transactionPolicy,
IReserveUtxoService utxoReservedService) :
base(loggerFactory, walletManager, walletFeePolicy, network, transactionPolicy, utxoReservedService)
{
}

Expand Down
Loading