diff --git a/Scripts/STRAXSidechainRegistrationScript.ps1 b/Scripts/STRAXSidechainRegistrationScript.ps1
index 7794caecc4..1cea9e7447 100644
--- a/Scripts/STRAXSidechainRegistrationScript.ps1
+++ b/Scripts/STRAXSidechainRegistrationScript.ps1
@@ -188,7 +188,8 @@ While ( ( Get-MaxHeight ) -eq $null )
While ( ( Get-MaxHeight ) -gt ( Get-LocalIndexerHeight ) )
{
$a = Get-MaxHeight
- $b = Get-LocalIndexerHeight
+ $b = Get-LocalIndexerHeight
+ $c = $a - $b
[int]$percentage = $b / $a * 100
""
Write-Host (Get-TimeStamp) "$percentage% Synced" -ForegroundColor Cyan
diff --git a/src/FederationSetup/FederationSetup.csproj b/src/FederationSetup/FederationSetup.csproj
index 3b7d953d51..69b5b66a07 100644
--- a/src/FederationSetup/FederationSetup.csproj
+++ b/src/FederationSetup/FederationSetup.csproj
@@ -3,7 +3,7 @@
Exe
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis Group Ltd.
diff --git a/src/FodyNlogAdapter/FodyNlogAdapter.csproj b/src/FodyNlogAdapter/FodyNlogAdapter.csproj
index ab1d18a171..edfea59ee0 100644
--- a/src/FodyNlogAdapter/FodyNlogAdapter.csproj
+++ b/src/FodyNlogAdapter/FodyNlogAdapter.csproj
@@ -3,7 +3,7 @@
netcoreapp3.1
FodyNlogAdapter
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
Stratis.Utils.FodyNlogAdapter
diff --git a/src/NBitcoin/BIP39/Mnemonic.cs b/src/NBitcoin/BIP39/Mnemonic.cs
index 6b322a5905..ddfca69f04 100644
--- a/src/NBitcoin/BIP39/Mnemonic.cs
+++ b/src/NBitcoin/BIP39/Mnemonic.cs
@@ -27,7 +27,7 @@ public Mnemonic(string mnemonic, Wordlist wordlist = null)
wordlist = Wordlist.AutoDetect(mnemonic) ?? Wordlist.English;
string[] words = mnemonic.Split((char[])null, StringSplitOptions.RemoveEmptyEntries);
- _Mnemonic = string.Join(wordlist.Space.ToString(), words);
+ this._Mnemonic = string.Join(wordlist.Space.ToString(), words);
//if the sentence is not at least 12 characters or cleanly divisible by 3, it is bad!
if (!CorrectWordCount(words.Length))
@@ -54,7 +54,7 @@ public Mnemonic(Wordlist wordList, byte[] entropy = null)
int i = Array.IndexOf(entArray, entropy.Length * 8);
if(i == -1)
- throw new ArgumentException("The length for entropy should be : " + String.Join(",", entArray), "entropy");
+ throw new ArgumentException("The length for entropy should be : " + string.Join(",", entArray), "entropy");
int cs = csArray[i];
byte[] checksum = Hashes.SHA256(entropy);
@@ -200,10 +200,10 @@ public ExtKey DeriveExtKey(string passphrase = null)
return new ExtKey(DeriveSeed(passphrase));
}
- private static Byte[] Concat(Byte[] source1, Byte[] source2)
+ private static byte[] Concat(byte[] source1, byte[] source2)
{
//Most efficient way to merge two arrays this according to http://stackoverflow.com/questions/415291/best-way-to-combine-two-or-more-byte-arrays-in-c-sharp
- var buffer = new Byte[source1.Length + source2.Length];
+ var buffer = new byte[source1.Length + source2.Length];
Buffer.BlockCopy(source1, 0, buffer, 0, source1.Length);
Buffer.BlockCopy(source2, 0, buffer, source1.Length, source2.Length);
diff --git a/src/NBitcoin/ConsensusOptions.cs b/src/NBitcoin/ConsensusOptions.cs
index 7c7ead2f73..42e16f3bb0 100644
--- a/src/NBitcoin/ConsensusOptions.cs
+++ b/src/NBitcoin/ConsensusOptions.cs
@@ -13,7 +13,7 @@ public class ConsensusOptions
///
public const int SerializeTransactionNoWitness = 0x40000000;
- /// Maximum size for a block in bytes.
+ /// Maximum size for a block in bytes.
public uint MaxBlockBaseSize { get; set; }
/// The maximum allowed weight for a block, see BIP 141 (network rule)
diff --git a/src/NBitcoin/Money.cs b/src/NBitcoin/Money.cs
index 4fdeb62091..03f485c08d 100644
--- a/src/NBitcoin/Money.cs
+++ b/src/NBitcoin/Money.cs
@@ -857,7 +857,7 @@ public string Format(string format, object arg, IFormatProvider formatProvider)
i++;
}
char unit = format[i];
- var unitToUseInCalc = MoneyUnit.BTC;
+ MoneyUnit unitToUseInCalc = MoneyUnit.BTC;
switch (unit)
{
case 'B':
diff --git a/src/NBitcoin/NBitcoin.csproj b/src/NBitcoin/NBitcoin.csproj
index ac190dbe71..0f1180eea6 100644
--- a/src/NBitcoin/NBitcoin.csproj
+++ b/src/NBitcoin/NBitcoin.csproj
@@ -2,12 +2,12 @@
NStratis
- Copyright © Stratis Platform SA 2020
+ Copyright © Stratis Platform SA 2022
The C# Bitcoin Library based on NBitcoin
- 4.0.0.83
+ 4.0.0.84
diff --git a/src/NBitcoin/TransactionBuilder.cs b/src/NBitcoin/TransactionBuilder.cs
index cb8cc12014..994aea9e4e 100644
--- a/src/NBitcoin/TransactionBuilder.cs
+++ b/src/NBitcoin/TransactionBuilder.cs
@@ -1584,7 +1584,7 @@ public int EstimateSize(Transaction tx, bool virtualSize)
int witSize = 0;
if (tx.HasWitness)
witSize += 2;
- foreach (var txin in tx.Inputs.AsIndexedInputs())
+ foreach (IndexedTxIn txin in tx.Inputs.AsIndexedInputs())
{
ICoin coin = FindSignableCoin(txin) ?? FindCoin(txin.PrevOut);
if (coin == null)
diff --git a/src/Stratis.Bitcoin.Api.Tests/ApiSettingsTest.cs b/src/Stratis.Bitcoin.Api.Tests/ApiSettingsTest.cs
index 68e35b79a9..4ca9711a65 100644
--- a/src/Stratis.Bitcoin.Api.Tests/ApiSettingsTest.cs
+++ b/src/Stratis.Bitcoin.Api.Tests/ApiSettingsTest.cs
@@ -231,7 +231,7 @@ public void GivenUseHttps_ThenUsesTheCorrectProtocol(bool useHttps, string expec
var nodeSettings = new NodeSettings(KnownNetworks.TestNet, args: new[] { $"-usehttps={useHttps}", "-certificatefilepath=nonNullValue" });
// Act.
- var settings = FullNodeSetup(nodeSettings);
+ ApiSettings settings = FullNodeSetup(nodeSettings);
// Assert.
settings.UseHttps.Should().Be(useHttps);
diff --git a/src/Stratis.Bitcoin.Cli/Stratis.Bitcoin.Cli.csproj b/src/Stratis.Bitcoin.Cli/Stratis.Bitcoin.Cli.csproj
index cb03d021d6..6fef66ca86 100644
--- a/src/Stratis.Bitcoin.Cli/Stratis.Bitcoin.Cli.csproj
+++ b/src/Stratis.Bitcoin.Cli/Stratis.Bitcoin.Cli.csproj
@@ -3,7 +3,7 @@
Exe
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis Group Ltd.
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Api/NodeController.cs b/src/Stratis.Bitcoin.Features.Api/NodeController.cs
index 9a22d2ed89..17019e21c6 100644
--- a/src/Stratis.Bitcoin.Features.Api/NodeController.cs
+++ b/src/Stratis.Bitcoin.Features.Api/NodeController.cs
@@ -7,7 +7,6 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using NLog.Config;
using NLog.Targets;
using NLog.Targets.Wrappers;
@@ -15,6 +14,7 @@
using Stratis.Bitcoin.Base;
using Stratis.Bitcoin.Builder.Feature;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Connection;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.Controllers.Models;
@@ -27,7 +27,6 @@
using Stratis.Bitcoin.Utilities;
using Stratis.Bitcoin.Utilities.JsonErrors;
using Stratis.Bitcoin.Utilities.ModelStateErrors;
-using ILogger = Microsoft.Extensions.Logging.ILogger;
using LogLevel = NLog.LogLevel;
using Target = NBitcoin.Target;
@@ -221,33 +220,34 @@ public IActionResult Status([FromQuery] bool publish)
/// The hash of the block to retrieve.
/// A flag that specifies whether to return the block header in the JSON format. Defaults to true. A value of false is currently not supported.
/// Json formatted . null if block not found. Returns formatted error if fails.
- /// Thrown if isJsonFormat = false"
- /// Thrown if hash is empty.
- /// Thrown if logger is not provided.
+ /// Returns the blockheader if found.
+ /// Null hash provided, BlockHeader does not exist or if isJsonFormat = false>/response>
/// Binary serialization is not supported with this method.
[Route("getblockheader")]
[HttpGet]
+ [ProducesResponseType((int)HttpStatusCode.OK)]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest)]
+ [ProducesResponseType((int)HttpStatusCode.NotFound)]
public IActionResult GetBlockHeader([FromQuery] string hash, bool isJsonFormat = true)
{
try
{
- Guard.NotEmpty(hash, nameof(hash));
+ if (string.IsNullOrEmpty(hash))
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", "Null hash provided.");
this.logger.LogDebug("GetBlockHeader {0}", hash);
+
if (!isJsonFormat)
{
this.logger.LogError("Binary serialization is not supported.");
- throw new NotImplementedException();
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", "Binary serialization is not supported.");
}
- BlockHeaderModel model = null;
BlockHeader blockHeader = this.chainIndexer?.GetHeader(uint256.Parse(hash))?.Header;
- if (blockHeader != null)
- {
- model = new BlockHeaderModel(blockHeader);
- }
+ if (blockHeader == null)
+ return this.NotFound($"Block header for '{hash}' not found");
- return this.Json(model);
+ return this.Json(new BlockHeaderModel(blockHeader));
}
catch (Exception e)
{
@@ -385,7 +385,7 @@ public IActionResult ValidateAddress([FromQuery] string address)
if (result.IsValid)
{
- var scriptPubKey = BitcoinAddress.Create(address, this.network).ScriptPubKey;
+ NBitcoin.Script scriptPubKey = BitcoinAddress.Create(address, this.network).ScriptPubKey;
result.ScriptPubKey = scriptPubKey.ToHex();
result.IsWitness = scriptPubKey.IsWitness(this.network);
}
@@ -453,7 +453,7 @@ public async Task GetTxOutAsync([FromQuery] string trxid, uint vo
/// The hex-encoded merkle proof.
[Route("gettxoutproof")]
[HttpGet]
- public async Task GetTxOutProofAsync([FromQuery] string[] txids, string blockhash = "")
+ public Task GetTxOutProofAsync([FromQuery] string[] txids, string blockhash = "")
{
List transactionIds = txids.Select(txString => uint256.Parse(txString)).ToList();
@@ -500,7 +500,7 @@ public async Task GetTxOutProofAsync([FromQuery] string[] txids,
var result = new MerkleBlock(block.Block, transactionIds.ToArray());
- return this.Json(result);
+ return Task.FromResult(this.Json(result));
}
///
@@ -529,6 +529,8 @@ public IActionResult Shutdown([FromBody] bool corsProtection = true)
/// Signals the node to rewind to the specified height.
/// This will be done via writing a flag to the .conf file so that on startup it be executed.
///
+ /// The rewind height.
+ /// A json text result indicating success or an indicating failure.
[Route("rewind")]
[HttpPut]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -697,7 +699,7 @@ public IActionResult GetAsyncLoops()
///
/// Schedules data folder storing chain state in the for deletion on the next graceful shutdown.
///
- ///
+ /// Returns an .
[HttpDelete]
[Route("datafolder/chain")]
public IActionResult DeleteChain()
@@ -717,7 +719,7 @@ public IActionResult DeleteChain()
/// Thrown if fullnode is not provided.
internal ChainedHeader GetTransactionBlock(uint256 trxid, ChainIndexer chain)
{
- Guard.NotNull(fullNode, nameof(fullNode));
+ Guard.NotNull(this.fullNode, nameof(this.fullNode));
ChainedHeader block = null;
uint256 blockid = this.blockStore?.GetBlockIdByTransactionId(trxid);
diff --git a/src/Stratis.Bitcoin.Features.Api/Startup.cs b/src/Stratis.Bitcoin.Features.Api/Startup.cs
index 7136012856..9a838a9635 100644
--- a/src/Stratis.Bitcoin.Features.Api/Startup.cs
+++ b/src/Stratis.Bitcoin.Features.Api/Startup.cs
@@ -9,7 +9,6 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
-using Newtonsoft.Json.Converters;
using Swashbuckle.AspNetCore.SwaggerGen;
using Swashbuckle.AspNetCore.SwaggerUI;
@@ -74,7 +73,9 @@ public void ConfigureServices(IServiceCollection services)
{
options.Filters.Add(typeof(LoggingActionFilter));
+#pragma warning disable ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices'
ServiceProvider serviceProvider = services.BuildServiceProvider();
+#pragma warning restore ASP0000 // Do not call 'IServiceCollection.BuildServiceProvider' in 'ConfigureServices'
var apiSettings = (ApiSettings)serviceProvider.GetRequiredService(typeof(ApiSettings));
if (apiSettings.KeepaliveTimer != null)
{
diff --git a/src/Stratis.Bitcoin.Features.Api/Stratis.Bitcoin.Features.Api.csproj b/src/Stratis.Bitcoin.Features.Api/Stratis.Bitcoin.Features.Api.csproj
index 9024d02ed5..cbb1b4420d 100644
--- a/src/Stratis.Bitcoin.Features.Api/Stratis.Bitcoin.Features.Api.csproj
+++ b/src/Stratis.Bitcoin.Features.Api/Stratis.Bitcoin.Features.Api.csproj
@@ -6,7 +6,7 @@
Stratis.Bitcoin.Features.Api
Library
Stratis.Features.Api
- 1.1.1.1
+ 1.2.0.0
False
library
diff --git a/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerOutpointsRepositoryTests.cs b/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerOutpointsRepositoryTests.cs
index 26e37e5e27..47939abe0d 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerOutpointsRepositoryTests.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerOutpointsRepositoryTests.cs
@@ -4,7 +4,6 @@
using System.Runtime.InteropServices;
using LiteDB;
using NBitcoin;
-using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.BlockStore.AddressIndexing;
using Xunit;
@@ -23,7 +22,7 @@ public AddressIndexerOutpointsRepositoryTests()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var db = new LiteDatabase(new ConnectionString() { Filename = this.RandomString(20) + ".litedb", Mode = fileMode });
- this.repository = new AddressIndexerOutpointsRepository(db, new ExtendedLoggerFactory(), this.maxItems);
+ this.repository = new AddressIndexerOutpointsRepository(db, this.maxItems);
}
[Fact]
diff --git a/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerTests.cs b/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerTests.cs
index 3cad2fc9f9..319db52591 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerTests.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore.Tests/AddressIndexerTests.cs
@@ -7,7 +7,6 @@
using NBitcoin;
using Stratis.Bitcoin.AsyncWork;
using Stratis.Bitcoin.Configuration;
-using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.Controllers.Models;
using Stratis.Bitcoin.Features.BlockStore.AddressIndexing;
@@ -52,7 +51,7 @@ public AddressIndexerTests()
var utxoIndexerMock = new Mock();
- this.addressIndexer = new AddressIndexer(storeSettings, dataFolder, new ExtendedLoggerFactory(), this.network, stats.Object,
+ this.addressIndexer = new AddressIndexer(storeSettings, dataFolder, this.network, stats.Object,
this.consensusManagerMock.Object, this.asyncProviderMock.Object, indexer, new DateTimeProvider(), utxoIndexerMock.Object);
this.genesisHeader = new ChainedHeader(this.network.GetGenesis().Header, this.network.GetGenesis().Header.GetHash(), 0);
@@ -182,7 +181,7 @@ public void OutPointCacheCanRetrieveExisting()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexerOutpointsRepository(database, new ExtendedLoggerFactory());
+ var cache = new AddressIndexerOutpointsRepository(database);
var outPoint = new OutPoint(uint256.Parse("0000af9ab2c8660481328d0444cf167dfd31f24ca2dbba8e5e963a2434cffa93"), 0);
@@ -205,7 +204,7 @@ public void OutPointCacheCannotRetrieveNonexistent()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexerOutpointsRepository(database, new ExtendedLoggerFactory());
+ var cache = new AddressIndexerOutpointsRepository(database);
Assert.False(cache.TryGetOutPointData(new OutPoint(uint256.Parse("0000af9ab2c8660481328d0444cf167dfd31f24ca2dbba8e5e963a2434cffa93"), 1), out OutPointData retrieved));
Assert.Null(retrieved);
@@ -220,7 +219,7 @@ public void OutPointCacheEvicts()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexerOutpointsRepository(database, new ExtendedLoggerFactory(), 2);
+ var cache = new AddressIndexerOutpointsRepository(database, 2);
Assert.Equal(0, cache.Count);
Assert.Equal(0, database.GetCollection(CollectionName).Count());
@@ -271,7 +270,7 @@ public void AddressCacheCanRetrieveExisting()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexRepository(database, new ExtendedLoggerFactory());
+ var cache = new AddressIndexRepository(database);
string address = "xyz";
var balanceChanges = new List();
@@ -300,7 +299,7 @@ public void AddressCacheRetrievesBlankRecordForNonexistent()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexRepository(database, new ExtendedLoggerFactory());
+ var cache = new AddressIndexRepository(database);
AddressIndexerData retrieved = cache.GetOrCreateAddress("xyz");
@@ -319,7 +318,7 @@ public void AddressCacheEvicts()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
var database = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- var cache = new AddressIndexRepository(database, new ExtendedLoggerFactory(), 4);
+ var cache = new AddressIndexRepository(database, 4);
// Recall, each index entry counts as 1 and each balance change associated with it is an additional 1.
Assert.Equal(0, database.GetCollection(CollectionName).Count());
diff --git a/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreControllerTests.cs b/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreControllerTests.cs
index 612f5cd55a..55730a8d4b 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreControllerTests.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreControllerTests.cs
@@ -68,9 +68,9 @@ public void Get_Block_When_Hash_Is_Not_Found_Should_Return_OkResult_WithMessage(
IActionResult response = controller.GetBlock(new SearchByHashRequest() { Hash = new uint256(1).ToString(), OutputJson = true });
- response.Should().BeOfType();
- var result = (OkObjectResult)response;
- result.StatusCode.Should().Be((int)HttpStatusCode.OK);
+ response.Should().BeOfType();
+ var result = (NotFoundObjectResult)response;
+ result.StatusCode.Should().Be((int)HttpStatusCode.NotFound);
result.Value.Should().Be("Block not found");
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreTests.cs b/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreTests.cs
index e34b8ff765..f48bdabdc7 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreTests.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore.Tests/BlockStoreTests.cs
@@ -333,6 +333,7 @@ public async Task ReorgedBlocksAreNotSavedAsync()
///
/// Tests reorgs inside the batch and inside the database at the same time.
///
+ /// The asynchronous task.
[Fact]
[Trait("Unstable", "True")]
public async Task ReorgedBlocksAreDeletedFromRepositoryIfReorgDetectedAsync()
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexRepository.cs b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexRepository.cs
index a202e8e4e6..7ba776766d 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexRepository.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexRepository.cs
@@ -3,6 +3,7 @@
using System.Linq;
using LiteDB;
using Microsoft.Extensions.Logging;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Controllers.Models;
using Stratis.Bitcoin.Utilities;
@@ -17,9 +18,9 @@ public class AddressIndexRepository : MemorySizeCache(DbAddressDataKey);
this.addressIndexerDataCollection.EnsureIndex("BalanceChangedHeightIndex", "$.BalanceChanges[*].BalanceChangedHeight", false);
}
@@ -80,10 +81,17 @@ public void SaveAllItems()
lock (this.LockObject)
{
CacheItem[] dirtyItems = this.Keys.Where(x => x.Dirty).ToArray();
- this.addressIndexerDataCollection.Upsert(dirtyItems.Select(x => x.Value));
+ this.logger.LogDebug("Saving {0} dirty items.", dirtyItems.Length);
+
+ List toUpsert = dirtyItems.Select(x => x.Value).ToList();
+
+ this.addressIndexerDataCollection.Upsert(toUpsert);
+
foreach (CacheItem dirtyItem in dirtyItems)
dirtyItem.Dirty = false;
+
+ this.logger.LogDebug("Saved dirty items.");
}
}
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexer.cs b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexer.cs
index 0faabfba2d..5bd1d73a1c 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexer.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexer.cs
@@ -40,6 +40,7 @@ public interface IAddressIndexer : IDisposable
/// Returns verbose balances data.
/// The set of addresses that will be queried.
+ /// See .
VerboseAddressBalancesResult GetAddressIndexerState(string[] addresses);
IFullNodeFeature InitializingFeature { set; }
@@ -82,7 +83,9 @@ public class AddressIndexer : IAddressIndexer
///
private const int DelayTimeMs = 2000;
- private const int CompactingThreshold = 50;
+ private int compactionThreshold;
+
+ private int compactionAmount => this.compactionThreshold / 2;
/// Max distance between consensus and indexer tip to consider indexer synced.
private const int ConsiderSyncedMaxDistance = 10;
@@ -103,9 +106,7 @@ public class AddressIndexer : IAddressIndexer
private readonly object lockObject;
private readonly CancellationTokenSource cancellation;
-
- private readonly ILoggerFactory loggerFactory;
-
+
private readonly ChainIndexer chainIndexer;
private readonly AverageCalculator averageTimePerBlock;
@@ -138,10 +139,10 @@ public class AddressIndexer : IAddressIndexer
/// We assume that nodes usually don't have view that is different from other nodes by that constant of blocks.
///
public const int SyncBuffer = 50;
-
+
public IFullNodeFeature InitializingFeature { get; set; }
- public AddressIndexer(StoreSettings storeSettings, DataFolder dataFolder, ILoggerFactory loggerFactory, Network network, INodeStats nodeStats,
+ public AddressIndexer(StoreSettings storeSettings, DataFolder dataFolder, Network network, INodeStats nodeStats,
IConsensusManager consensusManager, IAsyncProvider asyncProvider, ChainIndexer chainIndexer, IDateTimeProvider dateTimeProvider, IUtxoIndexer utxoIndexer)
{
this.storeSettings = storeSettings;
@@ -152,7 +153,6 @@ public AddressIndexer(StoreSettings storeSettings, DataFolder dataFolder, ILogge
this.asyncProvider = asyncProvider;
this.dateTimeProvider = dateTimeProvider;
this.utxoIndexer = utxoIndexer;
- this.loggerFactory = loggerFactory;
this.scriptAddressReader = new ScriptAddressReader();
this.lockObject = new object();
@@ -160,15 +160,18 @@ public AddressIndexer(StoreSettings storeSettings, DataFolder dataFolder, ILogge
this.lastFlushTime = this.dateTimeProvider.GetUtcNow();
this.cancellation = new CancellationTokenSource();
this.chainIndexer = chainIndexer;
- this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
+ this.logger = LogManager.GetCurrentClassLogger();
+ this.compactionThreshold = storeSettings.AddressIndexerCompactionThreshold;
this.averageTimePerBlock = new AverageCalculator(200);
int maxReorgLength = GetMaxReorgOrFallbackMaxReorg(this.network);
this.compactionTriggerDistance = maxReorgLength * 2 + SyncBuffer + 1000;
}
- /// Returns maxReorg of in case maxReorg is 0.
+ /// Gets the maxReorg of in case maxReorg is 0.
+ /// The network to get the value for.
+ /// Returns the maxReorg or value.
public static int GetMaxReorgOrFallbackMaxReorg(Network network)
{
int maxReorgLength = network.Consensus.MaxReorgLength == 0 ? FallBackMaxReorg : (int)network.Consensus.MaxReorgLength;
@@ -190,7 +193,7 @@ public void Initialize()
FileMode fileMode = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? FileMode.Exclusive : FileMode.Shared;
this.db = new LiteDatabase(new ConnectionString() { Filename = dbPath, Mode = fileMode });
- this.addressIndexRepository = new AddressIndexRepository(this.db, this.loggerFactory);
+ this.addressIndexRepository = new AddressIndexRepository(this.db);
this.logger.LogDebug("Address indexing is enabled.");
@@ -216,7 +219,7 @@ public void Initialize()
}
}
- this.outpointsRepository = new AddressIndexerOutpointsRepository(this.db, this.loggerFactory);
+ this.outpointsRepository = new AddressIndexerOutpointsRepository(this.db);
this.RewindAndSave(this.IndexerTip);
@@ -247,7 +250,10 @@ private async Task IndexAddressesContinuouslyAsync()
}
if (this.cancellation.IsCancellationRequested)
+ {
+ this.logger.LogDebug("Cancelled loop.");
break;
+ }
ChainedHeader nextHeader = this.consensusManager.Tip.GetAncestor(this.IndexerTip.Height + 1);
@@ -332,7 +338,7 @@ private async Task IndexAddressesContinuouslyAsync()
this.IndexerTip = nextHeader;
}
-
+
this.SaveAll();
}
@@ -369,7 +375,10 @@ private void SaveAll()
lock (this.lockObject)
{
+ this.logger.LogDebug("Saving addr indexer repo.");
this.addressIndexRepository.SaveAllItems();
+
+ this.logger.LogDebug("Saving outpoints repo.");
this.outpointsRepository.SaveAllItems();
AddressIndexerTipData tipData = this.tipDataStore.FindAll().FirstOrDefault();
@@ -380,6 +389,8 @@ private void SaveAll()
tipData.Height = this.IndexerTip.Height;
tipData.TipHashBytes = this.IndexerTip.HashBlock.ToBytes();
+ this.logger.LogDebug("Saving tip data.");
+
this.tipDataStore.Upsert(tipData);
this.lastSavedHeight = this.IndexerTip.Height;
}
@@ -390,7 +401,7 @@ private void SaveAll()
private void AddInlineStats(StringBuilder benchLog)
{
benchLog.AppendLine("AddressIndexer Height".PadRight(LoggingConfiguration.ColumnLength) + $": {this.IndexerTip.Height}".PadRight(9) +
- "AddressCache%: " + this.addressIndexRepository.GetLoadPercentage().ToString().PadRight(8) +
+ " AddressCache%: " + this.addressIndexRepository.GetLoadPercentage().ToString().PadRight(8) +
"OutPointCache%: " + this.outpointsRepository.GetLoadPercentage().ToString().PadRight(8) +
$"Ms/block: {Math.Round(this.averageTimePerBlock.Average, 2)}");
}
@@ -401,6 +412,8 @@ private void AddInlineStats(StringBuilder benchLog)
/// true if block was sucessfully processed.
private bool ProcessBlock(Block block, ChainedHeader header)
{
+ this.logger.LogTrace("Processing block " + header.ToString());
+
lock (this.lockObject)
{
// Record outpoints.
@@ -430,8 +443,8 @@ private bool ProcessBlock(Block block, ChainedHeader header)
// Process inputs.
var inputs = new List();
- // Collect all inputs excluding coinbases.
- foreach (TxInList inputsCollection in block.Transactions.Where(x => !x.IsCoinBase).Select(x => x.Inputs))
+ // Collect all inputs.
+ foreach (TxInList inputsCollection in block.Transactions.Select(x => x.Inputs))
inputs.AddRange(inputsCollection);
lock (this.lockObject)
@@ -442,6 +455,10 @@ private bool ProcessBlock(Block block, ChainedHeader header)
{
OutPoint consumedOutput = input.PrevOut;
+ // Ignore coinbase.
+ if (consumedOutput.Hash == uint256.Zero)
+ continue;
+
if (!this.outpointsRepository.TryGetOutPointData(consumedOutput, out OutPointData consumedOutputData))
{
this.logger.LogError("Missing outpoint data for {0}.", consumedOutput);
@@ -503,10 +520,11 @@ private bool ProcessBlock(Block block, ChainedHeader header)
}
// Remove outpoints that were consumed.
- foreach (OutPoint consumedOutPoint in inputs.Select(x => x.PrevOut))
+ foreach (OutPoint consumedOutPoint in inputs.Where(x => x.PrevOut.Hash != uint256.Zero).Select(x => x.PrevOut))
this.outpointsRepository.RemoveOutPointData(consumedOutPoint);
}
+ this.logger.LogTrace("Block processed.");
return true;
}
@@ -531,16 +549,17 @@ private void ProcessBalanceChangeLocked(int height, string address, Money amount
// Anything less than that should be compacted.
int heightThreshold = this.consensusManager.Tip.Height - this.compactionTriggerDistance;
- bool compact = (indexData.BalanceChanges.Count > CompactingThreshold) &&
- (indexData.BalanceChanges[1].BalanceChangedHeight < heightThreshold);
+ bool compact = (indexData.BalanceChanges.Count > this.compactionThreshold) && (indexData.BalanceChanges[1].BalanceChangedHeight < heightThreshold);
if (!compact)
{
+ this.addressIndexRepository.AddOrUpdate(indexData.Address, indexData, indexData.BalanceChanges.Count + 1);
+
this.logger.LogTrace("(-)[TOO_FEW_CHANGE_RECORDS]");
return;
}
- var compacted = new List(CompactingThreshold / 2)
+ var compacted = new List(this.compactionThreshold / 2)
{
new AddressBalanceChange()
{
@@ -550,9 +569,11 @@ private void ProcessBalanceChangeLocked(int height, string address, Money amount
}
};
- foreach (AddressBalanceChange change in indexData.BalanceChanges)
+ for (int i = 0; i < indexData.BalanceChanges.Count; i++)
{
- if (change.BalanceChangedHeight < heightThreshold)
+ AddressBalanceChange change = indexData.BalanceChanges[i];
+
+ if ((change.BalanceChangedHeight) < heightThreshold && i < this.compactionAmount)
{
this.logger.LogDebug("Balance change: {0} was selected for compaction. Compacted balance now: {1}.", change, compacted[0].Satoshi);
@@ -731,11 +752,15 @@ public LastBalanceDecreaseTransactionModel GetLastBalanceDecreaseTransaction(str
///
public void Dispose()
{
+ this.logger.LogDebug("Disposing.");
+
this.cancellation.Cancel();
this.indexingTask?.GetAwaiter().GetResult();
this.db?.Dispose();
+
+ this.logger.LogDebug("Disposed.");
}
}
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexerOutpointsRepository.cs b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexerOutpointsRepository.cs
index 73b7f93f31..852f486aed 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexerOutpointsRepository.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/AddressIndexing/AddressIndexerOutpointsRepository.cs
@@ -4,6 +4,7 @@
using LiteDB;
using Microsoft.Extensions.Logging;
using NBitcoin;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.BlockStore.AddressIndexing
@@ -27,9 +28,9 @@ public sealed class AddressIndexerOutpointsRepository : MemoryCache(DbOutputsDataKey);
this.addressIndexerRewindData = db.GetCollection(DbOutputsRewindDataKey);
this.maxCacheItems = maxItems;
@@ -92,6 +93,7 @@ public bool TryGetOutPointData(OutPoint outPoint, out OutPointData outPointData)
public void SaveAllItems()
{
+ this.logger.LogDebug("Saving all items.");
lock (this.LockObject)
{
CacheItem[] dirtyItems = this.Keys.Where(x => x.Dirty).ToArray();
@@ -99,7 +101,10 @@ public void SaveAllItems()
foreach (CacheItem dirtyItem in dirtyItems)
dirtyItem.Dirty = false;
+
+ this.logger.LogDebug("{0} items saved.", dirtyItems.Length);
}
+
}
/// Persists rewind data into the repository.
@@ -118,15 +123,9 @@ public void PurgeOldRewindData(int height)
{
lock (this.LockObject)
{
- var itemsToPurge = this.addressIndexerRewindData.Find(x => x.BlockHeight < height).ToArray();
-
- for (int i = 0; i < itemsToPurge.Count(); i++)
- {
- this.addressIndexerRewindData.Delete(itemsToPurge[i].BlockHash);
-
- if (i % 100 == 0)
- this.logger.LogInformation("Purging {0}/{1} rewind data items.", i, itemsToPurge.Count());
- }
+ this.logger.LogInformation("AddressIndexer: started purging rewind data items.");
+ int purgedCount = this.addressIndexerRewindData.Delete(x => x.BlockHeight < height);
+ this.logger.LogInformation("AddressIndexer: Purged {0} rewind data items.", purgedCount);
}
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreQueue.cs b/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreQueue.cs
index e9c40b12ef..ae245d367e 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreQueue.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreQueue.cs
@@ -54,6 +54,8 @@ public class BlockStoreQueue : IBlockStoreQueue
private readonly IInitialBlockDownloadState initialBlockDownloadState;
+#pragma warning disable SA1648
+
///
private readonly ILogger logger;
private readonly IBlockStoreQueueFlushCondition blockStoreQueueFlushCondition;
@@ -70,6 +72,8 @@ public class BlockStoreQueue : IBlockStoreQueue
///
private readonly IBlockRepository blockRepository;
+#pragma warning restore SA1648
+
private readonly IAsyncProvider asyncProvider;
/// Queue which contains blocks that should be saved to the database.
@@ -399,6 +403,7 @@ public List GetBlocks(List blockHashes)
}
/// Sets the internal store tip and exposes the store tip to other components through the chain state.
+ /// The new store tip to set.
private void SetStoreTip(ChainedHeader newTip)
{
this.storeTip = newTip;
@@ -408,6 +413,7 @@ private void SetStoreTip(ChainedHeader newTip)
///
/// Sets block store tip to the last block that exists both in the repository and in the .
///
+ /// The store tip set by this method.
private ChainedHeader RecoverStoreTip()
{
ChainedHeader blockStoreTip = this.chainIndexer.GetHeader(this.blockRepository.TipHashAndHeight.Hash);
@@ -496,6 +502,7 @@ public void AddToPending(ChainedHeaderBlock chainedHeaderBlock)
/// Dequeues the blocks continuously and saves them to the database when max batch size is reached or timer ran out.
///
/// Batch is always saved on shutdown.
+ /// The asynchronous task.
private async Task DequeueBlocksContinuouslyAsync()
{
Task dequeueTask = null;
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreSignaled.cs b/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreSignaled.cs
index 580e7f9f8e..039bd2c60b 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreSignaled.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/BlockStoreSignaled.cs
@@ -130,6 +130,7 @@ protected virtual void AddBlockToQueue(ChainedHeaderBlock blockPair, bool isIBD)
/// Continuously dequeues items from and sends
/// them to the peers after the timer runs out or if the last item is a tip.
///
+ /// The asynchronous task.
private async Task DequeueContinuouslyAsync()
{
var batch = new List();
@@ -186,6 +187,8 @@ private async Task DequeueContinuouslyAsync()
///
/// A method that relays blocks found in to connected peers on the network.
///
+ /// The batch containing the blocks to relay.
+ /// The asynchronous task.
///
///
/// The list contains hashes of blocks that were validated by the consensus rules.
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/Controllers/BlockStoreController.cs b/src/Stratis.Bitcoin.Features.BlockStore/Controllers/BlockStoreController.cs
index d7c5500ef9..a413d28f13 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/Controllers/BlockStoreController.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/Controllers/BlockStoreController.cs
@@ -122,6 +122,7 @@ public IActionResult GetAddressIndexerTip()
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
+ [ProducesResponseType((int)HttpStatusCode.NotFound)]
public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
{
if (!this.ModelState.IsValid)
@@ -134,14 +135,14 @@ public IActionResult GetBlock([FromQuery] SearchByHashRequest query)
ChainedHeader chainedHeader = this.chainIndexer.GetHeader(blockId);
if (chainedHeader == null)
- return this.Ok("Block not found");
+ return this.NotFound("Block not found");
Block block = chainedHeader.Block ?? this.blockStore.GetBlock(blockId);
// In rare occasions a block that is found in the
// indexer may not have been pushed to the store yet.
if (block == null)
- return this.Ok("Block not found");
+ return this.NotFound("Block not found");
if (!query.OutputJson)
{
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/IBlockRepository.cs b/src/Stratis.Bitcoin.Features.BlockStore/IBlockRepository.cs
index 03b8e126f1..37c50287dd 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/IBlockRepository.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/IBlockRepository.cs
@@ -34,13 +34,6 @@ public interface IBlockRepository : IBlockStore
/// Blocks to be inserted.
void PutBlocks(HashHeightPair newTip, List blocks);
- ///
- /// Get the blocks from the database by using block hashes.
- ///
- /// A list of unique block hashes.
- /// The blocks (or null if not found) in the same order as the hashes on input.
- List GetBlocks(List hashes);
-
///
/// Wipe out blocks and their transactions then replace with a new block.
///
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/Repositories/LevelDbBlockRepository.cs b/src/Stratis.Bitcoin.Features.BlockStore/Repositories/LevelDbBlockRepository.cs
index d6ec63f360..52dc357c29 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/Repositories/LevelDbBlockRepository.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/Repositories/LevelDbBlockRepository.cs
@@ -6,9 +6,10 @@
using System.Threading;
using DBreeze.Utils;
using LevelDB;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Persistence;
using Stratis.Bitcoin.Utilities;
@@ -85,7 +86,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (!this.TxIndex)
{
- this.logger.Trace("(-)[TX_INDEXING_DISABLED]:null");
+ this.logger.LogTrace("(-)[TX_INDEXING_DISABLED]:null");
return default(Transaction);
}
@@ -101,7 +102,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (transactionRow == null)
{
- this.logger.Trace("(-)[NO_BLOCK]:null");
+ this.logger.LogTrace("(-)[NO_BLOCK]:null");
return null;
}
@@ -122,7 +123,7 @@ public Transaction GetTransactionById(uint256 trxid)
{
if (!this.TxIndex)
{
- this.logger.Trace("(-)[TX_INDEXING_DISABLED]:null");
+ this.logger.LogTrace("(-)[TX_INDEXING_DISABLED]:null");
return null;
}
@@ -138,7 +139,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (alreadyFetched)
{
- this.logger.Debug("Duplicated transaction encountered. Tx id: '{0}'.", trxids[i]);
+ this.logger.LogDebug("Duplicated transaction encountered. Tx id: '{0}'.", trxids[i]);
txes[i] = txes.First(x => x.GetHash() == trxids[i]);
continue;
@@ -153,7 +154,7 @@ public Transaction GetTransactionById(uint256 trxid)
byte[] transactionRow = this.leveldb.Get(BlockRepositoryConstants.TransactionTableName, trxids[i].ToBytes());
if (transactionRow == null)
{
- this.logger.Trace("(-)[NO_TX_ROW]:null");
+ this.logger.LogTrace("(-)[NO_TX_ROW]:null");
return null;
}
@@ -161,7 +162,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (blockRow != null)
{
- this.logger.Trace("(-)[NO_BLOCK]:null");
+ this.logger.LogTrace("(-)[NO_BLOCK]:null");
return null;
}
@@ -182,7 +183,7 @@ public uint256 GetBlockIdByTransactionId(uint256 trxid)
if (!this.TxIndex)
{
- this.logger.Trace("(-)[NO_TXINDEX]:null");
+ this.logger.LogTrace("(-)[NO_TXINDEX]:null");
return default(uint256);
}
@@ -298,7 +299,7 @@ public void ReIndex()
warningMessage.AppendLine("".PadRight(133, '='));
warningMessage.AppendLine();
- this.logger.Info(warningMessage.ToString());
+ this.logger.LogInformation(warningMessage.ToString());
using (var batch = new WriteBatch())
{
var enumerator = this.leveldb.GetEnumerator();
@@ -315,7 +316,7 @@ public void ReIndex()
// inform the user about the ongoing operation
if (++rowCount % 1000 == 0)
{
- this.logger.Info("Reindex in process... {0}/{1} blocks processed.", rowCount, totalBlocksCount);
+ this.logger.LogInformation("Reindex in process... {0}/{1} blocks processed.", rowCount, totalBlocksCount);
}
}
}
@@ -323,7 +324,7 @@ public void ReIndex()
this.leveldb.Write(batch, new WriteOptions() { Sync = true });
}
- this.logger.Info("Reindex completed successfully.");
+ this.logger.LogInformation("Reindex completed successfully.");
}
else
{
@@ -498,13 +499,13 @@ public List GetBlocksFromHashes(List hashes)
{
results[key.Item1] = this.dBreezeSerializer.Deserialize(blockRow);
- this.logger.Debug("Block hash '{0}' loaded from the store.", key.Item1);
+ this.logger.LogDebug("Block hash '{0}' loaded from the store.", key.Item1);
}
else
{
results[key.Item1] = null;
- this.logger.Debug("Block hash '{0}' not found in the store.", key.Item1);
+ this.logger.LogDebug("Block hash '{0}' not found in the store.", key.Item1);
}
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/Repositories/RocksDbBlockRepository.cs b/src/Stratis.Bitcoin.Features.BlockStore/Repositories/RocksDbBlockRepository.cs
index d1d8b227b5..4b9fc03490 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/Repositories/RocksDbBlockRepository.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/Repositories/RocksDbBlockRepository.cs
@@ -5,10 +5,11 @@
using System.Text;
using System.Threading;
using DBreeze.Utils;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using RocksDbSharp;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Persistence;
using Stratis.Bitcoin.Utilities;
@@ -82,7 +83,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (!this.TxIndex)
{
- this.logger.Trace("(-)[TX_INDEXING_DISABLED]:null");
+ this.logger.LogTrace("(-)[TX_INDEXING_DISABLED]:null");
return default;
}
@@ -98,7 +99,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (transactionRow == null)
{
- this.logger.Trace("(-)[NO_BLOCK]:null");
+ this.logger.LogTrace("(-)[NO_BLOCK]:null");
return null;
}
@@ -119,7 +120,7 @@ public Transaction GetTransactionById(uint256 trxid)
{
if (!this.TxIndex)
{
- this.logger.Trace("(-)[TX_INDEXING_DISABLED]:null");
+ this.logger.LogTrace("(-)[TX_INDEXING_DISABLED]:null");
return null;
}
@@ -135,7 +136,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (alreadyFetched)
{
- this.logger.Debug("Duplicated transaction encountered. Tx id: '{0}'.", trxids[i]);
+ this.logger.LogDebug("Duplicated transaction encountered. Tx id: '{0}'.", trxids[i]);
txes[i] = txes.First(x => x.GetHash() == trxids[i]);
continue;
@@ -150,7 +151,7 @@ public Transaction GetTransactionById(uint256 trxid)
byte[] transactionRow = this.rocksDb.Get(BlockRepositoryConstants.TransactionTableName, trxids[i].ToBytes());
if (transactionRow == null)
{
- this.logger.Trace("(-)[NO_TX_ROW]:null");
+ this.logger.LogTrace("(-)[NO_TX_ROW]:null");
return null;
}
@@ -158,7 +159,7 @@ public Transaction GetTransactionById(uint256 trxid)
if (blockRow != null)
{
- this.logger.Trace("(-)[NO_BLOCK]:null");
+ this.logger.LogTrace("(-)[NO_BLOCK]:null");
return null;
}
@@ -179,7 +180,7 @@ public uint256 GetBlockIdByTransactionId(uint256 trxid)
if (!this.TxIndex)
{
- this.logger.Trace("(-)[NO_TXINDEX]:null");
+ this.logger.LogTrace("(-)[NO_TXINDEX]:null");
return default;
}
@@ -294,7 +295,7 @@ public void ReIndex()
warningMessage.AppendLine("".PadRight(133, '='));
warningMessage.AppendLine();
- this.logger.Info(warningMessage.ToString());
+ this.logger.LogInformation(warningMessage.ToString());
using (var batch = new WriteBatch())
{
var enumerator = this.rocksDb.NewIterator();
@@ -311,7 +312,7 @@ public void ReIndex()
// inform the user about the ongoing operation
if (++rowCount % 1000 == 0)
{
- this.logger.Info("Reindex in process... {0}/{1} blocks processed.", rowCount, totalBlocksCount);
+ this.logger.LogInformation("Reindex in process... {0}/{1} blocks processed.", rowCount, totalBlocksCount);
}
}
}
@@ -319,7 +320,7 @@ public void ReIndex()
this.rocksDb.Write(batch);
}
- this.logger.Info("Reindex completed successfully.");
+ this.logger.LogInformation("Reindex completed successfully.");
}
else
{
@@ -494,13 +495,13 @@ public List GetBlocksFromHashes(List hashes)
{
results[key.Item1] = this.dBreezeSerializer.Deserialize(blockRow);
- this.logger.Debug("Block hash '{0}' loaded from the store.", key.Item1);
+ this.logger.LogDebug("Block hash '{0}' loaded from the store.", key.Item1);
}
else
{
results[key.Item1] = null;
- this.logger.Debug("Block hash '{0}' not found in the store.", key.Item1);
+ this.logger.LogDebug("Block hash '{0}' not found in the store.", key.Item1);
}
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/StoreSettings.cs b/src/Stratis.Bitcoin.Features.BlockStore/StoreSettings.cs
index 4faf502a86..103428c0cc 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/StoreSettings.cs
+++ b/src/Stratis.Bitcoin.Features.BlockStore/StoreSettings.cs
@@ -35,6 +35,9 @@ public class StoreSettings
/// true to maintain a full addresses index.
public bool AddressIndex { get; set; }
+ /// How many balance changes per address should be accumulated before compaction happens. Compaction compacts half of the balance changes.
+ public int AddressIndexerCompactionThreshold { get; set; }
+
/// Calculates minimum amount of blocks we need to keep during pruning.
private int GetMinPruningAmount()
{
@@ -73,6 +76,7 @@ public StoreSettings(NodeSettings nodeSettings)
this.ReIndex = config.GetOrDefault("reindex", false, this.logger);
this.ReIndexChain = config.GetOrDefault("reindex-chain", false, this.logger);
this.AddressIndex = config.GetOrDefault("addressindex", false, this.logger);
+ this.AddressIndexerCompactionThreshold = config.GetOrDefault("compactionthreshold", 8000, this.logger);
if (this.PruningEnabled && this.TxIndex)
throw new ConfigurationException("Prune mode is incompatible with -txindex");
@@ -90,6 +94,7 @@ public static void PrintHelp(Network network)
builder.AppendLine($"-reindex=<0 or 1> Rebuild store with tx index from block data files on disk.");
builder.AppendLine($"-reindex-chain=<0 or 1> Rebuild the coindb from block data files on disk.");
builder.AppendLine($"-addressindex=<0 or 1> Enable to maintain a full address index.");
+ builder.AppendLine($"-compactionthreshold= Specify address indexer compaction threshold.");
NodeSettings.Default(network).Logger.LogInformation(builder.ToString());
}
diff --git a/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj b/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj
index 3cd4063a2f..3901f059f1 100644
--- a/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj
+++ b/src/Stratis.Bitcoin.Features.BlockStore/Stratis.Bitcoin.Features.BlockStore.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingControllerTest.cs b/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingControllerTest.cs
index 3bb7994cc2..8709fa2ab7 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingControllerTest.cs
+++ b/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingControllerTest.cs
@@ -810,6 +810,7 @@ public void GetColdStakingInfoOnlyConfirmAccountExistenceOnceCreated()
/// Adds a spendable cold staking transaction to a wallet.
///
/// Wallet to add the transaction to.
+ /// Set to true to output to the .
/// The spendable transaction that was added to the wallet.
private Transaction AddSpendableColdstakingTransactionToWallet(Wallet.Wallet wallet, bool script = false)
{
@@ -855,6 +856,7 @@ private Transaction AddSpendableColdstakingTransactionToWallet(Wallet.Wallet wal
/// Adds a spendable cold staking transaction to a normal account, as oppose to dedicated special account.
///
/// Wallet to add the transaction to.
+ /// Set to true to output to the .
/// The spendable transaction that was added to the wallet.
private Transaction AddSpendableColdstakingTransactionToNormalWallet(Wallet.Wallet wallet, bool script = false)
{
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingManagerTest.cs b/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingManagerTest.cs
index 94e40b8d9d..5054535c2c 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingManagerTest.cs
+++ b/src/Stratis.Bitcoin.Features.ColdStaking.Tests/ColdStakingManagerTest.cs
@@ -145,7 +145,7 @@ public void ProcessTransactionWithValidColdStakingSetupLoadsTransactionsIntoWall
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
Assert.Equal(2, transaction.Outputs.Count);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions);
TransactionData changeAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions.ElementAt(0);
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingManager.cs b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingManager.cs
index b82bbe1d67..567923967f 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingManager.cs
+++ b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingManager.cs
@@ -68,6 +68,7 @@ public class ColdStakingManager : WalletManager, IWalletManager
/// A reader for extracting an address from a .
/// The logger factory to use to create the custom logger.
/// Provider of time functions.
+ /// The wallet repository.
/// The broadcaster manager.
public ColdStakingManager(
Network network,
@@ -194,6 +195,7 @@ internal HdAccount GetColdStakingAccount(Wallet.Wallet wallet, bool isColdWallet
/// The name of the wallet where we wish to create the account.
/// Indicates whether we need the cold wallet account (versus the hot wallet account).
/// The wallet password which will be used to create the account.
+ /// The of the wallet account. Can be null for watch-only wallets.
/// The new or existing cold staking account.
internal HdAccount GetOrCreateColdStakingAccount(string walletName, bool isColdWalletAccount, string walletPassword, ExtPubKey extPubKey)
{
@@ -457,6 +459,14 @@ internal Money EstimateSetupTransactionFee(IWalletTransactionHandler walletTrans
/// Builds an unsigned transaction template for a cold staking withdrawal transaction.
/// This requires specialised logic due to the lack of a private key for the cold account.
///
+ /// The .
+ /// The receiving address.
+ /// The spending wallet name.
+ /// The spending account name.
+ /// The amount to spend.
+ /// The fee amount.
+ /// Set to true to subtract the from the .
+ /// See .
public BuildOfflineSignResponse BuildOfflineColdStakingWithdrawalRequest(IWalletTransactionHandler walletTransactionHandler, string receivingAddress,
string walletName, string accountName, Money amount, Money feeAmount, bool subtractFeeFromAmount)
{
@@ -552,6 +562,7 @@ private TransactionBuildContext GetOfflineWithdrawalBuildContext(string receivin
/// The wallet password.
/// The amount to remove from cold staking.
/// The fee to pay for cold staking transaction withdrawal.
+ /// Set to true to subtract the from the .
/// The for cold staking withdrawal.
/// Thrown if the receiving address is in a cold staking account in this wallet.
/// Thrown if the receiving address is invalid.
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingScriptTemplate.cs b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingScriptTemplate.cs
index 8f8d16b328..62570ef92c 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingScriptTemplate.cs
+++ b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingScriptTemplate.cs
@@ -100,9 +100,11 @@ public Script GenerateScriptPubKey(KeyId hotPubKeyHash, KeyId coldPubKeyHash)
return new Script(
// Duplicates the last stack entry resulting in:
// 0/1 .
+#pragma warning disable SA1114 // Parameter list must follow declaration
OP_DUP,
- // Replaces the last stack entry with its hash resulting in:
- // 0/1 .
+#pragma warning restore SA1114 // Parameter list must follow declaration
+ // Replaces the last stack entry with its hash resulting in:
+ // 0/1 .
OP_HASH160,
// Rotates the top 3 stack entries resulting in:
// 0/1.
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingWalletService.cs b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingWalletService.cs
index 7d8c51cc88..e2ae5ea5a5 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingWalletService.cs
+++ b/src/Stratis.Bitcoin.Features.ColdStaking/ColdStakingWalletService.cs
@@ -76,17 +76,17 @@ public override async Task OfflineSignRequest(Offli
$"Could not resolve address from UTXO's scriptPubKey '{scriptPubKey.ToHex()}'.");
}
- var accounts = this.walletManager.GetAccounts(request.WalletName);
- var addresses = accounts.SelectMany(hdAccount => hdAccount.GetCombinedAddresses());
+ IEnumerable accounts = this.walletManager.GetAccounts(request.WalletName);
+ IEnumerable addresses = accounts.SelectMany(hdAccount => hdAccount.GetCombinedAddresses());
HdAddress hdAddress = addresses.FirstOrDefault(a => a.Address == address || a.Bech32Address == address);
if (coldStakingWithdrawal && hdAddress == null)
{
var coldStakingManager = this.walletManager as ColdStakingManager;
- var wallet = coldStakingManager.GetWallet(request.WalletName);
- var coldAccount = coldStakingManager.GetColdStakingAccount(wallet, true);
- var coldAccountAddresses = coldAccount.GetCombinedAddresses();
+ Wallet.Wallet wallet = coldStakingManager.GetWallet(request.WalletName);
+ HdAccount coldAccount = coldStakingManager.GetColdStakingAccount(wallet, true);
+ IEnumerable coldAccountAddresses = coldAccount.GetCombinedAddresses();
hdAddress = coldAccountAddresses.FirstOrDefault(a => a.Address == address || a.Bech32Address == address);
}
diff --git a/src/Stratis.Bitcoin.Features.ColdStaking/Stratis.Bitcoin.Features.ColdStaking.csproj b/src/Stratis.Bitcoin.Features.ColdStaking/Stratis.Bitcoin.Features.ColdStaking.csproj
index b2c27d0c19..423c446b78 100644
--- a/src/Stratis.Bitcoin.Features.ColdStaking/Stratis.Bitcoin.Features.ColdStaking.csproj
+++ b/src/Stratis.Bitcoin.Features.ColdStaking/Stratis.Bitcoin.Features.ColdStaking.csproj
@@ -7,7 +7,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Consensus.Tests/CoinViews/CoinviewTests.cs b/src/Stratis.Bitcoin.Features.Consensus.Tests/CoinViews/CoinviewTests.cs
index d42f0204e1..8f882403a4 100644
--- a/src/Stratis.Bitcoin.Features.Consensus.Tests/CoinViews/CoinviewTests.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus.Tests/CoinViews/CoinviewTests.cs
@@ -176,7 +176,7 @@ private void SaveChanges(List unspent, int height)
this.cachedCoinView.SaveChanges(unspent, new HashHeightPair(previous), new HashHeightPair(current));
}
- private async Task ValidateCoinviewIntegrityAsync(List expectedAvailableOutPoints)
+ private Task ValidateCoinviewIntegrityAsync(List expectedAvailableOutPoints)
{
FetchCoinsResponse result = this.cachedCoinView.FetchCoins(expectedAvailableOutPoints.ToArray());
@@ -197,6 +197,8 @@ private async Task ValidateCoinviewIntegrityAsync(List expectedAvailab
{
Assert.Contains(referenceOutPoint, availableOutPoints);
}
+
+ return Task.CompletedTask;
}
private void Shuffle(IList list)
diff --git a/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/PosCoinViewRuleTest.cs b/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/PosCoinViewRuleTest.cs
index 4948d6612b..c01c9e6246 100644
--- a/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/PosCoinViewRuleTest.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/PosCoinViewRuleTest.cs
@@ -121,6 +121,7 @@ private async Task CreateConsensusManagerAsync(Dictionary
/// Tests whether an error is raised when a miner attempts to stake an output which he can't spend with his private key.
///
+ /// The asynchronous task.
///
/// Create a "previous transaction" with 2 outputs. The first output is sent to miner 2 and the second output is sent to miner 1.
/// Now miner 2 creates a proof of stake block with coinstake transaction which will have two inputs corresponding to both the
diff --git a/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/StraxCoinViewRuleTests.cs b/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/StraxCoinViewRuleTests.cs
index 669d820221..3ca882d4aa 100644
--- a/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/StraxCoinViewRuleTests.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus.Tests/Rules/CommonRules/StraxCoinViewRuleTests.cs
@@ -121,6 +121,7 @@ private async Task CreateConsensusManagerAsync(Dictionary
/// Tests whether an error is raised when a miner attempts to stake an output which he can't spend with his private key.
///
+ /// The asynchronous task.
///
/// Create a "previous transaction" with 2 outputs. The first output is sent to miner 2 and the second output is sent to miner 1.
/// Now miner 2 creates a proof of stake block with coinstake transaction which will have two inputs corresponding to both the
diff --git a/src/Stratis.Bitcoin.Features.Consensus.Tests/TestChainFactory.cs b/src/Stratis.Bitcoin.Features.Consensus.Tests/TestChainFactory.cs
index 59d4265931..a63f00becf 100644
--- a/src/Stratis.Bitcoin.Features.Consensus.Tests/TestChainFactory.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus.Tests/TestChainFactory.cs
@@ -97,6 +97,10 @@ internal class TestChainFactory
///
/// Creates test chain with a consensus loop.
///
+ /// The network context.
+ /// The data directory.
+ /// A mock .
+ /// The asynchronous task returning a .
public static async Task CreateAsync(Network network, string dataDir, Mock mockPeerAddressManager = null)
{
var testChainContext = new TestChainContext() { Network = network };
@@ -180,6 +184,11 @@ public static async Task> MineBlocksAsync(TestChainContext testChain
///
/// Mine new blocks in to the consensus database and the chain.
///
+ /// See .
+ /// The number of blocks to mine.
+ /// Script that explains what conditions must be met to claim ownership of the mined coins.
+ /// Indicates whether mutated blocks should be built.
+ /// A list of mined entries.
private static async Task> MineBlocksAsync(TestChainContext testChainContext, int count, Script receiver, bool mutateLastBlock)
{
var blockPolicyEstimator = new BlockPolicyEstimator(new MempoolSettings(testChainContext.NodeSettings), testChainContext.LoggerFactory, testChainContext.NodeSettings);
@@ -209,7 +218,7 @@ private static async Task MineBlockAsync(TestChainContext testCha
TryFindNonceForProofOfWork(testChainContext, newBlock);
- if (!getMutatedBlock) await ValidateBlock(testChainContext, newBlock);
+ if (!getMutatedBlock) await ValidateBlockAsync(testChainContext, newBlock);
else CheckBlockIsMutated(newBlock);
return newBlock;
@@ -219,7 +228,7 @@ private static BlockTemplate CreateBlockTemplate(TestChainContext testChainConte
TxMempool mempool, MempoolSchedulerLock mempoolLock)
{
PowBlockDefinition blockAssembler = new PowBlockDefinition(testChainContext.Consensus,
- testChainContext.DateTimeProvider, testChainContext.LoggerFactory as LoggerFactory, mempool, mempoolLock,
+ testChainContext.DateTimeProvider, testChainContext.LoggerFactory as ILoggerFactory, mempool, mempoolLock,
new MinerSettings(testChainContext.NodeSettings), testChainContext.Network, testChainContext.ConsensusRules, new NodeDeployments(testChainContext.Network, testChainContext.ChainIndexer));
BlockTemplate newBlock = blockAssembler.Build(testChainContext.ChainIndexer.Tip, scriptPubKey);
@@ -260,7 +269,7 @@ private static void CheckBlockIsMutated(BlockTemplate newBlock)
isMutated.Should().Be(true);
}
- private static async Task ValidateBlock(TestChainContext testChainContext, BlockTemplate newBlock)
+ private static async Task ValidateBlockAsync(TestChainContext testChainContext, BlockTemplate newBlock)
{
var res = await testChainContext.Consensus.BlockMinedAsync(newBlock.Block);
Assert.NotNull(res);
diff --git a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/CachedCoinView.cs b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/CachedCoinView.cs
index e9b6a95edc..dff4762122 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/CachedCoinView.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/CachedCoinView.cs
@@ -94,8 +94,10 @@ public long GetScriptSize
/// All access to this list has to be protected by .
private readonly Dictionary cachedRewindData;
+#pragma warning disable SA1648 // inheritdoc must be used with inheriting class
///
public ICoindb ICoindb => this.coindb;
+#pragma warning restore SA1648 // inheritdoc must be used with inheriting class
/// Storage of POS block information.
private readonly StakeChainStore stakeChainStore;
diff --git a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/ICoindb.cs b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/ICoindb.cs
index ed15db0d4f..c596f9c8db 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/ICoindb.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/ICoindb.cs
@@ -61,6 +61,7 @@ public interface ICoindb
/// Gets the rewind data by block height.
///
/// The height of the block.
+ /// See .
RewindData GetRewindData(int height);
/// Gets the minimum rewind height.
diff --git a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/LeveldbCoindb.cs b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/LeveldbCoindb.cs
index 17bc6a0a3f..0011906fe8 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/LeveldbCoindb.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/LeveldbCoindb.cs
@@ -3,9 +3,10 @@
using System.Linq;
using System.Text;
using LevelDB;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.Consensus.CoinViews
@@ -85,7 +86,7 @@ public void Initialize(ChainedHeader chainTip)
byte[] row2 = (current.Height > 1) ? this.leveldb.Get(new byte[] { rewindTable }.Concat(BitConverter.GetBytes(current.Height - 1)).ToArray()) : new byte[] { };
if (row2 != null)
{
- this.logger.Info("Fixing the coin db.");
+ this.logger.LogInformation("Fixing the coin db.");
var rows = new Dictionary();
@@ -133,12 +134,12 @@ public void Initialize(ChainedHeader chainTip)
if (this.GetTipHash() == null)
this.SetBlockHash(new HashHeightPair(genesis.GetHash(), 0));
- this.logger.Info("Coinview initialized with tip '{0}'.", this.persistedCoinviewTip);
+ this.logger.LogInformation("Coinview initialized with tip '{0}'.", this.persistedCoinviewTip);
}
private void EnsureCoinDatabaseIntegrity(ChainedHeader chainTip)
{
- this.logger.Info("Checking coin database integrity...");
+ this.logger.LogInformation("Checking coin database integrity...");
var heightToCheck = chainTip.Height;
@@ -157,13 +158,13 @@ private void EnsureCoinDatabaseIntegrity(ChainedHeader chainTip)
{
for (int height = heightToCheck - 1; height > chainTip.Height; height--)
{
- this.logger.Info($"Fixing coin database, deleting rewind data at height {height} above tip '{chainTip}'.");
+ this.logger.LogInformation($"Fixing coin database, deleting rewind data at height {height} above tip '{chainTip}'.");
RewindInternal(batch, height);
}
}
- this.logger.Info("Coin database integrity good.");
+ this.logger.LogInformation("Coin database integrity good.");
}
private void SetBlockHash(HashHeightPair nextBlockHash)
@@ -200,7 +201,7 @@ public FetchCoinsResponse FetchCoins(OutPoint[] utxos)
byte[] row = this.leveldb.Get(new byte[] { coinsTable }.Concat(outPoint.ToBytes()).ToArray());
Coins outputs = row != null ? this.dBreezeSerializer.Deserialize(row) : null;
- this.logger.Debug("Outputs for '{0}' were {1}.", outPoint, outputs == null ? "NOT loaded" : "loaded");
+ this.logger.LogDebug("Outputs for '{0}' were {1}.", outPoint, outputs == null ? "NOT loaded" : "loaded");
res.UnspentOutputs.Add(outPoint, new UnspentOutput(outPoint, outputs));
}
@@ -220,7 +221,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
HashHeightPair current = this.GetTipHash();
if (current != oldBlockHash)
{
- this.logger.Trace("(-)[BLOCKHASH_MISMATCH]");
+ this.logger.LogTrace("(-)[BLOCKHASH_MISMATCH]");
throw new InvalidOperationException("Invalid oldBlockHash");
}
@@ -231,7 +232,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
{
if (coin.Coins == null)
{
- this.logger.Debug("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.OutPoint);
+ this.logger.LogDebug("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.OutPoint);
batch.Delete(new byte[] { coinsTable }.Concat(coin.OutPoint.ToBytes()).ToArray());
}
else
@@ -245,7 +246,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
for (int i = 0; i < toInsert.Count; i++)
{
var coin = toInsert[i];
- this.logger.Debug("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.OutPoint, i, toInsert.Count);
+ this.logger.LogDebug("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.OutPoint, i, toInsert.Count);
batch.Put(new byte[] { coinsTable }.Concat(coin.OutPoint.ToBytes()).ToArray(), this.dBreezeSerializer.Serialize(coin.Coins));
}
@@ -256,7 +257,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
{
var nextRewindIndex = rewindData.PreviousBlockHash.Height + 1;
- this.logger.Debug("Rewind state #{0} created.", nextRewindIndex);
+ this.logger.LogDebug("Rewind state #{0} created.", nextRewindIndex);
batch.Put(new byte[] { rewindTable }.Concat(BitConverter.GetBytes(nextRewindIndex).Reverse()).ToArray(), this.dBreezeSerializer.Serialize(rewindData));
}
@@ -314,13 +315,13 @@ private HashHeightPair RewindInternal(WriteBatch batch, int height)
foreach (OutPoint outPoint in rewindData.OutputsToRemove)
{
- this.logger.Debug("Outputs of outpoint '{0}' will be removed.", outPoint);
+ this.logger.LogDebug("Outputs of outpoint '{0}' will be removed.", outPoint);
batch.Delete(new byte[] { coinsTable }.Concat(outPoint.ToBytes()).ToArray());
}
foreach (RewindDataOutput rewindDataOutput in rewindData.OutputsToRestore)
{
- this.logger.Debug("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint);
+ this.logger.LogDebug("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint);
batch.Put(new byte[] { coinsTable }.Concat(rewindDataOutput.OutPoint.ToBytes()).ToArray(), this.dBreezeSerializer.Serialize(rewindDataOutput.Coins));
}
@@ -366,7 +367,7 @@ public void GetStake(IEnumerable blocklist)
{
foreach (StakeItem blockStake in blocklist)
{
- this.logger.Trace("Loading POS block hash '{0}' from the database.", blockStake.BlockId);
+ this.logger.LogTrace("Loading POS block hash '{0}' from the database.", blockStake.BlockId);
byte[] stakeRow = this.leveldb.Get(new byte[] { stakeTable }.Concat(blockStake.BlockId.ToBytes(false)).ToArray());
if (stakeRow != null)
diff --git a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/RocksDbCoindb.cs b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/RocksDbCoindb.cs
index bd849584c4..4f715b61fb 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/RocksDbCoindb.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/CoinViews/Coindb/RocksDbCoindb.cs
@@ -2,10 +2,11 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using RocksDbSharp;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.Consensus.CoinViews
@@ -70,7 +71,7 @@ public void Initialize(ChainedHeader chainTip)
byte[] row2 = (current.Height > 1) ? this.rocksDb.Get(new byte[] { rewindTable }.Concat(BitConverter.GetBytes(current.Height - 1)).ToArray()) : new byte[] { };
if (row2 != null)
{
- this.logger.Info("Fixing the coin db.");
+ this.logger.LogInformation("Fixing the coin db.");
var rows = new Dictionary();
@@ -118,12 +119,12 @@ public void Initialize(ChainedHeader chainTip)
if (this.GetTipHash() == null)
this.SetBlockHash(new HashHeightPair(genesis.GetHash(), 0));
- this.logger.Info("Coinview initialized with tip '{0}'.", this.persistedCoinviewTip);
+ this.logger.LogInformation("Coinview initialized with tip '{0}'.", this.persistedCoinviewTip);
}
private void EnsureCoinDatabaseIntegrity(ChainedHeader chainTip)
{
- this.logger.Info("Checking coin database integrity...");
+ this.logger.LogInformation("Checking coin database integrity...");
var heightToCheck = chainTip.Height;
@@ -142,12 +143,12 @@ private void EnsureCoinDatabaseIntegrity(ChainedHeader chainTip)
{
for (int height = heightToCheck - 1; height > chainTip.Height; height--)
{
- this.logger.Info($"Fixing coin database, deleting rewind data at height {height} above tip '{chainTip}'.");
+ this.logger.LogInformation($"Fixing coin database, deleting rewind data at height {height} above tip '{chainTip}'.");
RewindInternal(batch, height);
}
}
- this.logger.Info("Coin database integrity good.");
+ this.logger.LogInformation("Coin database integrity good.");
}
private void SetBlockHash(HashHeightPair nextBlockHash)
@@ -184,7 +185,7 @@ public FetchCoinsResponse FetchCoins(OutPoint[] utxos)
byte[] row = this.rocksDb.Get(new byte[] { coinsTable }.Concat(outPoint.ToBytes()).ToArray());
Coins outputs = row != null ? this.dBreezeSerializer.Deserialize(row) : null;
- this.logger.Debug("Outputs for '{0}' were {1}.", outPoint, outputs == null ? "NOT loaded" : "loaded");
+ this.logger.LogDebug("Outputs for '{0}' were {1}.", outPoint, outputs == null ? "NOT loaded" : "loaded");
res.UnspentOutputs.Add(outPoint, new UnspentOutput(outPoint, outputs));
}
@@ -204,7 +205,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
HashHeightPair current = this.GetTipHash();
if (current != oldBlockHash)
{
- this.logger.Error("(-)[BLOCKHASH_MISMATCH]");
+ this.logger.LogError("(-)[BLOCKHASH_MISMATCH]");
throw new InvalidOperationException("Invalid oldBlockHash");
}
@@ -215,7 +216,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
{
if (coin.Coins == null)
{
- this.logger.Debug("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.OutPoint);
+ this.logger.LogDebug("Outputs of transaction ID '{0}' are prunable and will be removed from the database.", coin.OutPoint);
batch.Delete(new byte[] { coinsTable }.Concat(coin.OutPoint.ToBytes()).ToArray());
}
else
@@ -229,7 +230,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
for (int i = 0; i < toInsert.Count; i++)
{
var coin = toInsert[i];
- this.logger.Debug("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.OutPoint, i, toInsert.Count);
+ this.logger.LogDebug("Outputs of transaction ID '{0}' are NOT PRUNABLE and will be inserted into the database. {1}/{2}.", coin.OutPoint, i, toInsert.Count);
batch.Put(new byte[] { coinsTable }.Concat(coin.OutPoint.ToBytes()).ToArray(), this.dBreezeSerializer.Serialize(coin.Coins));
}
@@ -240,7 +241,7 @@ public void SaveChanges(IList unspentOutputs, HashHeightPair oldB
{
var nextRewindIndex = rewindData.PreviousBlockHash.Height + 1;
- this.logger.Debug("Rewind state #{0} created.", nextRewindIndex);
+ this.logger.LogDebug("Rewind state #{0} created.", nextRewindIndex);
batch.Put(new byte[] { rewindTable }.Concat(BitConverter.GetBytes(nextRewindIndex).Reverse()).ToArray(), this.dBreezeSerializer.Serialize(rewindData));
}
@@ -299,13 +300,13 @@ private HashHeightPair RewindInternal(WriteBatch batch, int height)
foreach (OutPoint outPoint in rewindData.OutputsToRemove)
{
- this.logger.Debug("Outputs of outpoint '{0}' will be removed.", outPoint);
+ this.logger.LogDebug("Outputs of outpoint '{0}' will be removed.", outPoint);
batch.Delete(new byte[] { coinsTable }.Concat(outPoint.ToBytes()).ToArray());
}
foreach (RewindDataOutput rewindDataOutput in rewindData.OutputsToRestore)
{
- this.logger.Debug("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint);
+ this.logger.LogDebug("Outputs of outpoint '{0}' will be restored.", rewindDataOutput.OutPoint);
batch.Put(new byte[] { coinsTable }.Concat(rewindDataOutput.OutPoint.ToBytes()).ToArray(), this.dBreezeSerializer.Serialize(rewindDataOutput.Coins));
}
@@ -351,7 +352,7 @@ public void GetStake(IEnumerable blocklist)
{
foreach (StakeItem blockStake in blocklist)
{
- this.logger.Debug("Loading POS block hash '{0}' from the database.", blockStake.BlockId);
+ this.logger.LogDebug("Loading POS block hash '{0}' from the database.", blockStake.BlockId);
byte[] stakeRow = this.rocksDb.Get(new byte[] { stakeTable }.Concat(blockStake.BlockId.ToBytes(false)).ToArray());
if (stakeRow != null)
diff --git a/src/Stratis.Bitcoin.Features.Consensus/ConsensusController.cs b/src/Stratis.Bitcoin.Features.Consensus/ConsensusController.cs
index c3ab53856f..3d8e54559f 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/ConsensusController.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/ConsensusController.cs
@@ -156,5 +156,33 @@ public IActionResult GetBlockHashAPI([FromQuery] int height)
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
+
+ ///
+ /// Returns the current tip of consensus.
+ ///
+ /// Json formatted hash and height of the block at the consensus tip. Returns formatted error if fails.
+ /// Returns the tip hash and height.
+ /// Unexpected exception occurred
+ [Route("api/[controller]/tip")]
+ [HttpGet]
+ [ProducesResponseType((int)HttpStatusCode.OK)]
+ [ProducesResponseType((int)HttpStatusCode.BadRequest)]
+ public IActionResult ConsensusTip()
+ {
+ try
+ {
+ if (this.ConsensusManager.Tip == null)
+ return this.Json("Consensus is not initialized.");
+
+ var tip = this.ConsensusManager.Tip;
+
+ return this.Json(new { TipHash = tip.HashBlock, TipHeight = tip.Height });
+ }
+ catch (Exception e)
+ {
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
+ return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
+ }
+ }
}
}
diff --git a/src/Stratis.Bitcoin.Features.Consensus/ProvenBlockHeaders/RocksDbProvenBlockHeaderRepository.cs b/src/Stratis.Bitcoin.Features.Consensus/ProvenBlockHeaders/RocksDbProvenBlockHeaderRepository.cs
index cab244d8fe..52803ffcc6 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/ProvenBlockHeaders/RocksDbProvenBlockHeaderRepository.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/ProvenBlockHeaders/RocksDbProvenBlockHeaderRepository.cs
@@ -3,10 +3,11 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using RocksDbSharp;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Interfaces;
using Stratis.Bitcoin.Persistence;
using Stratis.Bitcoin.Utilities;
@@ -116,7 +117,7 @@ public Task PutAsync(SortedDictionary headers, HashHeigh
Task task = Task.Run(() =>
{
- this.logger.Debug("({0}.Count():{1})", nameof(headers), headers.Count());
+ this.logger.LogDebug("({0}.Count():{1})", nameof(headers), headers.Count());
this.InsertHeaders(headers);
diff --git a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/CoinviewRule.cs b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/CoinviewRule.cs
index 9bbd88f2ba..05c8617d84 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/CoinviewRule.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/CoinviewRule.cs
@@ -148,6 +148,9 @@ protected virtual void AllowSpend(TxOut prevOut, Transaction spendingTx)
protected abstract Money GetTransactionFee(UnspentOutputSet view, Transaction tx);
/// Checks if transaction if final.
+ /// See .
+ /// See .
+ /// true if the transaction is final and false otherwise.
protected virtual bool IsTxFinal(Transaction transaction, RuleContext context)
{
return transaction.IsFinal(context.ValidationContext.ChainedHeaderToValidate);
@@ -197,6 +200,8 @@ protected void UpdateUTXOSet(RuleContext context, Transaction transaction)
/// Refer to .
///
///
+ /// See .
+ /// See .
public abstract void UpdateCoinView(RuleContext context, Transaction transaction);
///
@@ -230,11 +235,12 @@ public void CheckCoinbaseMaturity(UnspentOutput coins, int spendHeight)
}
///
- /// Network specific logic that checks the maturity of UTXO sets.
- ///
- /// Refer to .
- ///
+ /// Network-specific logic that checks the maturity of UTXOs.
///
+ /// UTXOs to check the maturity of.
+ /// Height at which coins are attempted to be spent.
+ /// Thrown if transaction tries to spend coinbase coins that are not mature.
+ /// Thrown if transaction tries to spend coinstake coins that are not mature.
public abstract void CheckMaturity(UnspentOutput coins, int spendHeight);
///
diff --git a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/HeaderVersionRule.cs b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/HeaderVersionRule.cs
index e8a63edec3..4917caa455 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/HeaderVersionRule.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/HeaderVersionRule.cs
@@ -15,6 +15,7 @@ public abstract class HeaderVersionRule : HeaderValidationConsensusRule
/// This method is currently used during block creation only. Different nodes may not implement
/// BIP9, or may disagree about what the current valid set of deployments are. It is therefore not strictly
/// possible to validate a block version number in anything more than general terms.
+ /// The block version.
public int ComputeBlockVersion(ChainedHeader prevChainedHeader)
{
uint version = ThresholdConditionCache.VersionbitsTopBits;
diff --git a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/SetActivationDeploymentsPartialValidationRule.cs b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/SetActivationDeploymentsPartialValidationRule.cs
index 8d5f9640c5..832a00b189 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/SetActivationDeploymentsPartialValidationRule.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/SetActivationDeploymentsPartialValidationRule.cs
@@ -17,7 +17,8 @@ public override Task RunAsync(RuleContext context)
}
}
- //TODO merge those 2 classes into 1 after activation
+ // TODO: Merge these 2 classes into one after activation.
+
/// Set the property that defines what deployments have been activated.
public class SetActivationDeploymentsFullValidationRule : FullValidationConsensusRule
{
diff --git a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/WitnessCommitmentsRule.cs b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/WitnessCommitmentsRule.cs
index 1294634b68..d7c0f59857 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/WitnessCommitmentsRule.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/Rules/CommonRules/WitnessCommitmentsRule.cs
@@ -27,6 +27,9 @@ public override Task RunAsync(RuleContext context)
///
/// Validation of the witness commitment if its found.
///
+ /// The including the block to validate.
+ /// The nwetwork to validate the commitment for.
+ /// The asynchronous task.
public Task ValidateWitnessCommitment(RuleContext context, Network network)
{
if (context.SkipValidation)
@@ -114,6 +117,7 @@ private bool EqualsArray(byte[] a, byte[] b, int length)
///
/// Gets commitment in the last coinbase transaction output with SegWit flag.
///
+ /// The network context.
/// Block which coinbase transaction's outputs will be checked for SegWit flags.
///
/// null if no SegWit flags were found.
@@ -154,6 +158,8 @@ public static Script GetWitnessCommitment(Network network, Block block)
///
/// Clear all witness commitments from the block.
///
+ /// The network context.
+ /// The block to clear commitments from.
public static void ClearWitnessCommitment(Network network, Block block)
{
if (network.Consensus.IsProofOfStake && network.Consensus.PosEmptyCoinbase)
@@ -185,6 +191,8 @@ public static void ClearWitnessCommitment(Network network, Block block)
///
/// Create a witness commitment based from the given block.
///
+ /// The network context.
+ /// The block to create commitments in.
public static void CreateWitnessCommitment(Network network, Block block)
{
var wtxidCoinbase = new byte[32]; // The wtxid of the coinbase transaction is defined as to be 0x0000....0000.
diff --git a/src/Stratis.Bitcoin.Features.Consensus/StakeValidator.cs b/src/Stratis.Bitcoin.Features.Consensus/StakeValidator.cs
index 5ac3672441..ea196cd9ab 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/StakeValidator.cs
+++ b/src/Stratis.Bitcoin.Features.Consensus/StakeValidator.cs
@@ -49,7 +49,8 @@ public class StakeValidator : IStakeValidator
/// When checking the POS block signature this determines the maximum push data (public key) size following the OP_RETURN in the nonspendable output.
private const int MaxPushDataSize = 40;
- // TODO: move this to IConsensus
+ // TODO: Move this to IConsensus.
+
/// Time interval in minutes that is used in the retarget calculation.
private const uint RetargetIntervalMinutes = 16;
@@ -65,6 +66,9 @@ public class StakeValidator : IStakeValidator
/// Consensus' view of UTXO set.
private readonly ICoinView coinView;
+
+#pragma warning disable SA1648 // inheritdoc must be used with inheriting class
+
///
private readonly Network network;
@@ -83,6 +87,8 @@ public StakeValidator(Network network, IStakeChain stakeChain, ChainIndexer chai
this.network = network;
}
+#pragma warning restore SA1648 // inheritdoc must be used with inheriting class
+
///
public ChainedHeader GetLastPowPosChainedBlock(IStakeChain stakeChain, ChainedHeader startChainedHeader, bool proofOfStake)
{
diff --git a/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj b/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj
index 67c52f6438..ed474bb294 100644
--- a/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj
+++ b/src/Stratis.Bitcoin.Features.Consensus/Stratis.Bitcoin.Features.Consensus.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Dns/DnsFeature.cs b/src/Stratis.Bitcoin.Features.Dns/DnsFeature.cs
index 0a4efff82c..e34509213c 100644
--- a/src/Stratis.Bitcoin.Features.Dns/DnsFeature.cs
+++ b/src/Stratis.Bitcoin.Features.Dns/DnsFeature.cs
@@ -132,6 +132,7 @@ public DnsFeature(IDnsServer dnsServer, IWhitelistManager whitelistManager, ILog
///
/// Initializes the DNS feature.
///
+ /// The asynchronous task.
public override Task InitializeAsync()
{
// Create long running task for DNS service.
diff --git a/src/Stratis.Bitcoin.Features.Dns/DnsSeedServer.cs b/src/Stratis.Bitcoin.Features.Dns/DnsSeedServer.cs
index 3954a58a60..a94ac41593 100644
--- a/src/Stratis.Bitcoin.Features.Dns/DnsSeedServer.cs
+++ b/src/Stratis.Bitcoin.Features.Dns/DnsSeedServer.cs
@@ -119,8 +119,10 @@ public class DnsSeedServer : IDnsServer
/// The UDP client to use to receive DNS requests and send DNS responses.
/// The initial DNS masterfile.
/// The async loop factory.
+ /// The .
/// The logger factory.
/// The provider.
+ /// The .
/// The data folders of the system.
public DnsSeedServer(IUdpClient client, IMasterFile masterFile, IAsyncProvider asyncProvider, INodeLifetime nodeLifetime, ILoggerFactory loggerFactory, IDateTimeProvider dateTimeProvider, DnsSettings dnsSettings, DataFolder dataFolders)
{
@@ -362,6 +364,7 @@ private IResponse Resolve(Request request)
/// Handles a DNS request received by the UDP client.
///
/// The DNS request received from the UDP client.
+ /// The asynchronous task.
private async Task HandleRequestAsync(Tuple udpRequest)
{
Request request = null;
@@ -430,7 +433,7 @@ private async Task HandleRequestAsync(Tuple udpRequest)
///
/// Seeds the given masterfile with the SOA and NS DNS records with the DNS specific settings.
///
- ///
+ /// The .
private void SeedMasterFile(IMasterFile masterFile)
{
this.logger.LogInformation("Seeding DNS masterfile with SOA and NS resource records: Host = {0}, Nameserver = {1}, Mailbox = {2}", this.dnsSettings.DnsHostName, this.dnsSettings.DnsNameServer, this.dnsSettings.DnsMailBox);
@@ -441,7 +444,7 @@ private void SeedMasterFile(IMasterFile masterFile)
///
/// Gets the peer count of IP v4 and v6 addresses in the DNS masterfile.
///
- ///
+ /// The peer count.
private int GetPeerCount()
{
int count = this.MasterFile.Get(new Question(new Domain(this.dnsSettings.DnsHostName), RecordType.A)).Count;
diff --git a/src/Stratis.Bitcoin.Features.Dns/Stratis.Bitcoin.Features.Dns.csproj b/src/Stratis.Bitcoin.Features.Dns/Stratis.Bitcoin.Features.Dns.csproj
index 746bf4f8bc..5ad3c3077f 100644
--- a/src/Stratis.Bitcoin.Features.Dns/Stratis.Bitcoin.Features.Dns.csproj
+++ b/src/Stratis.Bitcoin.Features.Dns/Stratis.Bitcoin.Features.Dns.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/CoinGeckoClient.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/CoinGeckoClient.cs
index 9f1ff07c08..788cf08539 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/CoinGeckoClient.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/CoinGeckoClient.cs
@@ -6,8 +6,14 @@
namespace Stratis.Bitcoin.Features.ExternalApi.ApiClients
{
+ ///
+ /// Retrieves price data from Coin Gecko.
+ ///
public class CoinGeckoClient : IDisposable
{
+ ///
+ /// The user-agent used by this class when retrieving price data.
+ ///
public const string DummyUserAgent = "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36";
private readonly ExternalApiSettings externalApiSettings;
@@ -16,6 +22,10 @@ public class CoinGeckoClient : IDisposable
private decimal stratisPrice = -1;
private decimal ethereumPrice = -1;
+ ///
+ /// Class constructor.
+ ///
+ /// The .
public CoinGeckoClient(ExternalApiSettings externalApiSettings)
{
this.externalApiSettings = externalApiSettings;
@@ -23,16 +33,28 @@ public CoinGeckoClient(ExternalApiSettings externalApiSettings)
this.client = new HttpClient();
}
+ ///
+ /// Gets the most recently retrieved Stratis price.
+ ///
+ /// The Stratis price.
public decimal GetStratisPrice()
{
return this.stratisPrice;
}
+ ///
+ /// Gets the most recently retrieved Ethereum price.
+ ///
+ /// The Ethereum price.
public decimal GetEthereumPrice()
{
return this.ethereumPrice;
}
+ ///
+ /// Retrieves price data for Stratis and Ethereum from Coin Gecko.
+ ///
+ /// The .
public async Task PriceDataRetrievalAsync()
{
var targetUri = new Uri(this.externalApiSettings.PriceUrl);
@@ -55,6 +77,9 @@ public async Task PriceDataRetrievalAsync()
return response;
}
+ ///
+ /// Disposes instances of this class.
+ ///
public void Dispose()
{
this.client?.Dispose();
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/EtherscanClient.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/EtherscanClient.cs
index c9f52b5a0d..3213b10410 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/EtherscanClient.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ApiClients/EtherscanClient.cs
@@ -6,6 +6,9 @@
namespace Stratis.Bitcoin.Features.ExternalApi.ApiClients
{
+ ///
+ /// Retrieves gas prices from Etherscan.
+ ///
public class EtherscanClient : IDisposable
{
private readonly ExternalApiSettings externalApiSettings;
@@ -18,6 +21,10 @@ public class EtherscanClient : IDisposable
private bool sampled = false;
private int samplePointer = 0;
+ ///
+ /// The class constructor.
+ ///
+ /// The .
public EtherscanClient(ExternalApiSettings externalApiSettings)
{
this.externalApiSettings = externalApiSettings;
@@ -58,7 +65,11 @@ public int GetGasPrice()
return (int)Math.Ceiling((((totalFast * fastWeighting) + (totalProposed * proposedWeighting) + (totalSafe * safeWeighting)) / this.fastSamples.Length));
}
- public async Task GasOracle(bool recordSamples)
+ ///
+ /// Samples the gas price from Etherscan.
+ ///
+ /// The .
+ public async Task GasOracleAsync()
{
string content = await this.client.GetStringAsync(this.externalApiSettings.EtherscanGasOracleUrl).ConfigureAwait(false);
@@ -85,23 +96,23 @@ public async Task GasOracle(bool recordSamples)
return response;
}
- if (recordSamples)
- {
- this.fastSamples[this.samplePointer] = response.result.FastGasPrice;
- this.proposeSamples[this.samplePointer] = response.result.ProposeGasPrice;
- this.safeSamples[this.samplePointer] = response.result.SafeGasPrice;
+ this.fastSamples[this.samplePointer] = response.result.FastGasPrice;
+ this.proposeSamples[this.samplePointer] = response.result.ProposeGasPrice;
+ this.safeSamples[this.samplePointer] = response.result.SafeGasPrice;
- this.samplePointer++;
+ this.samplePointer++;
- if (this.samplePointer >= this.fastSamples.Length)
- {
- this.samplePointer = 0;
- }
+ if (this.samplePointer >= this.fastSamples.Length)
+ {
+ this.samplePointer = 0;
}
return response;
}
+ ///
+ /// Disposes instances of this class.
+ ///
public void Dispose()
{
this.client?.Dispose();
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/Controllers/ExternalApiController.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/Controllers/ExternalApiController.cs
index 7682b6edeb..8c1d776a9c 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/Controllers/ExternalApiController.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/Controllers/ExternalApiController.cs
@@ -1,32 +1,63 @@
using System;
using System.Net;
using Microsoft.AspNetCore.Mvc;
-using NLog;
+using Microsoft.Extensions.Logging;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.ExternalApi;
using Stratis.Bitcoin.Utilities.JsonErrors;
namespace Stratis.Features.ExternalApi.Controllers
{
+ ///
+ /// Controller for the External Api.
+ ///
[ApiVersion("1")]
[Route("api/[controller]")]
public class ExternalApiController : Controller
{
+ ///
+ /// Name of api method which estimates the total gas a conversion will require.
+ ///
public const string EstimateConversionGasEndpoint = "estimateconversiongas";
+
+ ///
+ /// Name of api method which estimates the conversion fee (in STRAX).
+ ///
public const string EstimateConversionFeeEndpoint = "estimateconversionfee";
+
+ ///
+ /// Name of api method which estimates a recommended gas price based on historical measured samples.
+ ///
public const string GasPriceEndpoint = "gasprice";
+
+ ///
+ /// Name of api method which returns the most recently retrieved Stratis price.
+ ///
public const string StratisPriceEndpoint = "stratisprice";
+
+ ///
+ /// Name of api method which returns the most recently retrieved Ethereum price.
+ ///
public const string EthereumPriceEndpoint = "ethereumprice";
private readonly IExternalApiPoller externalApiPoller;
private readonly ILogger logger;
+ ///
+ /// The class constructor.
+ ///
+ /// The .
public ExternalApiController(IExternalApiPoller externalApiPoller)
{
this.externalApiPoller = externalApiPoller;
this.logger = LogManager.GetCurrentClassLogger();
}
+ ///
+ /// Estimates the total gas a conversion will require.
+ ///
+ /// The total gas a conversion will require or an .
[Route(EstimateConversionGasEndpoint)]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -40,11 +71,15 @@ public IActionResult EstimateConversionGas()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
+ ///
+ /// Estimates the conversion fee (in STRAX).
+ ///
+ /// The conversion fee or and .
[Route(EstimateConversionFeeEndpoint)]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -58,11 +93,15 @@ public IActionResult EstimateConversionFee()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
+ ///
+ /// Estimates a recommended gas price based on historical samples.
+ ///
+ /// The recommended gas price or an .
[Route(GasPriceEndpoint)]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -76,11 +115,15 @@ public IActionResult GasPrice()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
+ ///
+ /// Returns the most recently retrieved Stratis price.
+ ///
+ /// The most recently retrieved Stratis price or an .
[Route(StratisPriceEndpoint)]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -94,11 +137,15 @@ public IActionResult StratisPrice()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
+ ///
+ /// Returns the most recently retrieved Ethereum price.
+ ///
+ /// The most recently retrieved Ethereum price or an .
[Route(EthereumPriceEndpoint)]
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -112,7 +159,7 @@ public IActionResult EthereumPrice()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiClient.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiClient.cs
index 0ed60eb4eb..11691ebe43 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiClient.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiClient.cs
@@ -13,12 +13,22 @@ namespace Stratis.Bitcoin.Features.ExternalApi
///
public interface IExternalApiClient
{
+ ///
+ /// Estimates the conversion fee (in STRAX).
+ ///
+ /// .
+ /// The conversion fee.
Task EstimateConversionTransactionFeeAsync(CancellationToken cancellation = default);
}
///
public sealed class ExternalApiClient : RestApiClientBase, IExternalApiClient
{
+ ///
+ /// The class constructor.
+ ///
+ /// The .
+ /// The .
public ExternalApiClient(ICounterChainSettings counterChainSettings, IHttpClientFactory httpClientFactory)
: base(httpClientFactory, counterChainSettings.CounterChainApiPort, "ExternalApi", $"http://{counterChainSettings.CounterChainApiHost}")
{
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiFeature.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiFeature.cs
index d976b50157..dc253247d0 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiFeature.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiFeature.cs
@@ -6,15 +6,26 @@
namespace Stratis.Bitcoin.Features.ExternalApi
{
+ ///
+ /// The External API Feature.
+ ///
public sealed class ExternalApiFeature : FullNodeFeature
{
private readonly IExternalApiPoller externalApiPoller;
+ ///
+ /// The class constructor.
+ ///
+ /// The .
public ExternalApiFeature(IExternalApiPoller externalApiPoller)
{
this.externalApiPoller = externalApiPoller;
}
+ ///
+ /// Initializes the instance.
+ ///
+ /// The asynchronous task.
public override Task InitializeAsync()
{
this.externalApiPoller?.Initialize();
@@ -22,14 +33,25 @@ public override Task InitializeAsync()
return Task.CompletedTask;
}
+ ///
+ /// Disposes the instance.
+ ///
public override void Dispose()
{
this.externalApiPoller?.Dispose();
}
}
+ ///
+ /// extensions.
+ ///
public static partial class IFullNodeBuilderExtensions
{
+ ///
+ /// Add the External Api feature to the node.
+ ///
+ /// Implicitly passed .
+ /// The .
public static IFullNodeBuilder AddExternalApi(this IFullNodeBuilder fullNodeBuilder)
{
LoggingConfiguration.RegisterFeatureNamespace("externalapi");
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiPoller.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiPoller.cs
index 60bed7e0cb..0493667fc8 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiPoller.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiPoller.cs
@@ -9,26 +9,63 @@
namespace Stratis.Bitcoin.Features.ExternalApi
{
+ ///
+ /// External API poller.
+ ///
public interface IExternalApiPoller : IDisposable
{
+ ///
+ /// Initialize the instance.
+ ///
void Initialize();
+ ///
+ /// Gets the Stratis price.
+ ///
+ /// The Stratis price.
decimal GetStratisPrice();
+ ///
+ /// Gets the Ethereum price.
+ ///
+ /// The Ethereum price.
decimal GetEthereumPrice();
+ ///
+ /// Gets the gas price.
+ ///
+ /// The gas price.
int GetGasPrice();
+ /// Estimates the total conversion gas costs.
+ /// The estimated total amount of gas a conversion transaction will require.
+ /// The decimal type is acceptable here because it supports sufficiently large numbers for most conceivable gas calculations.
decimal EstimateConversionTransactionGas();
+ ///
+ /// Estimates the conversion transaction fee.
+ ///
+ /// The estimated conversion transaction fee, converted from the USD total to the equivalent STRAX amount.
decimal EstimateConversionTransactionFee();
}
+ ///
public class ExternalApiPoller : IExternalApiPoller
{
+ ///
+ /// The quorum size.
+ ///
// TODO: This should be linked to the setting in the interop feature
public const int QuorumSize = 6;
+
+ ///
+ /// One Ether.
+ ///
public const decimal OneEther = 1_000_000_000_000_000_000;
+
+ ///
+ /// One Gwei.
+ ///
public const decimal OneGwei = 1_000_000_000;
private readonly IAsyncProvider asyncProvider;
@@ -41,6 +78,13 @@ public class ExternalApiPoller : IExternalApiPoller
private IAsyncLoop gasPriceLoop;
private IAsyncLoop priceLoop;
+ ///
+ /// The instance constructor.
+ ///
+ /// The .
+ /// The .
+ /// The .
+ /// The .
public ExternalApiPoller(NodeSettings nodeSettings,
IAsyncProvider asyncProvider,
INodeLifetime nodeLifetime,
@@ -54,6 +98,9 @@ public ExternalApiPoller(NodeSettings nodeSettings,
this.coinGeckoClient = new CoinGeckoClient(this.externalApiSettings);
}
+ ///
+ /// Inializes the instance.
+ ///
public void Initialize()
{
this.logger.LogInformation($"External API feature enabled, initializing periodic loops.");
@@ -68,7 +115,7 @@ public void Initialize()
try
{
- await this.etherscanClient.GasOracle(true).ConfigureAwait(false);
+ await this.etherscanClient.GasOracleAsync().ConfigureAwait(false);
}
catch (HttpRequestException e2) when (e2.InnerException is SocketException socketException && socketException.ErrorCode == 11001)
{
@@ -115,23 +162,25 @@ public void Initialize()
}
}
+ ///
public decimal GetStratisPrice()
{
return this.coinGeckoClient.GetStratisPrice();
}
+ ///
public decimal GetEthereumPrice()
{
return this.coinGeckoClient.GetEthereumPrice();
}
+ ///
public int GetGasPrice()
{
return this.etherscanClient.GetGasPrice();
}
- /// The decimal type is acceptable here because it supports sufficiently large numbers for most conceivable gas calculations.
- /// The estimated total amount of gas a conversion transaction will require.
+ ///
public decimal EstimateConversionTransactionGas()
{
// The cost of submitting a multisig ERC20 transfer to the multisig contract.
@@ -152,7 +201,7 @@ public decimal EstimateConversionTransactionGas()
return totalGas * gasPrice * OneGwei;
}
- /// The estimated conversion transaction fee, converted from the USD total to the equivalent STRAX amount.
+ ///
public decimal EstimateConversionTransactionFee()
{
// The approximate USD fee that will be applied to conversion transactions, over and above the computed gas cost.
@@ -173,6 +222,7 @@ public decimal EstimateConversionTransactionFee()
return (overallGasUsd / stratisPriceUsd) + (ConversionTransactionFee / stratisPriceUsd);
}
+ ///
public void Dispose()
{
this.gasPriceLoop?.Dispose();
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiSettings.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiSettings.cs
index f488e3ef41..5727ad43c4 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiSettings.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/ExternalApiSettings.cs
@@ -2,28 +2,65 @@
namespace Stratis.Bitcoin.Features.ExternalApi
{
+ ///
+ /// External Api Settings.
+ ///
public class ExternalApiSettings
{
+ ///
+ /// The key for the Etherscan api key.
+ ///
public const string EtherscanApiKeyKey = "etherscanapikey";
+ ///
+ /// The Etherscan gas oracle key.
+ ///
public const string EtherscanGasOracleUrlKey = "etherscangasoracle";
+ ///
+ /// The Ethereum gas price tracking key.
+ ///
public const string EthereumGasPriceTrackingKey = "ethereumgaspricetracking";
+ ///
+ /// The Ethereum price url key.
+ ///
public const string PriceUrlKey = "ethereumpriceurl";
+ ///
+ /// The key for a flag indicating whether price tracking is enabled.
+ ///
public const string PriceTrackingKey = "pricetracking";
+ ///
+ /// The Etherscan api key.
+ ///
public string EtherscanApiKey { get; set; }
+ ///
+ /// The Etherscan gas oracle url and key.
+ ///
public string EtherscanGasOracleUrl { get; set; }
+ ///
+ /// Indicates whether Ethereum gas price tracking is enabled.
+ ///
public bool EthereumGasPriceTracking { get; set; }
+ ///
+ /// Url for retrieving Stratis and Ethereum prices.
+ ///
public string PriceUrl { get; set; }
+ ///
+ /// A flag indicating whether price tracking is enabled.
+ ///
public bool PriceTracking { get; set; }
+ ///
+ /// The instance constructor.
+ ///
+ /// The .
public ExternalApiSettings(NodeSettings nodeSettings)
{
// To avoid any rate limiting by Etherscan it is better to have an API key defined, but the API is still supposed to work to a limited extent without one.
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/Models/CoinGeckoResponse.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/Models/CoinGeckoResponse.cs
index b6863cc173..bc908bfae2 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/Models/CoinGeckoResponse.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/Models/CoinGeckoResponse.cs
@@ -1,14 +1,29 @@
namespace Stratis.Bitcoin.Features.ExternalApi.Models
{
+ ///
+ /// CoinGecko price data as included in .
+ ///
public class CoinGeckoPriceData
{
+ ///
+ /// The price in usd.
+ ///
public decimal usd { get; set; }
}
+ ///
+ /// CoinGecko response.
+ ///
public class CoinGeckoResponse
{
+ ///
+ /// The Stratis price.
+ ///
public CoinGeckoPriceData stratis { get; set; }
+ ///
+ /// The Ethereum price.
+ ///
public CoinGeckoPriceData ethereum { get; set; }
}
}
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/Models/EtherscanGasOracleResponse.cs b/src/Stratis.Bitcoin.Features.ExternalAPI/Models/EtherscanGasOracleResponse.cs
index 1bc915796e..2993bc7f78 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/Models/EtherscanGasOracleResponse.cs
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/Models/EtherscanGasOracleResponse.cs
@@ -1,22 +1,49 @@
namespace Stratis.Bitcoin.Features.ExternalApi.Models
{
+ ///
+ /// Etherscan gas oracle response.
+ ///
public class EtherscanGasOracleResponse
{
+ ///
+ /// Status.
+ ///
public string status { get; set; }
+ ///
+ /// Message.
+ ///
public string message { get; set; }
+ ///
+ /// See .
+ ///
public EtherscanGasOracleResponseResult result { get; set; }
}
+ ///
+ /// Etherscan gas oracle response result as included in .
+ ///
public class EtherscanGasOracleResponseResult
{
+ ///
+ /// The last block.
+ ///
public int LastBlock { get; set; }
+ ///
+ /// The safe gas price.
+ ///
public int SafeGasPrice { get; set; }
+ ///
+ /// The proposed gas price.
+ ///
public int ProposeGasPrice { get; set; }
+ ///
+ /// The fast gas price.
+ ///
public int FastGasPrice { get; set; }
}
}
diff --git a/src/Stratis.Bitcoin.Features.ExternalAPI/Stratis.Bitcoin.Features.ExternalApi.csproj b/src/Stratis.Bitcoin.Features.ExternalAPI/Stratis.Bitcoin.Features.ExternalApi.csproj
index 88f2172402..8c8a96a208 100644
--- a/src/Stratis.Bitcoin.Features.ExternalAPI/Stratis.Bitcoin.Features.ExternalApi.csproj
+++ b/src/Stratis.Bitcoin.Features.ExternalAPI/Stratis.Bitcoin.Features.ExternalApi.csproj
@@ -2,7 +2,7 @@
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis Group Ltd.
Stratis.Features.ExternalAPI
Stratis.Features.ExternalAPI
diff --git a/src/Stratis.Bitcoin.Features.Interop/Controllers/InteropController.cs b/src/Stratis.Bitcoin.Features.Interop/Controllers/InteropController.cs
index 784f4fc63b..646640311e 100644
--- a/src/Stratis.Bitcoin.Features.Interop/Controllers/InteropController.cs
+++ b/src/Stratis.Bitcoin.Features.Interop/Controllers/InteropController.cs
@@ -5,9 +5,10 @@
using System.Numerics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using NBitcoin;
using NBitcoin.DataEncoders;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.Interop.ETHClient;
using Stratis.Bitcoin.Features.Interop.Models;
using Stratis.Bitcoin.Features.PoA;
@@ -83,7 +84,7 @@ public IActionResult InteropStatusBurnRequests()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -123,7 +124,7 @@ public IActionResult InteropStatusMintRequests()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -159,7 +160,7 @@ public IActionResult InteropStatusVotes()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -187,7 +188,7 @@ public async Task OwnersAsync(DestinationChain destinationChain)
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -223,7 +224,7 @@ public async Task AddOwnerAsync(DestinationChain destinationChain
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -259,7 +260,7 @@ public async Task RemoveOwnerAsync(DestinationChain destinationCh
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -292,7 +293,7 @@ public async Task ConfirmTransactionAsync(DestinationChain destin
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -330,7 +331,7 @@ public async Task ChangeRequirementAsync(DestinationChain destina
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -374,7 +375,7 @@ public async Task MultisigTransactionAsync(DestinationChain desti
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -416,7 +417,7 @@ public async Task MultisigConfirmationsAsync(DestinationChain des
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -446,7 +447,7 @@ public async Task BalanceAsync(DestinationChain destinationChain,
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
@@ -486,7 +487,7 @@ public IActionResult SetOriginatorForRequest([FromBody] string requestId)
}
catch (Exception e)
{
- this.logger.Error("Exception setting conversion request '{0}' to {1} : {2}.", requestId, e.ToString(), ConversionRequestStatus.OriginatorNotSubmitted);
+ this.logger.LogError("Exception setting conversion request '{0}' to {1} : {2}.", requestId, e.ToString(), ConversionRequestStatus.OriginatorNotSubmitted);
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", e.Message);
}
@@ -510,7 +511,7 @@ public IActionResult ResetConversionRequestAsNotOriginator([FromBody] string req
}
catch (Exception e)
{
- this.logger.Error("Exception setting conversion request '{0}' to {1} : {2}.", requestId, e.ToString(), ConversionRequestStatus.NotOriginator);
+ this.logger.LogError("Exception setting conversion request '{0}' to {1} : {2}.", requestId, e.ToString(), ConversionRequestStatus.NotOriginator);
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", e.Message);
}
@@ -530,13 +531,13 @@ public IActionResult ReprocessBurnRequest([FromBody] ReprocessBurnRequestModel m
try
{
this.conversionRequestRepository.ReprocessBurnRequest(model.RequestId, model.BlockHeight, ConversionRequestStatus.Unprocessed);
- this.logger.Info($"Burn request '{model.RequestId}' will be reprocessed at height {model.BlockHeight}.");
+ this.logger.LogInformation($"Burn request '{model.RequestId}' will be reprocessed at height {model.BlockHeight}.");
return this.Json($"Burn request '{model.RequestId}' will be reprocessed at height {model.BlockHeight}.");
}
catch (Exception e)
{
- this.logger.Error("Exception setting burn request '{0}' to be reprocessed : {1}.", model.RequestId, e.ToString());
+ this.logger.LogError("Exception setting burn request '{0}' to be reprocessed : {1}.", model.RequestId, e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", e.Message);
}
@@ -561,7 +562,7 @@ public IActionResult PushVoteManually([FromBody] PushManualVoteForRequest model)
}
catch (Exception e)
{
- this.logger.Error("Exception manual pushing vote for conversion request '{0}' : {1}.", model.RequestId, e.ToString());
+ this.logger.LogError("Exception manual pushing vote for conversion request '{0}' : {1}.", model.RequestId, e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "Error", e.Message);
}
diff --git a/src/Stratis.Bitcoin.Features.Interop/GlobalSuppressions.cs b/src/Stratis.Bitcoin.Features.Interop/GlobalSuppressions.cs
new file mode 100644
index 0000000000..21cb2606e7
--- /dev/null
+++ b/src/Stratis.Bitcoin.Features.Interop/GlobalSuppressions.cs
@@ -0,0 +1,13 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+
+using System.Diagnostics.CodeAnalysis;
+
+// Temporary fix to reduce the clutter of warnings.
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.Interop")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1615:Element return value must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.Interop")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1611:The documentation for parameter is missing", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.Interop")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.Interop")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1614:Element parameter documentation must have text", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.Interop")]
diff --git a/src/Stratis.Bitcoin.Features.Interop/InteropBehavior.cs b/src/Stratis.Bitcoin.Features.Interop/InteropBehavior.cs
index 33f9c4add8..2e867e9d2f 100644
--- a/src/Stratis.Bitcoin.Features.Interop/InteropBehavior.cs
+++ b/src/Stratis.Bitcoin.Features.Interop/InteropBehavior.cs
@@ -1,8 +1,9 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.Interop.ETHClient;
using Stratis.Bitcoin.Features.Interop.Payloads;
using Stratis.Bitcoin.Features.PoA;
@@ -54,14 +55,14 @@ public override object Clone()
///
protected override void AttachCore()
{
- this.logger.Debug("Attaching behaviour for {0}", this.AttachedPeer.PeerEndPoint.Address);
+ this.logger.LogDebug("Attaching behaviour for {0}", this.AttachedPeer.PeerEndPoint.Address);
this.AttachedPeer.MessageReceived.Register(this.OnMessageReceivedAsync, true);
}
///
protected override void DetachCore()
{
- this.logger.Debug("Detaching behaviour for {0}", this.AttachedPeer.PeerEndPoint.Address);
+ this.logger.LogDebug("Detaching behaviour for {0}", this.AttachedPeer.PeerEndPoint.Address);
this.AttachedPeer.MessageReceived.Unregister(this.OnMessageReceivedAsync);
}
@@ -73,12 +74,12 @@ private async Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage mes
}
catch (OperationCanceledException)
{
- this.logger.Trace("(-)[CANCELED_EXCEPTION]");
+ this.logger.LogTrace("(-)[CANCELED_EXCEPTION]");
return;
}
catch (Exception ex)
{
- this.logger.Error("Exception occurred: {0}", ex.ToString());
+ this.logger.LogError("Exception occurred: {0}", ex.ToString());
throw;
}
}
@@ -104,7 +105,7 @@ private async Task ProcessMessageAsync(INetworkPeer peer, IncomingMessage messag
}
catch (OperationCanceledException)
{
- this.logger.Trace("(-)[CANCELED_EXCEPTION]");
+ this.logger.LogTrace("(-)[CANCELED_EXCEPTION]");
}
}
@@ -113,7 +114,7 @@ private async Task ProcessConversionRequestPayloadAsync(INetworkPeer peer, Conve
if (!this.federationManager.IsFederationMember)
return;
- this.logger.Debug("Conversion request payload request for id '{0}' received from '{1}':'{2}' proposing transaction ID '{4}'.", payload.RequestId, peer.PeerEndPoint.Address, peer.RemoteSocketEndpoint.Address, payload.RequestId, payload.TransactionId);
+ this.logger.LogDebug("Conversion request payload request for id '{0}' received from '{1}':'{2}' proposing transaction ID '{4}'.", payload.RequestId, peer.PeerEndPoint.Address, peer.RemoteSocketEndpoint.Address, payload.RequestId, payload.TransactionId);
if (payload.TransactionId == BigInteger.MinusOne)
return;
@@ -127,14 +128,14 @@ private async Task ProcessConversionRequestPayloadAsync(INetworkPeer peer, Conve
if (!this.federationManager.IsMultisigMember(pubKey))
{
- this.logger.Warn("Conversion request payload for '{0}'. Computed pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
+ this.logger.LogWarning("Conversion request payload for '{0}'. Computed pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
return;
}
}
catch (Exception)
{
- this.logger.Warn("Received malformed conversion request payload for '{0}'.", payload.RequestId);
+ this.logger.LogWarning("Received malformed conversion request payload for '{0}'.", payload.RequestId);
return;
}
@@ -153,7 +154,7 @@ private async Task ProcessConversionRequestPayloadAsync(INetworkPeer peer, Conve
// We presume that the initial submitter of the transaction must have at least confirmed it. Otherwise just ignore this coordination attempt.
if (confirmationCount < 1)
{
- this.logger.Info("Multisig wallet transaction {0} has no confirmations.", payload.TransactionId);
+ this.logger.LogInformation("Multisig wallet transaction {0} has no confirmations.", payload.TransactionId);
return;
}
@@ -183,13 +184,13 @@ private async Task ProcessFeeProposalAsync(FeeProposalPayload payload)
if (!this.federationManager.IsMultisigMember(pubKey))
{
- this.logger.Warn("Received unverified fee proposal payload for '{0}' from pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
+ this.logger.LogWarning("Received unverified fee proposal payload for '{0}' from pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
return;
}
}
catch (Exception)
{
- this.logger.Warn("Received malformed fee proposal payload for '{0}'.", payload.RequestId);
+ this.logger.LogWarning("Received malformed fee proposal payload for '{0}'.", payload.RequestId);
return;
}
@@ -213,13 +214,13 @@ private async Task ProcessFeeAgreeAsync(FeeAgreePayload payload)
if (!this.federationManager.IsMultisigMember(pubKey))
{
- this.logger.Warn("Received unverified fee vote payload for '{0}' from pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
+ this.logger.LogWarning("Received unverified fee vote payload for '{0}' from pubkey '{1}'.", payload.RequestId, pubKey?.ToHex());
return;
}
}
catch (Exception)
{
- this.logger.Warn("Received malformed fee vote payload for '{0}'.", payload.RequestId);
+ this.logger.LogWarning("Received malformed fee vote payload for '{0}'.", payload.RequestId);
return;
}
diff --git a/src/Stratis.Bitcoin.Features.Interop/InteropPoller.cs b/src/Stratis.Bitcoin.Features.Interop/InteropPoller.cs
index a21ad94145..4b69c8b7ef 100644
--- a/src/Stratis.Bitcoin.Features.Interop/InteropPoller.cs
+++ b/src/Stratis.Bitcoin.Features.Interop/InteropPoller.cs
@@ -5,14 +5,15 @@
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
+using Microsoft.Extensions.Logging;
using NBitcoin;
using NBitcoin.Crypto;
using Nethereum.RPC.Eth.DTOs;
using Nethereum.Util;
using Nethereum.Web3;
-using NLog;
using Stratis.Bitcoin.AsyncWork;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.ExternalApi;
using Stratis.Bitcoin.Features.Interop.ETHClient;
using Stratis.Bitcoin.Features.Interop.Exceptions;
@@ -126,17 +127,17 @@ public async Task InitializeAsync()
if (!this.ethClientProvider.GetAllSupportedChains().Any())
{
// There are no chains that are supported and enabled, exit.
- this.logger.Debug("Interop disabled.");
+ this.logger.LogDebug("Interop disabled.");
return;
}
if (!this.federationManager.IsFederationMember)
{
- this.logger.Debug("Not a federation member.");
+ this.logger.LogDebug("Not a federation member.");
return;
}
- this.logger.Info($"Interoperability enabled, initializing periodic loop.");
+ this.logger.LogInformation($"Interoperability enabled, initializing periodic loop.");
// Initialize the interop polling loop, to check for interop contract requests.
this.interopLoop = this.asyncProvider.CreateAndRunAsyncLoop("PeriodicCheckInterop", async (cancellation) =>
@@ -144,7 +145,7 @@ public async Task InitializeAsync()
if (this.initialBlockDownloadState.IsInitialBlockDownload())
return;
- this.logger.Trace("Beginning interop loop.");
+ this.logger.LogTrace("Beginning interop loop.");
try
{
@@ -152,10 +153,10 @@ public async Task InitializeAsync()
}
catch (Exception e)
{
- this.logger.Warn("Exception raised when checking interop requests. {0}", e);
+ this.logger.LogWarning("Exception raised when checking interop requests. {0}", e);
}
- this.logger.Trace("Finishing interop loop.");
+ this.logger.LogTrace("Finishing interop loop.");
},
this.nodeLifetime.ApplicationStopping,
repeatEvery: TimeSpans.TenSeconds,
@@ -167,7 +168,7 @@ public async Task InitializeAsync()
if (this.initialBlockDownloadState.IsInitialBlockDownload())
return;
- this.logger.Trace("Beginning conversion processing loop.");
+ this.logger.LogTrace("Beginning conversion processing loop.");
try
{
@@ -175,10 +176,10 @@ public async Task InitializeAsync()
}
catch (Exception e)
{
- this.logger.Warn($"Exception raised when checking conversion requests. {e}");
+ this.logger.LogWarning($"Exception raised when checking conversion requests. {e}");
}
- this.logger.Trace("Finishing conversion processing loop.");
+ this.logger.LogTrace("Finishing conversion processing loop.");
},
this.nodeLifetime.ApplicationStopping,
repeatEvery: TimeSpans.TenSeconds,
@@ -194,7 +195,7 @@ public async Task InitializeAsync()
if (this.initialBlockDownloadState.IsInitialBlockDownload())
return;
- this.logger.Debug("Beginning conversion burn transaction polling loop.");
+ this.logger.LogDebug("Beginning conversion burn transaction polling loop.");
try
{
@@ -208,10 +209,10 @@ public async Task InitializeAsync()
}
catch (Exception e)
{
- this.logger.Warn($"Exception raised when polling for conversion burn transactions. {e}");
+ this.logger.LogWarning($"Exception raised when polling for conversion burn transactions. {e}");
}
- this.logger.Debug("Finishing conversion burn transaction polling loop.");
+ this.logger.LogDebug("Finishing conversion burn transaction polling loop.");
},
this.nodeLifetime.ApplicationStopping,
repeatEvery: TimeSpans.TenSeconds,
@@ -233,14 +234,14 @@ private async Task LoadLastPolledBlockAsync()
else
this.lastPolledBlock[supportedChain.Key] = loaded;
- this.logger.Info($"Last polled block for {supportedChain.Key} set to {this.lastPolledBlock[supportedChain.Key]}.");
+ this.logger.LogInformation($"Last polled block for {supportedChain.Key} set to {this.lastPolledBlock[supportedChain.Key]}.");
}
}
private void SaveLastPolledBlock(DestinationChain destinationChain)
{
this.keyValueRepository.SaveValueJson(string.Format(LastPolledBlockKey, destinationChain), this.lastPolledBlock[destinationChain]);
- this.logger.Info($"Last polled block for {destinationChain} saved as {this.lastPolledBlock[destinationChain]}.");
+ this.logger.LogInformation($"Last polled block for {destinationChain} saved as {this.lastPolledBlock[destinationChain]}.");
}
///
@@ -263,7 +264,7 @@ private async Task EnsureLastPolledBlockIsSyncedWithChainAsync()
private async Task PollBlockForBurnRequestsAsync(KeyValuePair supportedChain, BigInteger blockHeight)
{
- this.logger.Info("Polling {0} block at height {1} for burn transactions.", supportedChain.Key, blockHeight);
+ this.logger.LogInformation("Polling {0} block at height {1} for burn transactions.", supportedChain.Key, blockHeight);
BlockWithTransactions block = await supportedChain.Value.GetBlockAsync(this.lastPolledBlock[supportedChain.Key]).ConfigureAwait(false);
List<(string TransactionHash, BurnFunction Burn)> burns = await supportedChain.Value.GetBurnsFromBlock(block).ConfigureAwait(false);
@@ -291,11 +292,11 @@ private async Task CheckInteropNodesAsync()
// TODO Add back or refactor so that this is specific per chain (if applicable)
// BigInteger balance = await this.ETHClientBase.GetBalanceAsync(this.interopSettings.ETHAccount).ConfigureAwait(false);
- this.logger.Info("Current {0} node block height is {1}.", clientForChain.Key, blockHeight);
+ this.logger.LogInformation("Current {0} node block height is {1}.", clientForChain.Key, blockHeight);
}
catch (Exception e)
{
- this.logger.Error("Error checking {0} node status: {1}", clientForChain.Key, e);
+ this.logger.LogError("Error checking {0} node status: {1}", clientForChain.Key, e);
}
}
}
@@ -305,24 +306,24 @@ private async Task CheckInteropNodesAsync()
///
private void ProcessBurn(string blockHash, string transactionHash, BurnFunction burn)
{
- this.logger.Info("Conversion burn transaction '{0}' received from polled block '{1}', sender {2}.", transactionHash, blockHash, burn.FromAddress);
+ this.logger.LogInformation("Conversion burn transaction '{0}' received from polled block '{1}', sender {2}.", transactionHash, blockHash, burn.FromAddress);
lock (this.repositoryLock)
{
if (this.conversionRequestRepository.Get(transactionHash) != null)
{
- this.logger.Info("Conversion burn transaction '{0}' already exists, ignoring.", transactionHash);
+ this.logger.LogInformation("Conversion burn transaction '{0}' already exists, ignoring.", transactionHash);
return;
}
}
- this.logger.Info("Conversion burn transaction '{0}' has value {1}.", transactionHash, burn.Amount);
+ this.logger.LogInformation("Conversion burn transaction '{0}' has value {1}.", transactionHash, burn.Amount);
// Get the destination address recorded in the contract call itself. This has the benefit that subsequent burn calls from the same account providing different addresses will not interfere with this call.
string destinationAddress = burn.StraxAddress;
- this.logger.Info("Conversion burn transaction '{0}' has destination address {1}.", transactionHash, destinationAddress);
+ this.logger.LogInformation("Conversion burn transaction '{0}' has destination address {1}.", transactionHash, destinationAddress);
// Validate that it is a mainchain address here before bothering to add it to the repository.
try
@@ -331,7 +332,7 @@ private void ProcessBurn(string blockHash, string transactionHash, BurnFunction
}
catch (Exception)
{
- this.logger.Warn("Error validating destination address '{0}' for transaction '{1}'.", destinationAddress, transactionHash);
+ this.logger.LogWarning("Error validating destination address '{0}' for transaction '{1}'.", destinationAddress, transactionHash);
return;
}
@@ -387,18 +388,18 @@ private async Task ProcessConversionRequestsAsync()
if (mintRequests == null)
{
- this.logger.Debug("There are no requests.");
+ this.logger.LogDebug("There are no requests.");
return;
}
- this.logger.Info("There are {0} unprocessed conversion mint requests.", mintRequests.Count);
+ this.logger.LogInformation("There are {0} unprocessed conversion mint requests.", mintRequests.Count);
foreach (ConversionRequest request in mintRequests)
{
// Ignore old conversion requests for the time being.
if (request.RequestStatus == ConversionRequestStatus.Unprocessed && (this.chainIndexer.Tip.Height - request.BlockHeight) > this.network.Consensus.MaxReorgLength)
{
- this.logger.Info("Ignoring old conversion mint request '{0}' with status {1} from block height {2}.", request.RequestId, request.RequestStatus, request.BlockHeight);
+ this.logger.LogInformation("Ignoring old conversion mint request '{0}' with status {1} from block height {2}.", request.RequestId, request.RequestStatus, request.BlockHeight);
request.Processed = true;
@@ -410,7 +411,7 @@ private async Task ProcessConversionRequestsAsync()
continue;
}
- this.logger.Info("Processing conversion mint request {0} on {1} chain.", request.RequestId, request.DestinationChain);
+ this.logger.LogInformation("Processing conversion mint request {0} on {1} chain.", request.RequestId, request.DestinationChain);
IETHClient clientForDestChain = this.ethClientProvider.GetClientForChain(request.DestinationChain);
@@ -439,13 +440,13 @@ private async Task ProcessConversionRequestsAsync()
if (originator)
{
// If this node is the designated transaction originator, it must create and submit the transaction to the multisig.
- this.logger.Info("This node selected as originator for transaction '{0}'.", request.RequestId);
+ this.logger.LogInformation("This node selected as originator for transaction '{0}'.", request.RequestId);
request.RequestStatus = ConversionRequestStatus.OriginatorNotSubmitted;
}
else
{
- this.logger.Info("This node was not selected as the originator for transaction '{0}'. The originator is: '{1}'.", request.RequestId, designatedMember == null ? "N/A (Overridden)" : designatedMember.PubKey?.ToHex());
+ this.logger.LogInformation("This node was not selected as the originator for transaction '{0}'. The originator is: '{1}'.", request.RequestId, designatedMember == null ? "N/A (Overridden)" : designatedMember.PubKey?.ToHex());
request.RequestStatus = ConversionRequestStatus.NotOriginator;
}
@@ -455,7 +456,7 @@ private async Task ProcessConversionRequestsAsync()
case ConversionRequestStatus.OriginatorNotSubmitted:
{
- this.logger.Info("Conversion not yet submitted, checking which gas price to use.");
+ this.logger.LogInformation("Conversion not yet submitted, checking which gas price to use.");
// First construct the necessary transfer() transaction data, utilising the ABI of the wrapped STRAX ERC20 contract.
// When this constructed transaction is actually executed, the transfer's source account will be the account executing the transaction i.e. the multisig contract address.
@@ -467,7 +468,7 @@ private async Task ProcessConversionRequestsAsync()
if (gasPrice == -1)
gasPrice = this.interopSettings.GetSettingsByChain(request.DestinationChain).GasPrice;
- this.logger.Info("Originator will use a gas price of {0} to submit the transaction.", gasPrice);
+ this.logger.LogInformation("Originator will use a gas price of {0} to submit the transaction.", gasPrice);
// Submit the unconfirmed transaction data to the multisig contract, returning a transactionId used to refer to it.
// Once sufficient multisig owners have confirmed the transaction the multisig contract will execute it.
@@ -488,12 +489,12 @@ private async Task ProcessConversionRequestsAsync()
case ConversionRequestStatus.OriginatorSubmitting:
{
(BigInteger confirmationCount, string blockHash) = await this.ethClientProvider.GetClientForChain(request.DestinationChain).GetConfirmationsAsync(request.ExternalChainTxHash).ConfigureAwait(false);
- this.logger.Info($"Originator confirming transaction id '{request.ExternalChainTxHash}' '({request.ExternalChainTxEventId})' before broadcasting; confirmations: {confirmationCount}; Block Hash {blockHash}.");
+ this.logger.LogInformation($"Originator confirming transaction id '{request.ExternalChainTxHash}' '({request.ExternalChainTxEventId})' before broadcasting; confirmations: {confirmationCount}; Block Hash {blockHash}.");
if (confirmationCount < this.SubmissionConfirmationThreshold)
break;
- this.logger.Info("Originator submitted transaction to multisig in transaction '{0}' and was allocated transactionId '{1}'.", request.ExternalChainTxHash, request.ExternalChainTxEventId);
+ this.logger.LogInformation("Originator submitted transaction to multisig in transaction '{0}' and was allocated transactionId '{1}'.", request.ExternalChainTxHash, request.ExternalChainTxEventId);
this.conversionRequestCoordinationService.AddVote(request.RequestId, BigInteger.Parse(request.ExternalChainTxEventId), this.federationManager.CurrentFederationKey.PubKey);
@@ -520,7 +521,7 @@ private async Task ProcessConversionRequestsAsync()
if (agreedTransactionId != BigInteger.MinusOne)
{
- this.logger.Info("Transaction '{0}' has received sufficient votes, it should now start getting confirmed by each peer.", agreedTransactionId);
+ this.logger.LogInformation("Transaction '{0}' has received sufficient votes, it should now start getting confirmed by each peer.", agreedTransactionId);
request.RequestStatus = ConversionRequestStatus.VoteFinalised;
}
@@ -541,7 +542,7 @@ private async Task ProcessConversionRequestsAsync()
if (confirmationCount >= this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum)
{
- this.logger.Info("Transaction '{0}' has received at least {1} confirmations, it will be automatically executed by the multisig contract.", transactionId3, this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum);
+ this.logger.LogInformation("Transaction '{0}' has received at least {1} confirmations, it will be automatically executed by the multisig contract.", transactionId3, this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum);
request.RequestStatus = ConversionRequestStatus.Processed;
request.Processed = true;
@@ -551,7 +552,7 @@ private async Task ProcessConversionRequestsAsync()
}
else
{
- this.logger.Info("Transaction '{0}' has finished voting but does not yet have {1} confirmations, re-broadcasting votes to peers.", transactionId3, this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum);
+ this.logger.LogInformation("Transaction '{0}' has finished voting but does not yet have {1} confirmations, re-broadcasting votes to peers.", transactionId3, this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum);
// There are not enough confirmations yet.
// Even though the vote is finalised, other nodes may come and go. So we re-broadcast the finalised votes to all federation peers.
// Nodes will simply ignore the messages if they are not relevant.
@@ -577,7 +578,7 @@ private async Task ProcessConversionRequestsAsync()
{
// TODO: Should we check the number of confirmations for the submission transaction here too?
- this.logger.Info("Quorum reached for conversion transaction '{0}' with transactionId '{1}', submitting confirmation to contract.", request.RequestId, agreedUponId);
+ this.logger.LogInformation("Quorum reached for conversion transaction '{0}' with transactionId '{1}', submitting confirmation to contract.", request.RequestId, agreedUponId);
int gasPrice = this.externalApiPoller.GetGasPrice();
@@ -585,7 +586,7 @@ private async Task ProcessConversionRequestsAsync()
if (gasPrice == -1)
gasPrice = this.interopSettings.GetSettingsByChain(request.DestinationChain).GasPrice;
- this.logger.Info("The non-originator will use a gas price of {0} to confirm the transaction.", gasPrice);
+ this.logger.LogInformation("The non-originator will use a gas price of {0} to confirm the transaction.", gasPrice);
// Once a quorum is reached, each node confirms the agreed transactionId.
// If the originator or some other nodes renege on their vote, the current node will not re-confirm a different transactionId.
@@ -593,7 +594,7 @@ private async Task ProcessConversionRequestsAsync()
request.ExternalChainTxHash = confirmationHash;
- this.logger.Info("The hash of the confirmation transaction for conversion transaction '{0}' was '{1}'.", request.RequestId, confirmationHash);
+ this.logger.LogInformation("The hash of the confirmation transaction for conversion transaction '{0}' was '{1}'.", request.RequestId, confirmationHash);
request.RequestStatus = ConversionRequestStatus.VoteFinalised;
}
@@ -603,7 +604,7 @@ private async Task ProcessConversionRequestsAsync()
if (transactionId4 != BigInteger.MinusOne)
{
- this.logger.Debug("Broadcasting vote (transactionId '{0}') for conversion transaction '{1}'.", transactionId4, request.RequestId);
+ this.logger.LogDebug("Broadcasting vote (transactionId '{0}') for conversion transaction '{1}'.", transactionId4, request.RequestId);
this.conversionRequestCoordinationService.AddVote(request.RequestId, transactionId4, this.federationManager.CurrentFederationKey.PubKey);
@@ -660,7 +661,7 @@ private bool DetermineConversionRequestOriginator(int blockHeight, out IFederati
// We are not able to simply use the entire federation member list, as only multisig nodes can be transaction originators.
List federation = this.federationHistory.GetFederationForBlock(this.chainIndexer.GetHeader(blockHeight));
- this.logger.Info($"Federation retrieved at height '{blockHeight}', size {federation.Count} members.");
+ this.logger.LogInformation($"Federation retrieved at height '{blockHeight}', size {federation.Count} members.");
var multisig = new List();
@@ -687,9 +688,10 @@ private bool DetermineConversionRequestOriginator(int blockHeight, out IFederati
}
///
- /// Wait for the submission to be well-confirmed before initial vote & broadcast.
+ /// Wait for the submission to be well-confirmed before initial vote and broadcast.
///
/// The transaction information to check.
+ ///
/// The caller that is waiting on the submission transaction's confirmation count.
/// True if it succeeded, false if the node is stopping.
private async Task WaitForReplenishmentToBeConfirmedAsync(MultisigTransactionIdentifiers identifiers, DestinationChain destinationChain, [CallerMemberName] string caller = null)
@@ -700,7 +702,7 @@ private async Task WaitForReplenishmentToBeConfirmedAsync(MultisigTransact
return false;
(BigInteger confirmationCount, string blockHash) = await this.ethClientProvider.GetClientForChain(destinationChain).GetConfirmationsAsync(identifiers.TransactionHash).ConfigureAwait(false);
- this.logger.Info($"[{caller}] Originator confirming transaction id '{identifiers.TransactionHash}' '({identifiers.TransactionId})' before broadcasting; confirmations: {confirmationCount}; Block Hash {blockHash}.");
+ this.logger.LogInformation($"[{caller}] Originator confirming transaction id '{identifiers.TransactionHash}' '({identifiers.TransactionId})' before broadcasting; confirmations: {confirmationCount}; Block Hash {blockHash}.");
if (confirmationCount >= this.SubmissionConfirmationThreshold)
break;
@@ -730,7 +732,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
if (originator)
{
- this.logger.Info("Insufficient reserve balance remaining, initiating mint transaction to replenish reserve.");
+ this.logger.LogInformation("Insufficient reserve balance remaining, initiating mint transaction to replenish reserve.");
// By minting the request amount + the reserve requirement, we cater for arbitrarily large amounts in the request.
string mintData = this.ethClientProvider.GetClientForChain(request.DestinationChain).EncodeMintParams(this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletAddress, amountInWei + this.ReserveBalanceTarget);
@@ -741,7 +743,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
if (gasPrice == -1)
gasPrice = this.interopSettings.GetSettingsByChain(request.DestinationChain).GasPrice;
- this.logger.Info("Originator will use a gas price of {0} to submit the mint replenishment transaction.", gasPrice);
+ this.logger.LogInformation("Originator will use a gas price of {0} to submit the mint replenishment transaction.", gasPrice);
MultisigTransactionIdentifiers identifiers = await this.ethClientProvider.GetClientForChain(request.DestinationChain).SubmitTransactionAsync(this.interopSettings.GetSettingsByChain(request.DestinationChain).WrappedStraxContractAddress, 0, mintData, gasPrice).ConfigureAwait(false);
@@ -757,7 +759,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
return;
}
- this.logger.Info("Originator adding its vote for mint transaction id: {0}", mintTransactionId);
+ this.logger.LogInformation("Originator adding its vote for mint transaction id: {0}", mintTransactionId);
this.conversionRequestCoordinationService.AddVote(mintRequestId, mintTransactionId, this.federationManager.CurrentFederationKey.PubKey);
@@ -767,7 +769,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
await this.BroadcastCoordinationVoteRequestAsync(mintRequestId, mintTransactionId, request.DestinationChain).ConfigureAwait(false);
}
else
- this.logger.Info("Insufficient reserve balance remaining, waiting for originator to initiate mint transaction to replenish reserve.");
+ this.logger.LogInformation("Insufficient reserve balance remaining, waiting for originator to initiate mint transaction to replenish reserve.");
BigInteger agreedTransactionId;
@@ -781,7 +783,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
agreedTransactionId = this.conversionRequestCoordinationService.GetAgreedTransactionId(mintRequestId, this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum);
- this.logger.Debug("Agreed transaction id '{0}'.", agreedTransactionId);
+ this.logger.LogDebug("Agreed transaction id '{0}'.", agreedTransactionId);
if (agreedTransactionId != BigInteger.MinusOne)
break;
@@ -789,7 +791,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
// Just re-broadcast.
if (originator)
{
- this.logger.Debug("Originator broadcasting id {0}.", mintTransactionId);
+ this.logger.LogDebug("Originator broadcasting id {0}.", mintTransactionId);
await this.BroadcastCoordinationVoteRequestAsync(mintRequestId, mintTransactionId, request.DestinationChain).ConfigureAwait(false);
}
@@ -798,7 +800,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
if (ourTransactionId == BigInteger.MinusOne)
ourTransactionId = this.conversionRequestCoordinationService.GetCandidateTransactionId(mintRequestId);
- this.logger.Debug("Non-originator broadcasting id {0}.", ourTransactionId);
+ this.logger.LogDebug("Non-originator broadcasting id {0}.", ourTransactionId);
if (ourTransactionId != BigInteger.MinusOne)
{
@@ -814,7 +816,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
}
- this.logger.Info("Agreed transaction ID for replenishment transaction: {0}", agreedTransactionId);
+ this.logger.LogInformation("Agreed transaction ID for replenishment transaction: {0}", agreedTransactionId);
if (!originator)
{
@@ -824,11 +826,11 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
if (gasPrice == -1)
gasPrice = this.interopSettings.GetSettingsByChain(request.DestinationChain).GasPrice;
- this.logger.Info("Non-originator will use a gas price of {0} to confirm the mint replenishment transaction.", gasPrice);
+ this.logger.LogInformation("Non-originator will use a gas price of {0} to confirm the mint replenishment transaction.", gasPrice);
string confirmation = await this.ethClientProvider.GetClientForChain(request.DestinationChain).ConfirmTransactionAsync(agreedTransactionId, gasPrice).ConfigureAwait(false);
- this.logger.Info("ID of confirmation transaction: {0}", confirmation);
+ this.logger.LogInformation("ID of confirmation transaction: {0}", confirmation);
}
while (true)
@@ -838,7 +840,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
BigInteger confirmationCount = await this.ethClientProvider.GetClientForChain(request.DestinationChain).GetMultisigConfirmationCountAsync(agreedTransactionId).ConfigureAwait(false);
- this.logger.Info("Waiting for confirmation of mint replenishment transaction {0}, current count {1}.", mintRequestId, confirmationCount);
+ this.logger.LogInformation("Waiting for confirmation of mint replenishment transaction {0}, current count {1}.", mintRequestId, confirmationCount);
if (confirmationCount >= this.interopSettings.GetSettingsByChain(request.DestinationChain).MultisigWalletQuorum)
break;
@@ -847,7 +849,7 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
}
- this.logger.Info("Mint replenishment transaction {0} fully confirmed.", mintTransactionId);
+ this.logger.LogInformation("Mint replenishment transaction {0} fully confirmed.", mintTransactionId);
while (true)
{
@@ -858,11 +860,11 @@ private async Task PerformReplenishmentAsync(ConversionRequest request, BigInteg
if (balance > startBalance)
{
- this.logger.Info("The contract's balance has been replenished, new balance {0}.", balance);
+ this.logger.LogInformation("The contract's balance has been replenished, new balance {0}.", balance);
break;
}
else
- this.logger.Info("The contract's balance is unchanged at {0}.", balance);
+ this.logger.LogInformation("The contract's balance is unchanged at {0}.", balance);
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
}
diff --git a/src/Stratis.Bitcoin.Features.Interop/Stratis.Bitcoin.Features.Interop.csproj b/src/Stratis.Bitcoin.Features.Interop/Stratis.Bitcoin.Features.Interop.csproj
index a51fa86041..adb2719f73 100644
--- a/src/Stratis.Bitcoin.Features.Interop/Stratis.Bitcoin.Features.Interop.csproj
+++ b/src/Stratis.Bitcoin.Features.Interop/Stratis.Bitcoin.Features.Interop.csproj
@@ -2,7 +2,7 @@
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis Group Ltd.
Stratis.Features.Interop
Stratis.Features.Interop
@@ -10,6 +10,7 @@
bin\Debug\netcoreapp3.1\Stratis.Bitcoin.Features.Interop.xml
+ 1701;1702;1591
diff --git a/src/Stratis.Bitcoin.Features.LightWallet/Stratis.Bitcoin.Features.LightWallet.csproj b/src/Stratis.Bitcoin.Features.LightWallet/Stratis.Bitcoin.Features.LightWallet.csproj
index 8908f0672d..c689b947a8 100644
--- a/src/Stratis.Bitcoin.Features.LightWallet/Stratis.Bitcoin.Features.LightWallet.csproj
+++ b/src/Stratis.Bitcoin.Features.LightWallet/Stratis.Bitcoin.Features.LightWallet.csproj
@@ -7,7 +7,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.MemoryPool.Tests/MempoolValidatorTest.cs b/src/Stratis.Bitcoin.Features.MemoryPool.Tests/MempoolValidatorTest.cs
index f26c6ed35c..34728fa25e 100644
--- a/src/Stratis.Bitcoin.Features.MemoryPool.Tests/MempoolValidatorTest.cs
+++ b/src/Stratis.Bitcoin.Features.MemoryPool.Tests/MempoolValidatorTest.cs
@@ -180,6 +180,7 @@ public async Task AcceptToMemoryPool_WithValidP2PKHTxn_IsSuccessfulAsync()
/// Validate multi input/output P2PK, P2PKH transactions in memory pool.
/// Transaction scenario adapted from code project article referenced below.
///
+ /// The asynchronous task.
///
[Fact]
public async Task AcceptToMemoryPool_WithMultiInOutValidTxns_IsSuccessfulAsync()
@@ -244,6 +245,7 @@ public async Task AcceptToMemoryPool_WithMultiInOutValidTxns_IsSuccessfulAsync()
/// Validate multi sig transactions in memory pool.
/// Transaction scenario adapted from code project article referenced below.
///
+ /// The asynchronous task.
///
[Fact]
public async Task AcceptToMemoryPool_WithMultiSigValidTxns_IsSuccessfulAsync()
@@ -312,6 +314,7 @@ public async Task AcceptToMemoryPool_WithMultiSigValidTxns_IsSuccessfulAsync()
/// Validate P2SH transaction in memory pool.
/// Transaction scenario adapted from code project article referenced below.
///
+ /// The asynchronous task.
///
[Fact]
public async Task AcceptToMemoryPool_WithP2SHValidTxns_IsSuccessfulAsync()
@@ -373,6 +376,7 @@ public async Task AcceptToMemoryPool_WithP2SHValidTxns_IsSuccessfulAsync()
///
/// Validate P2WPKH transaction in memory pool.
///
+ /// The asynchronous task.
[Fact]
public async Task AcceptToMemoryPool_WithP2WPKHValidTxns_IsSuccessfulAsync()
{
@@ -517,6 +521,7 @@ public async Task AcceptToMemoryPool_SpendingP2WPKH_WithMissingWitnessData_Retur
///
/// Validate P2WSH transaction in memory pool.
///
+ /// The asynchronous task.
[Fact]
public async Task AcceptToMemoryPool_WithP2WSHValidTxns_IsSuccessfulAsync()
{
@@ -1034,7 +1039,7 @@ public async Task AcceptToMemoryPool_NonBIP68CanMine_ReturnsFalseAsync()
}
[Fact]
- public async Task AcceptToMemoryPool_NonStandardBareMultiSig_ReturnsFalse()
+ public async Task AcceptToMemoryPool_NonStandardBareMultiSig_ReturnsFalseAsync()
{
string dataDir = GetTestDirectoryPath(this);
@@ -1686,9 +1691,10 @@ public async Task AcceptToMemoryPool_TxPowConsensusCheckInputBadTransactionInBel
}
[Fact(Skip = "Not clear how to test this without triggering In Below Out check instead.")]
- public async Task AcceptToMemoryPool_TxPowConsensusCheckInputNegativeFee_ReturnsFalseAsync()
+ public Task AcceptToMemoryPool_TxPowConsensusCheckInputNegativeFee_ReturnsFalse()
{
// TODO: Execute failure case for CheckAllInputs CheckInputs PowCoinViewRule.CheckInputs NegativeFee
+ return Task.CompletedTask;
}
[Fact(Skip = "Making transactions with very large inputs/outputs pass validation is difficult, WIP.")]
diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/BlocksDisconnectedSignaled.cs b/src/Stratis.Bitcoin.Features.MemoryPool/BlocksDisconnectedSignaled.cs
index f70667fe77..bd55d61843 100644
--- a/src/Stratis.Bitcoin.Features.MemoryPool/BlocksDisconnectedSignaled.cs
+++ b/src/Stratis.Bitcoin.Features.MemoryPool/BlocksDisconnectedSignaled.cs
@@ -53,6 +53,7 @@ private void OnBlockDisconnected(BlockDisconnected blockDisconnected)
///
/// This could potentially be optimized. with an async queue.
/// The disconnected block containing the transactions.
+ /// The asynchronous task.
private async Task AddBackToMempoolAsync(Block block)
{
var state = new MempoolValidationState(true);
@@ -78,6 +79,8 @@ await this.mempoolLock.WriteAsync(async () =>
///
/// If there are any transactions in the mempool that depend on transactions no longer in the chain, remove them.
///
+ /// The block containing the coinbase that should not be spent.
+ /// The asynchronous task.
private async Task RemoveInvalidTransactionsAsync(Block block)
{
// TODO: This was initially implemented only to fix a known issue on Cirrus.
@@ -96,7 +99,7 @@ private async Task RemoveInvalidTransactionsAsync(Block block)
// Invalid transactions would have spent the coinbase. The other transactions can be put back into the mempool and be fine.
uint256 coinbaseId = block.Transactions[0].GetHash();
- await this.mempoolLock.WriteAsync(async () =>
+ await this.mempoolLock.WriteAsync(() =>
{
foreach (TxMempoolEntry mempoolEntry in this.mempool.MapTx.SpendsCoinbase.ToList())
{
diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/MempoolFeature.cs b/src/Stratis.Bitcoin.Features.MemoryPool/MempoolFeature.cs
index 607284ea37..2159ad3e8b 100644
--- a/src/Stratis.Bitcoin.Features.MemoryPool/MempoolFeature.cs
+++ b/src/Stratis.Bitcoin.Features.MemoryPool/MempoolFeature.cs
@@ -52,6 +52,7 @@ public class MempoolFeature : FullNodeFeature
/// Memory pool node behavior for managing attached node messages.
/// Memory pool manager for managing external access to memory pool.
/// Logger factory for creating instance logger.
+ /// See .
public MempoolFeature(
IConnectionManager connectionManager,
MempoolSignaled mempoolSignaled,
@@ -142,7 +143,7 @@ public static class FullNodeBuilderMempoolExtension
/// Include the memory pool feature and related services in the full node.
///
/// Full node builder.
- /// Full node builder.
+ /// The full node builder.
public static IFullNodeBuilder UseMempool(this IFullNodeBuilder fullNodeBuilder)
{
LoggingConfiguration.RegisterFeatureNamespace("mempool");
diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/Rules/StraxCoinViewMempoolRule.cs b/src/Stratis.Bitcoin.Features.MemoryPool/Rules/StraxCoinViewMempoolRule.cs
index e1cc5e170e..6421bc30f9 100644
--- a/src/Stratis.Bitcoin.Features.MemoryPool/Rules/StraxCoinViewMempoolRule.cs
+++ b/src/Stratis.Bitcoin.Features.MemoryPool/Rules/StraxCoinViewMempoolRule.cs
@@ -20,6 +20,7 @@ public StraxCoinViewMempoolRule(Network network,
{
}
+ ///
/// Also see >
public override void CheckTransaction(MempoolValidationContext context)
{
diff --git a/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj b/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj
index c51a7792a7..b419d37d2c 100644
--- a/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj
+++ b/src/Stratis.Bitcoin.Features.MemoryPool/Stratis.Bitcoin.Features.MemoryPool.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
library
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Miner/BlockDefinition.cs b/src/Stratis.Bitcoin.Features.Miner/BlockDefinition.cs
index 04bb3cf238..d3123ab871 100644
--- a/src/Stratis.Bitcoin.Features.Miner/BlockDefinition.cs
+++ b/src/Stratis.Bitcoin.Features.Miner/BlockDefinition.cs
@@ -266,11 +266,13 @@ public virtual void BlockModified(ChainedHeader chainTip, Block block)
///
/// Network specific logic to add a transaction to the block from a given mempool entry.
///
+ /// The .
public abstract void AddToBlock(TxMempoolEntry mempoolEntry);
///
/// Adds a transaction to the block and updates the and values.
///
+ /// The .
protected void AddTransactionToBlock(Transaction transaction)
{
this.block.AddTransaction(transaction);
@@ -285,6 +287,7 @@ protected void AddTransactionToBlock(Transaction transaction)
/// The block's and values are adjusted.
///
///
+ /// The .
protected void UpdateBlockStatistics(TxMempoolEntry mempoolEntry)
{
this.BlockSigOpsCost += mempoolEntry.SigOpCost;
@@ -295,6 +298,7 @@ protected void UpdateBlockStatistics(TxMempoolEntry mempoolEntry)
///
/// Updates the total fee amount for this block.
///
+ /// The fee to add to the total fee amount for the block.
protected void UpdateTotalFees(Money fee)
{
this.fees += fee;
@@ -316,6 +320,8 @@ protected void UpdateTotalFees(Money fee)
/// mapModifiedTxs with the next transaction in the mempool to decide what
/// transaction package to work on next.
///
+ /// Updated packages selected statistic.
+ /// Updated descendants updated statistic.
protected virtual void AddTransactions(out int nPackagesSelected, out int nDescendantsUpdated)
{
nPackagesSelected = 0;
@@ -488,6 +494,7 @@ protected virtual void AddTransactions(out int nPackagesSelected, out int nDesce
///
/// Remove confirmed entries from given set.
///
+ /// The confirmed .
private void OnlyUnconfirmed(TxMempool.SetEntries testSet)
{
foreach (TxMempoolEntry setEntry in testSet.ToList())
@@ -503,6 +510,10 @@ private void OnlyUnconfirmed(TxMempool.SetEntries testSet)
///
/// Test if a new package would "fit" in the block.
///
+ /// The .
+ /// The package size.
+ /// The package sigops cost.
+ /// True if the package would fit in the block or false otherwise.
protected virtual bool TestPackage(TxMempoolEntry entry, long packageSize, long packageSigOpsCost)
{
// TODO: Switch to weight-based accounting for packages instead of vsize-based accounting.
@@ -532,6 +543,8 @@ protected virtual bool TestPackage(TxMempoolEntry entry, long packageSize, long
///
///
///
+ /// The package.
+ /// True if the checks have passed or false otherwise.
private bool TestPackageTransactions(TxMempool.SetEntries package)
{
foreach (TxMempoolEntry it in package)
@@ -561,6 +574,9 @@ private bool TestPackageTransactions(TxMempool.SetEntries package)
/// state updated assuming given transactions are inBlock. Returns number
/// of updated descendants.
///
+ /// The .
+ /// The map to add the descendants to.
+ /// The number of updated descendants.
private int UpdatePackagesForAdded(TxMempool.SetEntries alreadyAdded, Dictionary mapModifiedTx)
{
int descendantsUpdated = 0;
@@ -605,6 +621,9 @@ private int UpdatePackagesForAdded(TxMempool.SetEntries alreadyAdded, Dictionary
}
/// Network specific logic specific as to how the block will be built.
+ /// The chain tip.
+ /// The scriptpubkey.
+ /// The .
public abstract BlockTemplate Build(ChainedHeader chainTip, Script scriptPubKey);
/// Update the block's header information.
diff --git a/src/Stratis.Bitcoin.Features.Miner/BlockDefinitionOptions.cs b/src/Stratis.Bitcoin.Features.Miner/BlockDefinitionOptions.cs
index 11b4646600..6f02e00cb2 100644
--- a/src/Stratis.Bitcoin.Features.Miner/BlockDefinitionOptions.cs
+++ b/src/Stratis.Bitcoin.Features.Miner/BlockDefinitionOptions.cs
@@ -31,6 +31,8 @@ public BlockDefinitionOptions(uint blockMaxWeight, uint blockMaxSize)
/// Restrict the options to within those allowed by network consensus rules.
/// If set values are outside those allowed by consensus, set to nearest allowed value (minimum or maximum).
///
+ /// The network context.
+ /// The .
public BlockDefinitionOptions RestrictForNetwork(Network network)
{
uint minAllowedBlockWeight = MinBlockSize * (uint) network.Consensus.Options.WitnessScaleFactor;
diff --git a/src/Stratis.Bitcoin.Features.Miner/BlockProvider.cs b/src/Stratis.Bitcoin.Features.Miner/BlockProvider.cs
index fde2519c0a..260897b369 100644
--- a/src/Stratis.Bitcoin.Features.Miner/BlockProvider.cs
+++ b/src/Stratis.Bitcoin.Features.Miner/BlockProvider.cs
@@ -19,6 +19,8 @@ public sealed class BlockProvider : IBlockProvider
/// Defines how proof of work blocks are built on a Proof-of-Stake network.
private readonly PosPowBlockDefinition posPowBlockDefinition;
+ /// The instance constructor.
+ /// The network context.
/// A list of block definitions that the builder can utilize.
public BlockProvider(Network network, IEnumerable definitions)
{
diff --git a/src/Stratis.Bitcoin.Features.Miner/MiningFeature.cs b/src/Stratis.Bitcoin.Features.Miner/MiningFeature.cs
index 9fc1f7cf08..b9d309e701 100644
--- a/src/Stratis.Bitcoin.Features.Miner/MiningFeature.cs
+++ b/src/Stratis.Bitcoin.Features.Miner/MiningFeature.cs
@@ -260,6 +260,7 @@ public static IFullNodeBuilder AddMining(this IFullNodeBuilder fullNodeBuilder)
/// Adds POW and POS miner components to the node, so that it can mine or stake.
///
/// The object used to build the current node.
+ /// Indicates whether the class should be used.
/// The full node builder, enriched with the new component.
public static IFullNodeBuilder AddPowPosMining(this IFullNodeBuilder fullNodeBuilder, bool straxMode)
{
diff --git a/src/Stratis.Bitcoin.Features.Miner/PowMining.cs b/src/Stratis.Bitcoin.Features.Miner/PowMining.cs
index 929c43548c..3b80384b0b 100644
--- a/src/Stratis.Bitcoin.Features.Miner/PowMining.cs
+++ b/src/Stratis.Bitcoin.Features.Miner/PowMining.cs
@@ -192,6 +192,8 @@ public List GenerateBlocks(ReserveScript reserveScript, ulong amountOfB
///
/// Ensures that the node is synced before mining is allowed to start.
///
+ /// The .
+ /// True if the node is synced and false otherwise.
private bool ConsensusIsAtTip(MineBlockContext context)
{
this.miningCancellationTokenSource.Token.ThrowIfCancellationRequested();
@@ -219,6 +221,8 @@ private bool ConsensusIsAtTip(MineBlockContext context)
/// generation of blocks inside tests, where it is possible to generate multiple blocks within one second.
///
///
+ /// The .
+ /// True if the block was successfully built or false otherwise.
private bool BuildBlock(MineBlockContext context)
{
context.BlockTemplate = this.blockProvider.BuildPowBlock(context.ChainTip, context.ReserveScript.ReserveFullNodeScript);
@@ -235,6 +239,8 @@ private bool BuildBlock(MineBlockContext context)
///
/// Executes until the required work (difficulty) has been reached. This is the "mining" process.
///
+ /// The .
+ /// True if the block was successfully mined or false otherwise.
private bool MineBlock(MineBlockContext context)
{
if (this.network.Consensus.LastPOWBlock != 0 && context.ChainTip.Height > this.network.Consensus.LastPOWBlock)
@@ -263,6 +269,8 @@ private bool MineBlock(MineBlockContext context)
///
/// Ensures that the block was properly mined by checking the block's work against the next difficulty target.
///
+ /// The .
+ /// True if the block passed validation or false otherwise.
private bool ValidateMinedBlock(MineBlockContext context)
{
if (context.BlockTemplate.Block.Header.Nonce == InnerLoopCount)
@@ -281,6 +289,8 @@ private bool ValidateMinedBlock(MineBlockContext context)
/// On successful block validation the block will be connected to the chain.
///
///
+ /// The .
+ /// True if the block was successfully validated and connected or false otherwise.
private bool ValidateAndConnectBlock(MineBlockContext context)
{
ChainedHeader chainedHeader = this.consensusManager.BlockMinedAsync(context.BlockTemplate.Block).GetAwaiter().GetResult();
diff --git a/src/Stratis.Bitcoin.Features.Miner/Stratis.Bitcoin.Features.Miner.csproj b/src/Stratis.Bitcoin.Features.Miner/Stratis.Bitcoin.Features.Miner.csproj
index 938e15a118..8a4a2276df 100644
--- a/src/Stratis.Bitcoin.Features.Miner/Stratis.Bitcoin.Features.Miner.csproj
+++ b/src/Stratis.Bitcoin.Features.Miner/Stratis.Bitcoin.Features.Miner.csproj
@@ -1,4 +1,4 @@
-
+
Stratis Bitcoin Features Miner
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Notifications/Stratis.Bitcoin.Features.Notifications.csproj b/src/Stratis.Bitcoin.Features.Notifications/Stratis.Bitcoin.Features.Notifications.csproj
index d157857348..2a08f51253 100644
--- a/src/Stratis.Bitcoin.Features.Notifications/Stratis.Bitcoin.Features.Notifications.csproj
+++ b/src/Stratis.Bitcoin.Features.Notifications/Stratis.Bitcoin.Features.Notifications.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common.csproj b/src/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common.csproj
index 6a689853df..4816b77229 100644
--- a/src/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common.csproj
+++ b/src/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common/Stratis.Bitcoin.Features.PoA.IntegrationTests.Common.csproj
@@ -13,7 +13,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
diff --git a/src/Stratis.Bitcoin.Features.PoA.IntegrationTests/VotingAndMiningTests.cs b/src/Stratis.Bitcoin.Features.PoA.IntegrationTests/VotingAndMiningTests.cs
index 3bdb73dbe3..2ac9f23f68 100644
--- a/src/Stratis.Bitcoin.Features.PoA.IntegrationTests/VotingAndMiningTests.cs
+++ b/src/Stratis.Bitcoin.Features.PoA.IntegrationTests/VotingAndMiningTests.cs
@@ -393,7 +393,7 @@ public async Task TransactionSentFeesReceivedByMinerAsync()
Assert.True(context.TransactionBuilder.Verify(trx, out _));
- await nodeA.FullNode.NodeController().SendTransaction(new SendTransactionRequest(trx.ToHex()));
+ await nodeA.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(trx.ToHex()));
TestBase.WaitLoop(() => nodeA.CreateRPCClient().GetRawMempool().Length == 1 && nodeB.CreateRPCClient().GetRawMempool().Length == 1);
@@ -451,7 +451,7 @@ public async Task CanMineVotingRequestTransactionAsync()
var encoder = new JoinFederationRequestEncoder();
JoinFederationRequestResult result = JoinFederationRequestBuilder.BuildTransaction(nodeA.FullNode.WalletTransactionHandler(), this.poaNetwork, request, encoder, walletName, walletAccount, walletPassword);
- await nodeA.FullNode.NodeController().SendTransaction(new SendTransactionRequest(result.Transaction.ToHex()));
+ await nodeA.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(result.Transaction.ToHex()));
TestBase.WaitLoop(() => nodeA.CreateRPCClient().GetRawMempool().Length == 1 && nodeB.CreateRPCClient().GetRawMempool().Length == 1);
diff --git a/src/Stratis.Bitcoin.Features.PoA.Tests/PoATestsBase.cs b/src/Stratis.Bitcoin.Features.PoA.Tests/PoATestsBase.cs
index 0bdd24def6..f0429d0fa4 100644
--- a/src/Stratis.Bitcoin.Features.PoA.Tests/PoATestsBase.cs
+++ b/src/Stratis.Bitcoin.Features.PoA.Tests/PoATestsBase.cs
@@ -59,7 +59,7 @@ public PoATestsBase(TestPoANetwork network = null)
(this.federationManager, this.federationHistory) = CreateFederationManager(this, this.network, this.loggerFactory, this.signals);
- this.slotsManager = new SlotsManager(this.network, this.federationManager, this.ChainIndexer, this.loggerFactory);
+ this.slotsManager = new SlotsManager(this.network, this.federationManager, this.federationHistory, this.ChainIndexer);
this.poaHeaderValidator = new PoABlockHeaderValidator(this.loggerFactory);
this.asyncProvider = new AsyncProvider(this.loggerFactory, this.signals);
@@ -120,7 +120,7 @@ public static (IFederationManager federationManager, IFederationHistory federati
return members[chainedHeader.Height % members.Count];
});
- federationHistory.Setup(x => x.GetFederationForBlock(It.IsAny())).Returns((chainedHeader) =>
+ federationHistory.Setup(x => x.GetFederationForBlock(It.IsAny(), It.IsAny())).Returns((chainedHeader, offset) =>
{
return ((PoAConsensusOptions)network.Consensus.Options).GenesisFederationMembers;
});
diff --git a/src/Stratis.Bitcoin.Features.PoA.Tests/Rules/PoAVotingCoinbaseOutputFormatRuleTests.cs b/src/Stratis.Bitcoin.Features.PoA.Tests/Rules/PoAVotingCoinbaseOutputFormatRuleTests.cs
index 2c1b9fb729..8a714a09ff 100644
--- a/src/Stratis.Bitcoin.Features.PoA.Tests/Rules/PoAVotingCoinbaseOutputFormatRuleTests.cs
+++ b/src/Stratis.Bitcoin.Features.PoA.Tests/Rules/PoAVotingCoinbaseOutputFormatRuleTests.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using NBitcoin;
-using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.Consensus.Rules;
using Stratis.Bitcoin.Features.PoA.Voting;
diff --git a/src/Stratis.Bitcoin.Features.PoA.Tests/SlotsManagerTests.cs b/src/Stratis.Bitcoin.Features.PoA.Tests/SlotsManagerTests.cs
index fcf198562b..e7d29c9e67 100644
--- a/src/Stratis.Bitcoin.Features.PoA.Tests/SlotsManagerTests.cs
+++ b/src/Stratis.Bitcoin.Features.PoA.Tests/SlotsManagerTests.cs
@@ -15,6 +15,7 @@ public class SlotsManagerTests
private TestPoANetwork network;
private readonly PoAConsensusOptions consensusOptions;
private readonly IFederationManager federationManager;
+ private readonly IFederationHistory federationHistory;
private Mock chainIndexer;
public SlotsManagerTests()
@@ -22,9 +23,9 @@ public SlotsManagerTests()
this.network = new TestPoANetwork();
this.consensusOptions = this.network.ConsensusOptions;
- this.federationManager = PoATestsBase.CreateFederationManager(this).federationManager;
+ (this.federationManager, this.federationHistory) = PoATestsBase.CreateFederationManager(this);
this.chainIndexer = new Mock();
- this.slotsManager = new SlotsManager(this.network, this.federationManager, this.chainIndexer.Object, new LoggerFactory());
+ this.slotsManager = new SlotsManager(this.network, this.federationManager, this.federationHistory, this.chainIndexer.Object);
}
[Fact]
@@ -45,10 +46,10 @@ public void GetMiningTimestamp()
Key key = tool.GeneratePrivateKey();
this.network = new TestPoANetwork(new List() { tool.GeneratePrivateKey().PubKey, key.PubKey, tool.GeneratePrivateKey().PubKey });
- IFederationManager fedManager = PoATestsBase.CreateFederationManager(this, this.network, new ExtendedLoggerFactory(), new Signals.Signals(new LoggerFactory(), null)).federationManager;
+ (IFederationManager fedManager, IFederationHistory federationHistory) = PoATestsBase.CreateFederationManager(this, this.network, new ExtendedLoggerFactory(), new Signals.Signals(new LoggerFactory(), null));
var header = new BlockHeader();
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(header, header.GetHash(), 0));
- this.slotsManager = new SlotsManager(this.network, fedManager, this.chainIndexer.Object, new LoggerFactory());
+ this.slotsManager = new SlotsManager(this.network, fedManager, federationHistory, this.chainIndexer.Object);
List federationMembers = fedManager.GetFederationMembers();
uint roundStart = this.consensusOptions.TargetSpacingSeconds * (uint)federationMembers.Count * 5;
@@ -81,8 +82,13 @@ public void GetMiningTimestamp()
Time = thisTurnTimestamp
};
+ Mock.Get(federationHistory).Setup(x => x.GetFederationMemberForBlock(It.IsAny())).Returns((chainedHeader) =>
+ {
+ return federationMembers[1];
+ });
+
this.chainIndexer.Setup(x => x.Tip).Returns(new ChainedHeader(header, header.GetHash(), 0));
- this.slotsManager = new SlotsManager(this.network, fedManager, this.chainIndexer.Object, new LoggerFactory());
+ this.slotsManager = new SlotsManager(this.network, fedManager, federationHistory, this.chainIndexer.Object);
Assert.Equal(nextTurnTimestamp, this.slotsManager.GetMiningTimestamp(thisTurnTimestamp + 1));
}
diff --git a/src/Stratis.Bitcoin.Features.PoA.Tests/VotingDataEncoderTests.cs b/src/Stratis.Bitcoin.Features.PoA.Tests/VotingDataEncoderTests.cs
index a628902223..18707d543d 100644
--- a/src/Stratis.Bitcoin.Features.PoA.Tests/VotingDataEncoderTests.cs
+++ b/src/Stratis.Bitcoin.Features.PoA.Tests/VotingDataEncoderTests.cs
@@ -2,7 +2,6 @@
using System.Linq;
using System.Text;
using NBitcoin;
-using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.Features.PoA.Voting;
using Xunit;
diff --git a/src/Stratis.Bitcoin.Features.PoA/BasePoAFeatureConsensusRules/PoAHeaderSignatureRule.cs b/src/Stratis.Bitcoin.Features.PoA/BasePoAFeatureConsensusRules/PoAHeaderSignatureRule.cs
index 3181205fa2..1055896814 100644
--- a/src/Stratis.Bitcoin.Features.PoA/BasePoAFeatureConsensusRules/PoAHeaderSignatureRule.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/BasePoAFeatureConsensusRules/PoAHeaderSignatureRule.cs
@@ -1,4 +1,6 @@
-using System.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin;
@@ -34,15 +36,15 @@ public override void Initialize()
this.federationHistory = engine.FederationHistory;
this.validator = engine.PoaHeaderValidator;
- var lastCheckPoint = engine.Network.Checkpoints.LastOrDefault();
+ KeyValuePair lastCheckPoint = engine.Network.Checkpoints.LastOrDefault();
this.lastCheckPoint = (lastCheckPoint.Value != null) ? new HashHeightPair(lastCheckPoint.Value.Hash, lastCheckPoint.Key) : null;
}
- public override async Task RunAsync(RuleContext context)
+ public override Task RunAsync(RuleContext context)
{
// Only start validating at the last checkpoint block.
if (context.ValidationContext.ChainedHeaderToValidate.Height < (this.lastCheckPoint?.Height ?? 0))
- return;
+ return Task.CompletedTask;
ChainedHeader chainedHeader = context.ValidationContext.ChainedHeaderToValidate;
@@ -71,12 +73,12 @@ public override async Task RunAsync(RuleContext context)
}
// Look at the last round of blocks to find the previous time that the miner mined.
- var roundTime = this.slotsManager.GetRoundLength(this.federationHistory.GetFederationForBlock(chainedHeader).Count);
+ TimeSpan roundTime = this.slotsManager.GetRoundLength(this.federationHistory.GetFederationForBlock(chainedHeader).Count);
// Quick check for optimisation.
this.federationHistory.GetLastActiveTime(federationMember, chainedHeader.Previous, out uint lastActiveTime);
if ((chainedHeader.Header.Time - lastActiveTime) >= roundTime.TotalSeconds)
- return;
+ return Task.CompletedTask;
int blockCounter = 0;
@@ -103,6 +105,8 @@ public override async Task RunAsync(RuleContext context)
this.Logger.LogTrace("(-)[TIME_TOO_EARLY]");
ConsensusErrors.BlockTimestampTooEarly.Throw();
}
+
+ return Task.CompletedTask;
}
}
}
\ No newline at end of file
diff --git a/src/Stratis.Bitcoin.Features.PoA/Collateral/CollateralHeightCommitmentEncoder.cs b/src/Stratis.Bitcoin.Features.PoA/Collateral/CollateralHeightCommitmentEncoder.cs
index 6de818eadd..fdf9a0a662 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Collateral/CollateralHeightCommitmentEncoder.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Collateral/CollateralHeightCommitmentEncoder.cs
@@ -1,8 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
namespace Stratis.Features.PoA.Collateral
{
@@ -40,7 +41,7 @@ public byte[] EncodeCommitmentHeight(int height)
byte[] commitmentData = null;
byte[] magic = null;
- this.logger.Debug("Transaction contains {0} OP_RETURN outputs.", opReturnOutputs.Count());
+ this.logger.LogDebug("Transaction contains {0} OP_RETURN outputs.", opReturnOutputs.Count());
foreach (Script script in opReturnOutputs)
{
@@ -55,7 +56,7 @@ public byte[] EncodeCommitmentHeight(int height)
if (!correctPrefix)
{
- this.logger.Debug("Push data contains incorrect prefix for height commitment.");
+ this.logger.LogDebug("Push data contains incorrect prefix for height commitment.");
continue;
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/FederationHistory.cs b/src/Stratis.Bitcoin.Features.PoA/FederationHistory.cs
index a74dacda09..a74e0ed72f 100644
--- a/src/Stratis.Bitcoin.Features.PoA/FederationHistory.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/FederationHistory.cs
@@ -27,8 +27,9 @@ public interface IFederationHistory
/// Gets the federation for a specified block.
/// Identifies the block and timestamp.
+ /// Identifies a block relative to
/// The federation member or null if the member could not be determined.
- List GetFederationForBlock(ChainedHeader chainedHeader);
+ List GetFederationForBlock(ChainedHeader chainedHeader, int offset = 0);
///
/// Determines when a federation member was last active. This includes mining or joining.
@@ -96,11 +97,12 @@ public bool CanGetFederationForBlock(ChainedHeader chainedHeader)
}
///
- public List GetFederationForBlock(ChainedHeader chainedHeader)
+ public List GetFederationForBlock(ChainedHeader chainedHeader, int offset = 0)
{
lock (this.lockObject)
{
- if ((this.lastActiveTip == chainedHeader || this.lastActiveTip?.FindFork(chainedHeader)?.Height >= chainedHeader.Height) &&
+ if (this.lastFederationTip >= (chainedHeader.Height + offset) &&
+ (this.lastActiveTip == chainedHeader || this.lastActiveTip?.FindFork(chainedHeader)?.Height >= chainedHeader.Height) &&
this.federationHistory.TryGetValue(chainedHeader.Height, out (List modifiedFederation, HashSet whoJoined, IFederationMember miner) item))
{
return item.modifiedFederation;
@@ -347,7 +349,7 @@ ChainedHeader GetHeader(int height)
return blockHeader.GetAncestor(height);
}
-
+
// Find the first block with Time >= minTime. We're not interested in re-reading any blocks below or at the last active tip though.
int startHeight = (this.lastActiveTip?.Height ?? -1) + 1;
startHeight = BinarySearch.BinaryFindFirst(n => GetHeader(n).Header.Time >= minTime, startHeight, blockHeader.Height - startHeight + 1);
@@ -373,7 +375,8 @@ ChainedHeader GetHeader(int height)
foreach (ChainedHeader header in blockHeader.EnumerateToGenesis().Take(miners.Length).Reverse())
{
- var history = this.federationHistory[header.Height];
+ // Add the miner to the history.
+ (List members, HashSet joined, IFederationMember miner) history = this.federationHistory[header.Height];
history.miner = miners[header.Height - startHeight];
this.federationHistory[header.Height] = history;
diff --git a/src/Stratis.Bitcoin.Features.PoA/FederationManager.cs b/src/Stratis.Bitcoin.Features.PoA/FederationManager.cs
index 6a6d321775..dde8319dac 100644
--- a/src/Stratis.Bitcoin.Features.PoA/FederationManager.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/FederationManager.cs
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Consensus;
using Stratis.Bitcoin.Features.PoA.Events;
using Stratis.Bitcoin.Features.PoA.Voting;
@@ -31,11 +32,12 @@ public interface IFederationManager
void Initialize();
- /// Provides up to date list of federation members.
+ /// Provides up-to-date list of federation members.
///
/// Blocks that are not signed with private keys that correspond
/// to public keys from this list are considered to be invalid.
///
+ /// An up-to-date list of federation members.
List GetFederationMembers();
bool IsMultisigMember(PubKey pubKey);
@@ -101,19 +103,19 @@ public void Initialize()
{
var genesisFederation = new List(this.network.ConsensusOptions.GenesisFederationMembers);
- this.logger.Info("Genesis federation contains {0} members. Their public keys are: {1}", genesisFederation.Count, $"{Environment.NewLine}{string.Join(Environment.NewLine, genesisFederation)}");
+ this.logger.LogInformation("Genesis federation contains {0} members. Their public keys are: {1}", genesisFederation.Count, $"{Environment.NewLine}{string.Join(Environment.NewLine, genesisFederation)}");
// Load federation from the db.
this.LoadFederation();
if (this.federationMembers == null)
{
- this.logger.Debug("Federation members are not stored in the database, using genesis federation members.");
+ this.logger.LogDebug("Federation members are not stored in the database, using genesis federation members.");
this.federationMembers = genesisFederation;
}
// Display federation.
- this.logger.Info("Current federation contains {0} members. Their public keys are: {1}", this.federationMembers.Count, Environment.NewLine + string.Join(Environment.NewLine, this.federationMembers));
+ this.logger.LogInformation("Current federation contains {0} members. Their public keys are: {1}", this.federationMembers.Count, Environment.NewLine + string.Join(Environment.NewLine, this.federationMembers));
// Set the current federation member's key.
if (!InitializeFederationMemberKey())
@@ -122,14 +124,14 @@ public void Initialize()
// Loaded key has to be a key for current federation.
if (!this.federationMembers.Any(x => x.PubKey == this.CurrentFederationKey.PubKey))
{
- this.logger.Warn("Key provided is not registered on the network.");
+ this.logger.LogWarning("Key provided is not registered on the network.");
}
// TODO This will be removed once we remove the distinction between FederationMember and CollateralFederationMember
if (this.federationMembers.Any(f => f is CollateralFederationMember))
CheckCollateralMembers();
- this.logger.Info("Federation key pair was successfully loaded. Your public key is: '{0}'.", this.CurrentFederationKey.PubKey);
+ this.logger.LogInformation("Federation key pair was successfully loaded. Your public key is: '{0}'.", this.CurrentFederationKey.PubKey);
}
private bool InitializeFederationMemberKey()
@@ -140,7 +142,7 @@ private bool InitializeFederationMemberKey()
Key key = new KeyTool(this.nodeSettings.DataFolder).LoadPrivateKey();
if (key == null)
{
- this.logger.Warn("No federation key was loaded from 'federationKey.dat'.");
+ this.logger.LogWarning("No federation key was loaded from 'federationKey.dat'.");
return false;
}
@@ -149,7 +151,7 @@ private bool InitializeFederationMemberKey()
if (this.CurrentFederationKey == null)
{
- this.logger.Trace("(-)[NOT_FED_MEMBER]");
+ this.logger.LogTrace("(-)[NOT_FED_MEMBER]");
return false;
}
@@ -285,20 +287,22 @@ public void AddFederationMember(IFederationMember federationMember)
this.signals.Publish(new FedMemberAdded(federationMember));
}
- /// Should be protected by .
+ /// Adds a federation member to the internal list of federation members.
+ /// The to add.
+ /// Should be protected by .
private void AddFederationMemberLocked(IFederationMember federationMember)
{
if (federationMember is CollateralFederationMember collateralFederationMember)
{
if (this.federationMembers.IsCollateralAddressRegistered(collateralFederationMember.CollateralMainchainAddress))
{
- this.logger.Warn($"Federation member with address '{collateralFederationMember.CollateralMainchainAddress}' already exists.");
+ this.logger.LogWarning($"Federation member with address '{collateralFederationMember.CollateralMainchainAddress}' already exists.");
return;
}
if (this.federationMembers.Contains(federationMember))
{
- this.logger.Trace("(-)[ALREADY_EXISTS]");
+ this.logger.LogTrace("(-)[ALREADY_EXISTS]");
return;
}
}
@@ -307,7 +311,7 @@ private void AddFederationMemberLocked(IFederationMember federationMember)
this.SetIsFederationMember();
- this.logger.Info("Federation member '{0}' was added.", federationMember);
+ this.logger.LogInformation("Federation member '{0}' was added.", federationMember);
}
public void RemoveFederationMember(IFederationMember federationMember)
@@ -318,7 +322,7 @@ public void RemoveFederationMember(IFederationMember federationMember)
this.SetIsFederationMember();
- this.logger.Info("Federation member '{0}' was removed.", federationMember);
+ this.logger.LogInformation("Federation member '{0}' was removed.", federationMember);
}
this.signals.Publish(new FedMemberKicked(federationMember));
diff --git a/src/Stratis.Bitcoin.Features.PoA/PoAConsensusOptions.cs b/src/Stratis.Bitcoin.Features.PoA/PoAConsensusOptions.cs
index 6899e76a8b..145d7741e3 100644
--- a/src/Stratis.Bitcoin.Features.PoA/PoAConsensusOptions.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/PoAConsensusOptions.cs
@@ -15,6 +15,9 @@ public class PoAConsensusOptions : ConsensusOptions
///
public List GenesisFederationMembers { get; protected set; }
+ ///
+ /// The number of elapsed seconds required between mined block.
+ ///
public uint TargetSpacingSeconds { get; protected set; }
/// Adds capability of voting for adding\kicking federation members and other things.
@@ -50,6 +53,13 @@ public class PoAConsensusOptions : ConsensusOptions
///
public int InterFluxV2MainChainActivationHeight { get; set; }
+ ///
+ /// The height at which inituitive mining slots become active.
+ /// Legacy mining slots are determined by mining_slot = block_height % number_of_federation_members.
+ /// Once the specified height is reached there should no longer be a shift in mining slots when new federation members are added/removed.
+ ///
+ public int GetMiningTimestampV2ActivationHeight { get; set; }
+
///
/// Logic related to release 1.1.0.0 will activate at this height, this includes Poll Expiry and the Join Federation Voting Request consensus rule.
///
@@ -68,6 +78,16 @@ public class PoAConsensusOptions : ConsensusOptions
public int ContractSerializerV2ActivationHeight { get; set; }
/// Initializes values for networks that use block size rules.
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
+ /// See .
public PoAConsensusOptions(
uint maxBlockBaseSize,
int maxStandardVersion,
diff --git a/src/Stratis.Bitcoin.Features.PoA/PoAFeature.cs b/src/Stratis.Bitcoin.Features.PoA/PoAFeature.cs
index 3342f9260d..08c469ff2f 100644
--- a/src/Stratis.Bitcoin.Features.PoA/PoAFeature.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/PoAFeature.cs
@@ -153,6 +153,7 @@ public override Task InitializeAsync()
}
/// Replaces default with .
+ /// See .
private void ReplaceConsensusManagerBehavior(NetworkPeerConnectionParameters connectionParameters)
{
INetworkPeerBehavior defaultConsensusManagerBehavior = connectionParameters.TemplateBehaviors.FirstOrDefault(behavior => behavior is ConsensusManagerBehavior);
@@ -167,6 +168,7 @@ private void ReplaceConsensusManagerBehavior(NetworkPeerConnectionParameters con
}
/// Replaces default with .
+ /// See .
private void ReplaceBlockStoreBehavior(NetworkPeerConnectionParameters connectionParameters)
{
INetworkPeerBehavior defaultBlockStoreBehavior = connectionParameters.TemplateBehaviors.FirstOrDefault(behavior => behavior is BlockStoreBehavior);
diff --git a/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs b/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
index b348a801ef..330579660f 100644
--- a/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/PoAMiner.cs
@@ -177,10 +177,31 @@ public virtual void InitializeMining()
return Task.CompletedTask;
},
this.nodeLifetime.ApplicationStopping,
- repeatEvery: TimeSpans.Minute,
+ repeatEvery: TimeSpans.TenSeconds,
startAfter: TimeSpans.TenSeconds);
}
+ private IFederationMember DetermineExpectedMinerForTimestamp(uint headerTime)
+ {
+ // When blocks are missing for given timestamps we have to determine whom was supposed to mine
+ // by looking at the federation make-up at the time and whom mined last.
+
+ ChainedHeader prevBlockMined = this.consensusManager.Tip;
+ while (prevBlockMined.Header.Time > headerTime)
+ prevBlockMined = prevBlockMined.Previous;
+
+ IFederationMember minerForBlock = this.federationHistory.GetFederationMemberForBlock(prevBlockMined);
+ List federationAtBlock = this.federationHistory.GetFederationForBlock(prevBlockMined);
+
+ int offset = (int)((headerTime - prevBlockMined.Header.Time) / this.network.ConsensusOptions.TargetSpacingSeconds);
+
+ int minerForBlockIndex = federationAtBlock.TakeWhile(m => m.PubKey != minerForBlock.PubKey).Count();
+
+ int expectedIndex = (minerForBlockIndex + offset) % federationAtBlock.Count;
+
+ return federationAtBlock[expectedIndex];
+ }
+
private void GatherMiningStatistics()
{
var log = new StringBuilder();
@@ -188,6 +209,17 @@ private void GatherMiningStatistics()
log.AppendLine(">> Miner");
log.AppendLine();
+ if (!this.federationManager.IsFederationMember)
+ {
+ log.AppendLine("Mining information is not available for non federation members.");
+ log.AppendLine("It is possible that your node was kicked from the federation due to inactivity.");
+ log.AppendLine();
+
+ this.miningStatisticsLog = log.ToString();
+
+ return;
+ }
+
if (this.ibdState.IsInitialBlockDownload())
{
log.AppendLine("Mining information is not available whilst the node is syncing.");
@@ -209,49 +241,59 @@ private void GatherMiningStatistics()
int maxDepth = modifiedFederation.Count;
+ // TODO: Make this a command line option.
+ bool includeHeight = false;
+
log.AppendLine($"Mining information for the last { maxDepth } blocks.");
- log.AppendLine("Note that '<' and '>' surrounds a slot where a miner didn't produce a block.");
+ if (includeHeight)
+ log.AppendLine("Note 'MISS' indicates a slot where a miner didn't produce a block.");
+ else
+ log.AppendLine("Note that '<' and '>' surrounds a slot where a miner didn't produce a block.");
- uint timeHeader = (uint)this.dateTimeProvider.GetAdjustedTimeAsUnixTimestamp();
- timeHeader -= timeHeader % this.network.ConsensusOptions.TargetSpacingSeconds;
- if (timeHeader < currentHeader.Header.Time)
- timeHeader += this.network.ConsensusOptions.TargetSpacingSeconds;
+ uint currentSlotTime = (uint)this.dateTimeProvider.GetAdjustedTimeAsUnixTimestamp();
+ currentSlotTime -= currentSlotTime % this.network.ConsensusOptions.TargetSpacingSeconds;
+ // Determine the public key of the current slot.
+ string pubKeyRepresentation;
// Iterate mining slots.
- for (int i = 0; i < maxDepth; i++)
+ for (int i = 0; i < maxDepth; i++, currentSlotTime -= this.network.ConsensusOptions.TargetSpacingSeconds)
{
- int headerSlot = (int)(timeHeader / this.network.ConsensusOptions.TargetSpacingSeconds) % modifiedFederation.Count;
-
- PubKey pubKey = modifiedFederation[headerSlot].PubKey;
-
- string pubKeyRepresentation = pubKey.ToString().Substring(0, pubKeyTakeCharacters);
- if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
- pubKeyRepresentation = "█████";
+ // Find the chained header for this slot.
+ while (currentHeader.Header.Time > currentSlotTime)
+ currentHeader = currentHeader.Previous;
// Mined in this slot?
- if (timeHeader == currentHeader.Header.Time)
- {
- log.Append($"[{ pubKeyRepresentation }] ");
+ bool minedInThisSlot = currentHeader.Header.Time == currentSlotTime;
- currentHeader = currentHeader.Previous;
- hitCount++;
+ PubKey pubKey = (minedInThisSlot ?
+ this.federationHistory.GetFederationMemberForBlock(currentHeader) :
+ DetermineExpectedMinerForTimestamp(currentSlotTime)).PubKey;
- modifiedFederation = this.federationHistory.GetFederationForBlock(currentHeader);
- if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
- this.miningStatistics.ProducedBlockInLastRound = true;
+ if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
+ {
+ pubKeyRepresentation = "█████";
+ this.miningStatistics.ProducedBlockInLastRound = minedInThisSlot;
}
else
{
- log.Append($"<{ pubKeyRepresentation }> ");
+ pubKeyRepresentation = pubKey.ToHex().Substring(0, pubKeyTakeCharacters);
+ }
- if (pubKey == this.federationManager.CurrentFederationKey?.PubKey)
- this.miningStatistics.ProducedBlockInLastRound = false;
+ if (includeHeight)
+ {
+ string strHeight = minedInThisSlot ? currentHeader.Height.ToString().PadLeft(7) : "---MISS";
+ log.Append($"{strHeight}:{ pubKeyRepresentation } ");
+ }
+ else
+ {
+ log.Append(minedInThisSlot ? $"[{pubKeyRepresentation}] " : $"<{pubKeyRepresentation}> ");
}
- timeHeader -= this.network.ConsensusOptions.TargetSpacingSeconds;
+ if (minedInThisSlot)
+ hitCount++;
- if ((i % 20) == 19)
+ if (((i + 1) % (includeHeight ? 10 : 20)) == 0)
log.AppendLine();
}
@@ -360,38 +402,32 @@ private async Task CreateBlocksAsync()
private async Task WaitUntilMiningSlotAsync()
{
- uint? myTimestamp = null;
-
while (!this.cancellation.IsCancellationRequested)
{
uint timeNow = (uint)this.dateTimeProvider.GetAdjustedTimeAsUnixTimestamp();
if (timeNow <= this.consensusManager.Tip.Header.Time)
{
- await Task.Delay(TimeSpan.FromMilliseconds(500)).ConfigureAwait(false);
+ await Task.Delay(TimeSpan.FromMilliseconds(100)).ConfigureAwait(false);
continue;
}
- if (myTimestamp == null)
+ try
{
- try
- {
- myTimestamp = this.slotsManager.GetMiningTimestamp(timeNow);
- }
- catch (NotAFederationMemberException)
- {
- this.logger.LogWarning("This node is no longer a federation member!");
+ uint myTimestamp = this.slotsManager.GetMiningTimestamp(timeNow);
- throw new OperationCanceledException();
- }
- }
+ if (myTimestamp <= timeNow)
+ return myTimestamp;
- int estimatedWaitingTime = (int)(myTimestamp - timeNow) - 1;
+ }
+ catch (NotAFederationMemberException)
+ {
+ this.logger.LogWarning("This node is no longer a federation member!");
- if (estimatedWaitingTime <= 0)
- return myTimestamp.Value;
+ throw new OperationCanceledException();
+ }
- await Task.Delay(TimeSpan.FromMilliseconds(500), this.cancellation.Token).ConfigureAwait(false);
+ await Task.Delay(TimeSpan.FromMilliseconds(100), this.cancellation.Token).ConfigureAwait(false);
}
throw new OperationCanceledException();
@@ -401,7 +437,7 @@ protected async Task MineBlockAtTimestampAsync(uint timestamp)
{
ChainedHeader tip = this.consensusManager.Tip;
- // Timestamp should always be greater than prev one.
+ // Timestamp should always be greater than prev one.
if (timestamp <= tip.Header.Time)
{
// Can happen only when target spacing had crazy low value or key was compromised and someone is mining with our key.
@@ -479,6 +515,8 @@ protected async Task MineBlockAtTimestampAsync(uint timestamp)
}
/// Fills block template with custom non-standard data.
+ /// See .
+ /// Indicates whether the template should be dropped.
protected virtual void FillBlockTemplate(BlockTemplate blockTemplate, out bool dropTemplate)
{
if (this.network.ConsensusOptions.VotingEnabled)
@@ -496,7 +534,8 @@ protected virtual void FillBlockTemplate(BlockTemplate blockTemplate, out bool d
dropTemplate = false;
}
- /// Gets scriptPubKey from the wallet.
+ /// Gets the first address from the first account of the first wallet - if any. Returns null otherwise.
+ /// See
private HdAddress GetMiningAddressFromWallet()
{
string walletName = this.walletManager.GetWalletsNames().FirstOrDefault();
@@ -515,6 +554,7 @@ private HdAddress GetMiningAddressFromWallet()
}
/// Adds OP_RETURN output to a coinbase transaction which contains encoded voting data.
+ /// See .
/// If there are no votes scheduled output will not be added.
private void AddVotingData(BlockTemplate blockTemplate)
{
diff --git a/src/Stratis.Bitcoin.Features.PoA/SlotsManager.cs b/src/Stratis.Bitcoin.Features.PoA/SlotsManager.cs
index 1e1c22bcd6..d8449916c0 100644
--- a/src/Stratis.Bitcoin.Features.PoA/SlotsManager.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/SlotsManager.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using Microsoft.Extensions.Logging;
using NBitcoin;
using Stratis.Bitcoin.Utilities;
@@ -15,9 +14,13 @@ public interface ISlotsManager
/// Gets next timestamp at which current node can produce a block.
/// Thrown if this node is not a federation member.
+ /// The current unix timestamp.
+ /// The next timestamp at which current node can produce a block.
uint GetMiningTimestamp(uint currentTime);
/// Determines whether timestamp is valid according to the network rules.
+ /// The unix timstamp of a block header.
+ /// True if the timestamp is valid and false otherwise.
bool IsValidTimestamp(uint headerUnixTimestamp);
TimeSpan GetRoundLength(int? federationMembersCount = null);
@@ -29,21 +32,85 @@ public class SlotsManager : ISlotsManager
private readonly IFederationManager federationManager;
- private readonly ChainIndexer chainIndexer;
+ private readonly IFederationHistory federationHistory;
- private readonly ILogger logger;
+ private readonly ChainIndexer chainIndexer;
- public SlotsManager(Network network, IFederationManager federationManager, ChainIndexer chainIndexer, ILoggerFactory loggerFactory)
+ public SlotsManager(Network network, IFederationManager federationManager, IFederationHistory federationHistory, ChainIndexer chainIndexer)
{
Guard.NotNull(network, nameof(network));
+
this.federationManager = Guard.NotNull(federationManager, nameof(federationManager));
+ this.federationHistory = federationHistory;
this.chainIndexer = chainIndexer;
this.consensusOptions = (network as PoANetwork).ConsensusOptions;
- this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
}
- ///
public uint GetMiningTimestamp(uint currentTime)
+ {
+ /*
+ A miner can calculate when its expected to mine by looking at the ordered list of federation members
+ and the last block that was mined and by whom. It can count the number of mining slots from that member
+ to itself and multiply that with the target spacing to arrive at its mining timestamp.
+ The fact that the federation can change at any time adds extra complexity to this basic approach.
+ The miner that mined the last block may no longer exist when the next block is about to be mined. As such
+ we may need to look a bit further back to find a "reference miner" that still occurs in the latest federation.
+ */
+ ChainedHeader tip = this.chainIndexer.Tip;
+ if (tip.Height < this.consensusOptions.GetMiningTimestampV2ActivationHeight)
+ return GetMiningTimestampLegacy(currentTime);
+
+ List federationMembers = this.federationHistory.GetFederationForBlock(tip, 1);
+ if (federationMembers == null)
+ throw new Exception($"Could not determine the federation at block { tip.Height } + 1.");
+
+ int myIndex = federationMembers.FindIndex(m => m.PubKey == this.federationManager.CurrentFederationKey?.PubKey);
+ if (myIndex < 0)
+ throw new NotAFederationMemberException();
+
+ // Find a "reference miner" to determine our slot against.
+ ChainedHeader referenceMinerBlock = tip;
+ IFederationMember referenceMiner = null;
+ int referenceMinerIndex = -1;
+ int referenceMinerDepth = 0;
+ for (int i = 0; i < federationMembers.Count; i++, referenceMinerDepth++)
+ {
+ referenceMiner = this.federationHistory.GetFederationMemberForBlock(referenceMinerBlock);
+ referenceMinerIndex = federationMembers.FindIndex(m => m.PubKey == referenceMiner.PubKey);
+ if (referenceMinerIndex >= 0)
+ break;
+ }
+
+ if (referenceMinerIndex < 0)
+ throw new Exception("Could not find a member in common between the old and new federation");
+
+ // Found a reference miner that also occurs in the latest federation.
+ // Determine how many blocks before our mining slot.
+ int blocksFromTipToMiningSlot = myIndex - referenceMinerIndex - referenceMinerDepth;
+ while (blocksFromTipToMiningSlot < 0)
+ blocksFromTipToMiningSlot += federationMembers.Count;
+
+ // Round length in seconds.
+ uint roundTime = (uint)this.GetRoundLength(federationMembers.Count).TotalSeconds;
+
+ // Get the tip time and make is a valid time if required.
+ uint tipTime = tip.Header.Time;
+ if (!IsValidTimestamp(tipTime))
+ tipTime += (this.consensusOptions.TargetSpacingSeconds - tipTime % this.consensusOptions.TargetSpacingSeconds);
+
+ // Check if we have missed our turn for this round.
+ // We still consider ourselves "in a turn" if we are in the first half of the turn and we haven't mined there yet.
+ // This might happen when starting the node for the first time or if there was a problem when mining.
+
+ uint nextTimestampForMining = (uint)(tipTime + blocksFromTipToMiningSlot * this.consensusOptions.TargetSpacingSeconds);
+ while (currentTime > nextTimestampForMining + (this.consensusOptions.TargetSpacingSeconds / 2) // We are closer to the next turn than our own
+ || tipTime == nextTimestampForMining)
+ nextTimestampForMining += roundTime;
+
+ return nextTimestampForMining;
+ }
+
+ private uint GetMiningTimestampLegacy(uint currentTime)
{
if (!this.federationManager.IsFederationMember)
throw new NotAFederationMemberException();
diff --git a/src/Stratis.Bitcoin.Features.PoA/Stratis.Bitcoin.Features.PoA.csproj b/src/Stratis.Bitcoin.Features.PoA/Stratis.Bitcoin.Features.PoA.csproj
index 2d2a061c37..15faa5571b 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Stratis.Bitcoin.Features.PoA.csproj
+++ b/src/Stratis.Bitcoin.Features.PoA/Stratis.Bitcoin.Features.PoA.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
index 41f4ae13c5..db647bb47f 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/FederationController.cs
@@ -4,8 +4,9 @@
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.PoA.Models;
using Stratis.Bitcoin.Utilities.JsonErrors;
@@ -45,7 +46,7 @@ public FederationController(
}
///
- /// Signals the node to rebuild the federation via cleabning and rebuilding executed polls.
+ /// Signals the node to rebuild the federation via cleaning and rebuilding executed polls.
/// This will be done via writing a flag to the .conf file so that on startup it be executed.
///
/// See response codes
@@ -65,7 +66,7 @@ public IActionResult Reconstruct()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -126,12 +127,10 @@ public IActionResult GetCurrentMemberInfo()
federationMemberModel.PollWillFinishInBlocks = 0;
else
federationMemberModel.PollWillFinishInBlocks = (poll.PollVotedInFavorBlockData.Height + this.network.Consensus.MaxReorgLength) - chainTip.Height;
- }
- // Has the poll executed?
- poll = this.votingManager.GetExecutedPolls().MemberPolls().OrderByDescending(p => p.PollExecutedBlockData.Height).FirstOrDefault(p => this.votingManager.GetMemberVotedOn(p.VotingData).PubKey == this.federationManager.CurrentFederationKey.PubKey);
- if (poll != null)
- federationMemberModel.PollExecutedBlockHeight = poll.PollExecutedBlockData.Height;
+ // Has the poll executed?
+ federationMemberModel.PollExecutedBlockHeight = poll.PollExecutedBlockData?.Height;
+ }
federationMemberModel.RewardEstimatePerBlock = 9d / this.federationManager.GetFederationMembers().Count;
@@ -141,7 +140,7 @@ public IActionResult GetCurrentMemberInfo()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -181,7 +180,7 @@ public IActionResult GetMembers()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -208,7 +207,7 @@ public IActionResult GetPubkeyAtHeight([FromQuery(Name = "blockHeight")] int blo
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -241,7 +240,7 @@ public IActionResult GetFederationAtHeight([FromQuery(Name = "blockHeight")] int
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestEncoder.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestEncoder.cs
index a229421249..c72aa1d5d3 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestEncoder.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestEncoder.cs
@@ -1,8 +1,9 @@
using System;
using System.IO;
using DBreeze.Utils;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.PoA;
namespace Stratis.Bitcoin.PoA.Features.Voting
@@ -18,7 +19,9 @@ public JoinFederationRequestEncoder()
this.logger = LogManager.GetCurrentClassLogger();
}
- /// Encodes voting request data.
+ /// Encodes voting request data as an array of bytes.
+ /// See .
+ /// An array of bytes encoding the voting request.
public byte[] Encode(JoinFederationRequest votingRequestData)
{
using (var memoryStream = new MemoryStream())
@@ -32,8 +35,10 @@ public byte[] Encode(JoinFederationRequest votingRequestData)
}
}
- /// Decodes the voting request.
+ /// Decodes a voting request that had previously been encoded as an array of bytes.
/// Thrown in case voting data format is invalid.
+ /// An array of bytes encoding the voting request.
+ /// The .
public JoinFederationRequest Decode(byte[] votingRequestDataBytes)
{
try
@@ -55,7 +60,7 @@ public JoinFederationRequest Decode(byte[] votingRequestDataBytes)
if (deserializeStream.ProcessedBytes != votingRequestDataBytes.Length)
{
- this.logger.Trace("(-)[INVALID_SIZE]");
+ this.logger.LogTrace("(-)[INVALID_SIZE]");
PoAConsensusErrors.VotingRequestInvalidFormat.Throw();
}
@@ -64,8 +69,8 @@ public JoinFederationRequest Decode(byte[] votingRequestDataBytes)
}
catch (Exception e)
{
- this.logger.Debug("Exception during deserialization: '{0}'.", e.ToString());
- this.logger.Trace("(-)[DESERIALIZING_EXCEPTION]");
+ this.logger.LogDebug("Exception during deserialization: '{0}'.", e.ToString());
+ this.logger.LogTrace("(-)[DESERIALIZING_EXCEPTION]");
PoAConsensusErrors.VotingRequestInvalidFormat.Throw();
return null;
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestService.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestService.cs
index d3276e7b3f..1c5f8bf839 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestService.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/JoinFederationRequestService.cs
@@ -49,6 +49,23 @@ public JoinFederationRequestService(ICounterChainSettings counterChainSettings,
this.votingManager = votingManager;
}
+ public static byte[] GetFederationMemberBytes(JoinFederationRequest joinRequest, Network network, Network counterChainNetwork)
+ {
+ Script collateralScript = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(joinRequest.CollateralMainchainAddress);
+ BitcoinAddress bitcoinAddress = collateralScript.GetDestinationAddress(counterChainNetwork);
+ var collateralFederationMember = new CollateralFederationMember(joinRequest.PubKey, false, joinRequest.CollateralAmount, bitcoinAddress.ToString());
+
+ return (network.Consensus.ConsensusFactory as CollateralPoAConsensusFactory).SerializeFederationMember(collateralFederationMember);
+ }
+
+ public static void SetLastRemovalEventId(JoinFederationRequest joinRequest, byte[] federationMemberBytes, VotingManager votingManager)
+ {
+ Poll poll = votingManager.GetExecutedPolls().OrderByDescending(p => p.PollExecutedBlockData.Height).FirstOrDefault(x =>
+ x.VotingData.Key == VoteKey.KickFederationMember && x.VotingData.Data.SequenceEqual(federationMemberBytes));
+
+ joinRequest.RemovalEventId = (poll == null) ? Guid.Empty : new Guid(poll.PollExecutedBlockData.Hash.ToBytes().TakeLast(16).ToArray());
+ }
+
public async Task JoinFederationAsync(JoinFederationRequestModel request, CancellationToken cancellationToken)
{
// Wait until the node is synced before joining.
@@ -74,13 +91,7 @@ public async Task JoinFederationAsync(JoinFederationRequestModel request
var joinRequest = new JoinFederationRequest(minerKey.PubKey, new Money(expectedCollateralAmount, MoneyUnit.BTC), addressKey);
// Populate the RemovalEventId.
- var collateralFederationMember = new CollateralFederationMember(minerKey.PubKey, false, joinRequest.CollateralAmount, request.CollateralAddress);
-
- byte[] federationMemberBytes = (this.network.Consensus.ConsensusFactory as CollateralPoAConsensusFactory).SerializeFederationMember(collateralFederationMember);
- Poll poll = this.votingManager.GetApprovedPolls().FirstOrDefault(x => x.IsExecuted &&
- x.VotingData.Key == VoteKey.KickFederationMember && x.VotingData.Data.SequenceEqual(federationMemberBytes));
-
- joinRequest.RemovalEventId = (poll == null) ? Guid.Empty : new Guid(poll.PollExecutedBlockData.Hash.ToBytes().TakeLast(16).ToArray());
+ SetLastRemovalEventId(joinRequest, GetFederationMemberBytes(joinRequest, this.network, this.counterChainSettings.CounterChainNetwork), this.votingManager);
// Get the signature by calling the counter-chain "signmessage" API.
var signMessageRequest = new SignMessageRequest()
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/PollResultExecutor.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/PollResultExecutor.cs
index 644ef6fc7f..2e10360f99 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/PollResultExecutor.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/PollResultExecutor.cs
@@ -7,12 +7,16 @@ namespace Stratis.Bitcoin.Features.PoA.Voting
public interface IPollResultExecutor
{
/// Applies effect of .
+ /// See .
void ApplyChange(VotingData data);
/// Reverts effect of .
+ /// See .
void RevertChange(VotingData data);
/// Converts to a human readable format.
+ /// See .
+ /// The string representation of the .
string ConvertToString(VotingData data);
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/PollsCollection.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/PollsCollection.cs
index 1c2880cf69..209d61253c 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/PollsCollection.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/PollsCollection.cs
@@ -1,6 +1,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
-using NLog;
+using Microsoft.Extensions.Logging;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.PoA.Voting
@@ -39,7 +40,7 @@ public void Add(Poll poll)
{
if (this.polls.Contains(poll))
{
- this.logger.Warn("The poll already exists: '{0}'.", poll);
+ this.logger.LogWarning("The poll already exists: '{0}'.", poll);
return;
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/PollsRepository.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/PollsRepository.cs
index 38b4e877e5..000a263c9e 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/PollsRepository.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/PollsRepository.cs
@@ -5,9 +5,10 @@
using DBreeze;
using DBreeze.DataTypes;
using DBreeze.Utils;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using Stratis.Bitcoin.Configuration;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Utilities;
namespace Stratis.Bitcoin.Features.PoA.Voting
@@ -65,7 +66,7 @@ public void Initialize()
var uniquePolls = new HashSet(polls);
if (uniquePolls.Count != polls.Count)
{
- this.logger.Warn("The polls repository contains {0} duplicate polls, it will be rebuilt.", polls.Count - uniquePolls.Count);
+ this.logger.LogWarning("The polls repository contains {0} duplicate polls, it will be rebuilt.", polls.Count - uniquePolls.Count);
this.ResetLocked(transaction);
transaction.Commit();
@@ -76,7 +77,7 @@ public void Initialize()
Row rowTip = transaction.Select(DataTable, RepositoryTipKey);
if (!rowTip.Exists)
{
- this.logger.Info("The polls repository tip is unknown, it will be rebuilt.");
+ this.logger.LogInformation("The polls repository tip is unknown, it will be rebuilt.");
this.ResetLocked(transaction);
transaction.Commit();
return;
@@ -89,11 +90,11 @@ public void Initialize()
if (chainedHeaderTip != null)
{
this.highestPollId = (polls.Count > 0) ? polls.Max(p => p.Id) : -1;
- this.logger.Info("Polls repository tip exists on chain; initializing at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
+ this.logger.LogInformation("Polls repository tip exists on chain; initializing at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
return;
}
- this.logger.Info("The polls repository tip {0} was not found in the consensus chain, determining fork.", this.CurrentTip);
+ this.logger.LogInformation("The polls repository tip {0} was not found in the consensus chain, determining fork.", this.CurrentTip);
// The polls repository tip could not be found in the chain.
// Look at all other known hash/height pairs to find something in common with the consensus chain.
@@ -111,7 +112,7 @@ public void Initialize()
if (maxGoodHeight == -1)
{
- this.logger.Info("No common blocks found; the repo will be rebuilt from scratch.");
+ this.logger.LogInformation("No common blocks found; the repo will be rebuilt from scratch.");
this.ResetLocked(transaction);
transaction.Commit();
return;
@@ -119,7 +120,7 @@ public void Initialize()
this.CurrentTip = new HashHeightPair(this.chainIndexer.GetHeader(maxGoodHeight));
- this.logger.Info("Common block found at height {0}; the repo will be rebuilt from there.", this.CurrentTip.Height);
+ this.logger.LogInformation("Common block found at height {0}; the repo will be rebuilt from there.", this.CurrentTip.Height);
// Trim polls to tip.
HashSet pollsToDelete = new HashSet();
@@ -128,7 +129,7 @@ public void Initialize()
if (poll.PollStartBlockData.Height > this.CurrentTip.Height)
{
pollsToDelete.Add(poll);
- this.logger.Debug("Poll {0} will be deleted.", poll.Id);
+ this.logger.LogDebug("Poll {0} will be deleted.", poll.Id);
continue;
}
@@ -156,7 +157,7 @@ public void Initialize()
// if so un-expire it.
if (poll.IsExpired && !IsPollExpiredAt(poll, chainedHeaderTip, this.network))
{
- this.logger.Debug("Un-expiring poll {0}.", poll.Id);
+ this.logger.LogDebug("Un-expiring poll {0}.", poll.Id);
poll.IsExpired = false;
modified = true;
@@ -170,11 +171,11 @@ public void Initialize()
SaveCurrentTip(transaction, this.CurrentTip);
transaction.Commit();
- this.logger.Info("Polls repository initialized at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
+ this.logger.LogInformation("Polls repository initialized at height {0}; highest poll id: {1}.", this.CurrentTip.Height, this.highestPollId);
}
catch (Exception err) when (err.Message == "No more byte to read")
{
- this.logger.Warn("There was an error reading the polls repository, it will be rebuild.");
+ this.logger.LogWarning("There was an error reading the polls repository, it will be rebuild.");
this.ResetLocked(transaction);
transaction.Commit();
}
@@ -219,6 +220,7 @@ public void SaveCurrentTip(DBreeze.Transactions.Transaction transaction, HashHei
}
/// Provides Id of the most recently added poll.
+ /// Id of the most recently added poll.
public int GetHighestPollId()
{
return this.highestPollId;
@@ -233,6 +235,8 @@ public void Synchronous(Action action)
}
/// Removes polls for the provided ids.
+ /// See .
+ /// The ids of the polls to remove.
public void DeletePollsAndSetHighestPollId(DBreeze.Transactions.Transaction transaction, params int[] ids)
{
lock (this.lockObject)
@@ -248,6 +252,8 @@ public void DeletePollsAndSetHighestPollId(DBreeze.Transactions.Transaction tran
}
/// Removes polls under provided ids.
+ /// See .
+ /// The ids of the polls to remove.
public void RemovePolls(DBreeze.Transactions.Transaction transaction, params int[] ids)
{
lock (this.lockObject)
@@ -294,7 +300,9 @@ public void WithTransaction(Action action)
}
}
- /// Adds new poll.
+ /// Adds new polls.
+ /// See .
+ /// The polls to add.
public void AddPolls(DBreeze.Transactions.Transaction transaction, params Poll[] polls)
{
lock (this.lockObject)
@@ -314,6 +322,8 @@ public void AddPolls(DBreeze.Transactions.Transaction transaction, params Poll[]
}
/// Updates existing poll.
+ /// See .
+ /// The poll to update.
public void UpdatePoll(DBreeze.Transactions.Transaction transaction, Poll poll)
{
lock (this.lockObject)
@@ -325,6 +335,9 @@ public void UpdatePoll(DBreeze.Transactions.Transaction transaction, Poll poll)
}
/// Loads polls under provided keys from the database.
+ /// See .
+ /// The ids of the polls to retrieve.
+ /// A list of retrieved entries.
public List GetPolls(DBreeze.Transactions.Transaction transaction, params int[] ids)
{
lock (this.lockObject)
@@ -348,6 +361,8 @@ public List GetPolls(DBreeze.Transactions.Transaction transaction, params
}
/// Loads all polls from the database.
+ /// See .
+ /// A list of retrieved entries.
public List GetAllPolls(DBreeze.Transactions.Transaction transaction)
{
lock (this.lockObject)
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingController.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingController.cs
index 861ee078c9..9f8fa1bcaa 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingController.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingController.cs
@@ -3,8 +3,9 @@
using System.Linq;
using System.Net;
using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.Features.PoA.Models;
using Stratis.Bitcoin.Features.Wallet.Models;
using Stratis.Bitcoin.Utilities;
@@ -72,7 +73,7 @@ public IActionResult GetPollsRepositoryTip()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -80,6 +81,8 @@ public IActionResult GetPollsRepositoryTip()
///
/// Retrieves a list of pending or "active" polls.
///
+ /// See 0 = Kick Member, 1 - Add Member, 2 = Whitelist Hash, 3 = Remove Hash
+ /// The public key of the member being voted on (in hexadecimal). If omitted or empty then all polls are returned.
/// Active polls
/// Returns the active polls
/// Unexpected exception occurred
@@ -101,7 +104,7 @@ public IActionResult GetPendingPolls([FromQuery] VoteKey voteType, [FromQuery] s
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -109,6 +112,8 @@ public IActionResult GetPendingPolls([FromQuery] VoteKey voteType, [FromQuery] s
///
/// Retrieves a list of finished polls.
///
+ /// See 0 = Kick Member, 1 - Add Member, 2 = Whitelist Hash, 3 = Remove Hash
+ /// The public key of the member being voted on (in hexadecimal). If omitted or empty then all polls are returned.
/// Finished polls
/// Returns the finished polls
/// Unexpected exception occurred
@@ -130,7 +135,7 @@ public IActionResult GetFinishedPolls([FromQuery] VoteKey voteType, [FromQuery]
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -138,6 +143,8 @@ public IActionResult GetFinishedPolls([FromQuery] VoteKey voteType, [FromQuery]
///
/// Retrieves a list of executed polls.
///
+ /// See 0 = Kick Member, 1 - Add Member, 2 = Whitelist Hash, 3 = Remove Hash
+ /// The public key of the member being voted on (in hexadecimal). If omitted or empty then all polls are returned.
/// Finished polls
/// Returns the finished polls
/// Unexpected exception occurred
@@ -159,7 +166,7 @@ public IActionResult GetExecutedPolls([FromQuery] VoteKey voteType, [FromQuery]
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -185,7 +192,7 @@ public IActionResult GetExpiredPollsMembers()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -211,7 +218,7 @@ public IActionResult GetExpiredPollsWhitelist()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -236,7 +243,7 @@ public IActionResult GetWhitelistedHashes()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -244,6 +251,7 @@ public IActionResult GetWhitelistedHashes()
///
/// Votes to add a hash to the whitelist.
///
+ /// See .
/// The HTTP response
/// Voted to add hash to whitelist
/// Invalid request, node is not a federation member, or an unexpected exception occurred
@@ -261,6 +269,7 @@ public IActionResult VoteWhitelistHash([FromBody] HashModel request)
///
/// Votes to remove a hash from the whitelist.
///
+ /// See .
/// The HTTP response
/// Voted to remove hash from whitelist
/// Invalid request, node is not a federation member, or an unexpected exception occurred
@@ -299,7 +308,7 @@ private IActionResult VoteWhitelistRemoveHashMember(HashModel request, bool whit
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "There was a problem executing a command.", e.ToString());
}
}
@@ -326,7 +335,7 @@ public IActionResult GetScheduledVotes()
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString());
}
}
@@ -334,6 +343,7 @@ public IActionResult GetScheduledVotes()
///
/// Votes to kick/remove a member from the federation.
///
+ /// See .
/// The HTTP response
/// Voted to remove a member from the federation.
/// Invalid request, node is not a federation member, or an unexpected exception occurred
@@ -376,7 +386,7 @@ public IActionResult VoteKickFederationMember([FromBody] KickFederationMemberMod
}
catch (Exception e)
{
- this.logger.Error("Exception occurred: {0}", e.ToString());
+ this.logger.LogError("Exception occurred: {0}", e.ToString());
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, "There was a problem executing a vote to be scheduled.", e.ToString());
}
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingDataEncoder.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingDataEncoder.cs
index 3f5e26e72e..9dabf40952 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingDataEncoder.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingDataEncoder.cs
@@ -2,8 +2,9 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
+using Stratis.Bitcoin.Configuration.Logging;
namespace Stratis.Bitcoin.Features.PoA.Voting
{
@@ -29,7 +30,7 @@ public List Decode(byte[] votingDataBytes)
{
if (votingDataBytes.Length > VotingDataMaxSerializedSize)
{
- this.logger.Trace("(-)[INVALID_SIZE]");
+ this.logger.LogTrace("(-)[INVALID_SIZE]");
PoAConsensusErrors.VotingDataInvalidFormat.Throw();
}
@@ -46,8 +47,8 @@ public List Decode(byte[] votingDataBytes)
}
catch (Exception e)
{
- this.logger.Debug("Exception during deserialization: '{0}'.", e.ToString());
- this.logger.Trace("(-)[DESERIALIZING_EXCEPTION]");
+ this.logger.LogDebug("Exception during deserialization: '{0}'.", e.ToString());
+ this.logger.LogTrace("(-)[DESERIALIZING_EXCEPTION]");
PoAConsensusErrors.VotingDataInvalidFormat.Throw();
return null;
@@ -93,7 +94,7 @@ public byte[] ExtractRawVotingData(Transaction tx)
if (votingData != null)
{
- this.logger.Trace("(-)[TOO_MANY_VOTING_OUTPUTS]");
+ this.logger.LogTrace("(-)[TOO_MANY_VOTING_OUTPUTS]");
PoAConsensusErrors.TooManyVotingOutputs.Throw();
}
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingManager.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingManager.cs
index 72fb813e61..a64c30c5ac 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/VotingManager.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/VotingManager.cs
@@ -3,8 +3,8 @@
using System.Linq;
using System.Text;
using ConcurrentCollections;
+using Microsoft.Extensions.Logging;
using NBitcoin;
-using NLog;
using Stratis.Bitcoin.Configuration;
using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.EventBus;
@@ -114,10 +114,11 @@ public void Initialize(IFederationHistory federationHistory, IIdleFederationMemb
this.isInitialized = true;
- this.logger.Debug("VotingManager initialized.");
+ this.logger.LogDebug("VotingManager initialized.");
}
/// Schedules a vote for the next time when the block will be mined.
+ /// See .
/// Thrown in case caller is not a federation member.
public void ScheduleVote(VotingData votingData)
{
@@ -125,7 +126,7 @@ public void ScheduleVote(VotingData votingData)
if (!this.federationManager.IsFederationMember)
{
- this.logger.Trace("(-)[NOT_FED_MEMBER]");
+ this.logger.LogTrace("(-)[NOT_FED_MEMBER]");
throw new InvalidOperationException("Not a federation member!");
}
@@ -137,10 +138,11 @@ public void ScheduleVote(VotingData votingData)
this.SanitizeScheduledPollsLocked();
}
- this.logger.Debug("Vote was scheduled with key: {0}.", votingData.Key);
+ this.logger.LogDebug("Vote was scheduled with key: {0}.", votingData.Key);
}
/// Provides a copy of scheduled voting data.
+ /// A list of .
public List GetScheduledVotes()
{
this.EnsureInitialized();
@@ -154,6 +156,7 @@ public List GetScheduledVotes()
}
/// Provides scheduled voting data and removes all items that were provided.
+ /// A list of .
/// Used by miner.
public List GetAndCleanScheduledVotes()
{
@@ -168,7 +171,7 @@ public List GetAndCleanScheduledVotes()
this.scheduledVotingData = new List();
if (votingData.Count > 0)
- this.logger.Debug("{0} scheduled votes were taken.", votingData.Count);
+ this.logger.LogDebug("{0} scheduled votes were taken.", votingData.Count);
return votingData;
}
@@ -205,6 +208,7 @@ bool IsValid(VotingData currentScheduledData)
}
/// Provides a collection of polls that are currently active.
+ /// A list of items.
public List GetPendingPolls()
{
this.EnsureInitialized();
@@ -217,6 +221,7 @@ public List GetPendingPolls()
}
/// Provides a collection of polls that are approved but not executed yet.
+ /// A list of items.
public List GetApprovedPolls()
{
this.EnsureInitialized();
@@ -228,6 +233,7 @@ public List GetApprovedPolls()
}
/// Provides a collection of polls that are approved and their results applied.
+ /// A list of items.
public List GetExecutedPolls()
{
this.EnsureInitialized();
@@ -239,6 +245,7 @@ public List GetExecutedPolls()
}
/// Provides a collection of polls that are expired.
+ /// A list of items.
public List GetExpiredPolls()
{
this.EnsureInitialized();
@@ -250,8 +257,11 @@ public List GetExpiredPolls()
}
///
- /// Tells us whether we have already voted to boot a federation member.
+ /// Tells us whether we have already voted on this federation member.
///
+ /// See .
+ /// The bytes to compare against.
+ /// True if we have already voted or false otherwise.
public bool AlreadyVotingFor(VoteKey voteKey, byte[] federationMemberBytes)
{
List approvedPolls = this.GetApprovedPolls();
@@ -306,7 +316,7 @@ public List GetFederationFromExecutedPolls()
{
if (federationMember is CollateralFederationMember colMember2 && federation.IsCollateralAddressRegistered(colMember2.CollateralMainchainAddress))
{
- this.logger.Debug("Not adding member '{0}' with duplicate collateral address '{1}'.", federationMember.PubKey.ToHex(), colMember2.CollateralMainchainAddress);
+ this.logger.LogDebug("Not adding member '{0}' with duplicate collateral address '{1}'.", federationMember.PubKey.ToHex(), colMember2.CollateralMainchainAddress);
continue;
}
@@ -404,7 +414,7 @@ public List GetModifiedFederation(ChainedHeader chainedHeader
{
if (modifiedFederation.IsCollateralAddressRegistered(collateralFederationMember.CollateralMainchainAddress))
{
- this.logger.Debug("Not adding member '{0}' with duplicate collateral address '{1}'.", collateralFederationMember.PubKey.ToHex(), collateralFederationMember.CollateralMainchainAddress);
+ this.logger.LogDebug("Not adding member '{0}' with duplicate collateral address '{1}'.", collateralFederationMember.PubKey.ToHex(), collateralFederationMember.CollateralMainchainAddress);
continue;
}
@@ -466,7 +476,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
foreach (Poll poll in this.GetPendingPolls().Where(p => PollsRepository.IsPollExpiredAt(p, chBlock.ChainedHeader, this.network as PoANetwork)).ToList())
{
- this.logger.Debug("Expiring poll '{0}'.", poll);
+ this.logger.LogDebug("Expiring poll '{0}'.", poll);
// Flag the poll as expired. The "PollVotedInFavorBlockData" will always be null at this point due to the "GetPendingPolls" filter above.
// The value of the hash is not significant but we set it to a non-zero value to prevent the field from being de-serialized as null.
@@ -481,7 +491,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
if (poll.IsExpired || chBlock.ChainedHeader.Height != (poll.PollVotedInFavorBlockData.Height + this.network.Consensus.MaxReorgLength))
continue;
- this.logger.Debug("Applying poll '{0}'.", poll);
+ this.logger.LogDebug("Applying poll '{0}'.", poll);
this.pollResultExecutor.ApplyChange(poll.VotingData);
poll.PollExecutedBlockData = new HashHeightPair(chBlock.ChainedHeader);
@@ -504,8 +514,8 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
IFederationMember member = this.federationHistory.GetFederationMemberForBlock(chBlock.ChainedHeader);
if (member == null)
{
- this.logger.Error("The block was mined by a non-federation-member!");
- this.logger.Trace("(-)[ALIEN_BLOCK]");
+ this.logger.LogError("The block was mined by a non-federation-member!");
+ this.logger.LogTrace("(-)[ALIEN_BLOCK]");
this.PollsRepository.SaveCurrentTip(pollsRepositoryModified ? transaction : null, chBlock.ChainedHeader);
return;
@@ -517,7 +527,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
List votingDataList = this.votingDataEncoder.Decode(rawVotingData);
- this.logger.Debug("Applying {0} voting data items included in a block by '{1}'.", votingDataList.Count, fedMemberKeyHex);
+ this.logger.LogDebug("Applying {0} voting data items included in a block by '{1}'.", votingDataList.Count, fedMemberKeyHex);
lock (this.locker)
{
@@ -556,7 +566,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
this.PollsRepository.AddPolls(transaction, poll);
pollsRepositoryModified = true;
- this.logger.Debug("New poll was created: '{0}'.", poll);
+ this.logger.LogDebug("New poll was created: '{0}'.", poll);
});
}
else if (!poll.PubKeysHexVotedInFavor.Any(v => v.PubKey == fedMemberKeyHex))
@@ -565,11 +575,11 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
this.PollsRepository.UpdatePoll(transaction, poll);
pollsRepositoryModified = true;
- this.logger.Debug("Voted on existing poll: '{0}'.", poll);
+ this.logger.LogDebug("Voted on existing poll: '{0}'.", poll);
}
else
{
- this.logger.Debug("Fed member '{0}' already voted for this poll. Ignoring his vote. Poll: '{1}'.", fedMemberKeyHex, poll);
+ this.logger.LogDebug("Fed member '{0}' already voted for this poll. Ignoring his vote. Poll: '{1}'.", fedMemberKeyHex, poll);
}
List modifiedFederation = this.federationManager.GetFederationMembers();
@@ -586,7 +596,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
chainedHeader = this.chainIndexer.GetHeader(poll.PollStartBlockData.Hash);
if (chainedHeader == null)
{
- this.logger.Warn("Couldn't retrieve header for block at height-hash: {0}-{1}.", poll.PollStartBlockData.Height, poll.PollStartBlockData.Hash?.ToString());
+ this.logger.LogWarning("Couldn't retrieve header for block at height-hash: {0}-{1}.", poll.PollStartBlockData.Height, poll.PollStartBlockData.Hash?.ToString());
Guard.NotNull(chainedHeader, nameof(chainedHeader));
Guard.NotNull(chainedHeader.Header, nameof(chainedHeader.Header));
@@ -608,7 +618,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
int requiredVotesCount = (fedMembersHex.Count / 2) + 1;
- this.logger.Debug("Fed members count: {0}, valid votes count: {1}, required votes count: {2}.", fedMembersHex.Count, validVotesCount, requiredVotesCount);
+ this.logger.LogDebug("Fed members count: {0}, valid votes count: {1}, required votes count: {2}.", fedMembersHex.Count, validVotesCount, requiredVotesCount);
if (validVotesCount < requiredVotesCount)
continue;
@@ -626,7 +636,7 @@ private void ProcessBlock(DBreeze.Transactions.Transaction transaction, ChainedH
}
catch (Exception ex)
{
- this.logger.Error(ex, ex.ToString());
+ this.logger.LogError(ex, ex.ToString());
throw;
}
finally
@@ -646,7 +656,7 @@ private void UnProcessBlock(DBreeze.Transactions.Transaction transaction, Chaine
{
foreach (Poll poll in this.polls.Where(x => !x.IsPending && x.PollExecutedBlockData?.Hash == chBlock.ChainedHeader.HashBlock).ToList())
{
- this.logger.Debug("Reverting poll execution '{0}'.", poll);
+ this.logger.LogDebug("Reverting poll execution '{0}'.", poll);
this.pollResultExecutor.RevertChange(poll.VotingData);
poll.PollExecutedBlockData = null;
@@ -656,7 +666,7 @@ private void UnProcessBlock(DBreeze.Transactions.Transaction transaction, Chaine
foreach (Poll poll in this.polls.Where(x => x.IsExpired && !PollsRepository.IsPollExpiredAt(x, chBlock.ChainedHeader.Previous, this.network as PoANetwork)).ToList())
{
- this.logger.Debug("Reverting poll expiry '{0}'.", poll);
+ this.logger.LogDebug("Reverting poll expiry '{0}'.", poll);
// Revert back to null as this field would have been when the poll was expired.
poll.IsExpired = false;
@@ -673,7 +683,7 @@ private void UnProcessBlock(DBreeze.Transactions.Transaction transaction, Chaine
if (rawVotingData == null)
{
- this.logger.Trace("(-)[NO_VOTING_DATA]");
+ this.logger.LogTrace("(-)[NO_VOTING_DATA]");
this.PollsRepository.SaveCurrentTip(pollsRepositoryModified ? transaction : null, chBlock.ChainedHeader.Previous);
return;
@@ -698,7 +708,7 @@ private void UnProcessBlock(DBreeze.Transactions.Transaction transaction, Chaine
targetPoll = this.polls.Last(x => x.VotingData == votingData);
}
- this.logger.Debug("Reverting poll voting in favor: '{0}'.", targetPoll);
+ this.logger.LogDebug("Reverting poll voting in favor: '{0}'.", targetPoll);
if (targetPoll.PollVotedInFavorBlockData == new HashHeightPair(chBlock.ChainedHeader))
{
@@ -722,7 +732,7 @@ private void UnProcessBlock(DBreeze.Transactions.Transaction transaction, Chaine
this.PollsRepository.RemovePolls(transaction, targetPoll.Id);
pollsRepositoryModified = true;
- this.logger.Debug("Poll with Id {0} was removed.", targetPoll.Id);
+ this.logger.LogDebug("Poll with Id {0} was removed.", targetPoll.Id);
}
}
}
@@ -809,7 +819,7 @@ internal bool Synchronize(ChainedHeader newTip)
{
if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
{
- this.logger.Trace("(-)[NODE_DISPOSED]");
+ this.logger.LogTrace("(-)[NODE_DISPOSED]");
this.PollsRepository.SaveCurrentTip(currentTransaction);
currentTransaction.Commit();
currentTransaction.Dispose();
@@ -827,7 +837,7 @@ internal bool Synchronize(ChainedHeader newTip)
var progress = (int)((decimal)header.Height / this.chainIndexer.Tip.Height * 100);
var progressString = $"Synchronizing voting data at height {header.Height} / {this.chainIndexer.Tip.Height} ({progress} %).";
- this.logger.Info(progressString);
+ this.logger.LogInformation(progressString);
this.signals.Publish(new FullNodeEvent() { Message = progressString, State = FullNodeState.Initializing.ToString() });
this.PollsRepository.SaveCurrentTip(currentTransaction);
diff --git a/src/Stratis.Bitcoin.Features.PoA/Voting/WhitelistedHashesRepository.cs b/src/Stratis.Bitcoin.Features.PoA/Voting/WhitelistedHashesRepository.cs
index 56771d6a4e..cd8ac70124 100644
--- a/src/Stratis.Bitcoin.Features.PoA/Voting/WhitelistedHashesRepository.cs
+++ b/src/Stratis.Bitcoin.Features.PoA/Voting/WhitelistedHashesRepository.cs
@@ -24,16 +24,18 @@ public WhitelistedHashesRepository(ILoggerFactory loggerFactory, IKeyValueReposi
this.locker = new object();
this.logger = loggerFactory.CreateLogger(this.GetType().FullName);
- }
- public void Initialize()
- {
+ // Load this before initialize to ensure its available to when the Mempool feature initializes.
lock (this.locker)
{
this.whitelistedHashes = this.kvRepository.LoadValueJson>(dbKey) ?? new List();
}
}
+ public void Initialize()
+ {
+ }
+
private void SaveHashes()
{
lock (this.locker)
diff --git a/src/Stratis.Bitcoin.Features.RPC.Tests/RPCSettingsTest.cs b/src/Stratis.Bitcoin.Features.RPC.Tests/RPCSettingsTest.cs
index 3addf0ffd3..1a3d76af06 100644
--- a/src/Stratis.Bitcoin.Features.RPC.Tests/RPCSettingsTest.cs
+++ b/src/Stratis.Bitcoin.Features.RPC.Tests/RPCSettingsTest.cs
@@ -269,8 +269,8 @@ public void Load_ValidNodeSettings_UpdatesRpcSettingsFromNodeSettings_Empty_User
Assert.True(rpcSettings.Server);
Assert.Equal(1378, rpcSettings.RPCPort);
- Assert.Equal(null, rpcSettings.RpcUser);
- Assert.Equal(null, rpcSettings.RpcPassword);
+ Assert.Null(rpcSettings.RpcUser);
+ Assert.Null(rpcSettings.RpcPassword);
Assert.NotEmpty(rpcSettings.Bind);
Assert.Equal("127.0.0.1:1378", rpcSettings.Bind[0].ToString());
Assert.NotEmpty(rpcSettings.DefaultBindings);
diff --git a/src/Stratis.Bitcoin.Features.RPC/Controllers/FullNodeController.cs b/src/Stratis.Bitcoin.Features.RPC/Controllers/FullNodeController.cs
index fa0c2a1b36..4e9887ee3c 100644
--- a/src/Stratis.Bitcoin.Features.RPC/Controllers/FullNodeController.cs
+++ b/src/Stratis.Bitcoin.Features.RPC/Controllers/FullNodeController.cs
@@ -99,6 +99,7 @@ public FullNodeController(
///
/// Stops the full node.
///
+ /// The asynchronous task.
[ActionName("stop")]
[ActionDescription("Stops the full node.")]
public Task Stop()
@@ -254,7 +255,7 @@ public async Task GetTxOutAsync(string txid, uint vout, bool incl
/// The hex-encoded merkle proof.
[ActionName("gettxoutproof")]
[ActionDescription("Checks if transactions are within block. Returns a merkle proof of transaction inclusion.")]
- public async Task GetTxOutProofAsync(string[] txids, string blockhash = "")
+ public Task GetTxOutProofAsync(string[] txids, string blockhash = "")
{
List transactionIds = txids.Select(txString => uint256.Parse(txString)).ToList();
@@ -306,7 +307,7 @@ public async Task GetTxOutProofAsync(string[] txids, string blockha
var result = new MerkleBlock(block.Block, transactionIds.ToArray());
- return result;
+ return Task.FromResult(result);
}
///
diff --git a/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj b/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj
index 4d74f02c2f..c6188bec38 100644
--- a/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj
+++ b/src/Stratis.Bitcoin.Features.RPC/Stratis.Bitcoin.Features.RPC.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.SignalR/EventSubscriptionService.cs b/src/Stratis.Bitcoin.Features.SignalR/EventSubscriptionService.cs
index cd984367bd..b5c0ea48cb 100644
--- a/src/Stratis.Bitcoin.Features.SignalR/EventSubscriptionService.cs
+++ b/src/Stratis.Bitcoin.Features.SignalR/EventSubscriptionService.cs
@@ -2,7 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
-using NLog;
+using Microsoft.Extensions.Logging;
+using Stratis.Bitcoin.Configuration.Logging;
using Stratis.Bitcoin.EventBus;
using Stratis.Bitcoin.Signals;
@@ -35,7 +36,7 @@ public void Init()
{
foreach (IClientEvent eventToHandle in this.options.EventsToHandle)
{
- this.logger.Debug("Create subscription for {0}", eventToHandle.NodeEventType);
+ this.logger.LogDebug("Create subscription for {0}", eventToHandle.NodeEventType);
async Task callback(EventBase eventBase)
{
diff --git a/src/Stratis.Bitcoin.Features.SignalR/EventsHub.cs b/src/Stratis.Bitcoin.Features.SignalR/EventsHub.cs
index 3d3bc07c3a..dfce4fa0df 100644
--- a/src/Stratis.Bitcoin.Features.SignalR/EventsHub.cs
+++ b/src/Stratis.Bitcoin.Features.SignalR/EventsHub.cs
@@ -3,10 +3,14 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
-using NLog;
+using Microsoft.Extensions.Logging;
+using Stratis.Bitcoin.Configuration.Logging;
namespace Stratis.Bitcoin.Features.SignalR
{
+ ///
+ /// SignalR message.
+ ///
public class SignalRMessageArgs
{
public string Target { get; set; }
@@ -30,17 +34,18 @@ public EventsHub()
public override Task OnConnectedAsync()
{
- this.logger.Debug("New client with id {id} connected", this.Context.ConnectionId);
+ this.logger.LogDebug("New client with id {id} connected", this.Context.ConnectionId);
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
- this.logger.Debug("Client with id {id} disconnected", this.Context.ConnectionId);
+ this.logger.LogDebug("Client with id {id} disconnected", this.Context.ConnectionId);
return base.OnDisconnectedAsync(exception);
}
- /// Called using reflection from SignalR
+ /// Called using reflection from SignalR
+ /// See .
public void SendMessage(SignalRMessageArgs message)
{
try
@@ -55,7 +60,7 @@ public void SendMessage(SignalRMessageArgs message)
}
catch (Exception e)
{
- this.logger.Error("Error SendMessage", e);
+ this.logger.LogError("Error SendMessage", e);
}
}
@@ -89,7 +94,7 @@ public async Task SendToClientsAsync(IClientEvent @event)
}
catch (Exception ex)
{
- this.logger.Error(ex, "Error sending to clients");
+ this.logger.LogError(ex, "Error sending to clients");
}
}
}
diff --git a/src/Stratis.Bitcoin.Features.SignalR/SignalRFeature.cs b/src/Stratis.Bitcoin.Features.SignalR/SignalRFeature.cs
index 31fc049147..2a1ec89454 100644
--- a/src/Stratis.Bitcoin.Features.SignalR/SignalRFeature.cs
+++ b/src/Stratis.Bitcoin.Features.SignalR/SignalRFeature.cs
@@ -23,7 +23,7 @@ public class SignalRFeature : FullNodeFeature
private readonly IEnumerable eventBroadcasters;
private readonly IEventsSubscriptionService eventsSubscriptionService;
private IWebHost webHost;
- private readonly ILogger logger;
+ private readonly ILogger logger;
public SignalRFeature(
FullNode fullNode,
diff --git a/src/Stratis.Bitcoin.Features.SignalR/Stratis.Bitcoin.Features.SignalR.csproj b/src/Stratis.Bitcoin.Features.SignalR/Stratis.Bitcoin.Features.SignalR.csproj
index 81f203751b..fb71d5c61c 100644
--- a/src/Stratis.Bitcoin.Features.SignalR/Stratis.Bitcoin.Features.SignalR.csproj
+++ b/src/Stratis.Bitcoin.Features.SignalR/Stratis.Bitcoin.Features.SignalR.csproj
@@ -1,7 +1,7 @@
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis.Features.SignalR
Stratis.Features.SignalR
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/GlobalSuppressions.cs b/src/Stratis.Bitcoin.Features.SmartContracts/GlobalSuppressions.cs
new file mode 100644
index 0000000000..fef494d847
--- /dev/null
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/GlobalSuppressions.cs
@@ -0,0 +1,16 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+
+using System.Diagnostics.CodeAnalysis;
+
+// Temporary fix to reduce the clutter of warnings.
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1615:Element return value must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1611:The documentation for parameter is missing", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1614:Element parameter documentation must have text", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1602:Element items must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1601:Partial elements must be documented", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1616:Element return value documentation must have text", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
+[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1627:The documentation text within the 'exception' tag must not be empty", Justification = "Temporary", Scope = "namespaceanddescendants", Target = "~N:Stratis.Bitcoin.Features.SmartContracts")]
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/ContractSchemaFactory.cs b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/ContractSchemaFactory.cs
index 39f28a3fee..d5058c4e3d 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/ContractSchemaFactory.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/ContractSchemaFactory.cs
@@ -47,7 +47,7 @@ public IDictionary Map(IContractAssembly assembly)
///
/// Maps a type to its schemas.
///
- ///
+ ///
///
public IDictionary Map(IEnumerable methods)
{
@@ -65,7 +65,7 @@ public OpenApiSchema Map(MethodInfo method)
schema.Properties = new Dictionary();
schema.Title = method.Name;
- foreach (var parameter in method.GetParameters())
+ foreach (ParameterInfo parameter in method.GetParameters())
{
// Default to string.
OpenApiSchema paramSchema = PrimitiveTypeMap.ContainsKey(parameter.ParameterType)
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/ContractSwaggerController.cs b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/ContractSwaggerController.cs
index e8d3a8fae2..8bdcaa938a 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/ContractSwaggerController.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/ContractSwaggerController.cs
@@ -50,11 +50,11 @@ public ContractSwaggerController(
/// Dynamically generates a swagger document for the contract at the given address.
///
/// The contract's address.
- /// A model.
+ /// A swagger document serialized as an OpenApi 3.0 json string.
///
[Route("swagger/contracts/{address}")]
[HttpGet]
- public async Task ContractSwaggerDoc(string address)
+ public Task ContractSwaggerDoc(string address)
{
var code = this.stateRepository.GetCode(address.ToUint160(this.network));
@@ -82,7 +82,7 @@ public async Task ContractSwaggerDoc(string address)
// TODO confirm v2/v3
var outputString = doc.Serialize(OpenApiSpecVersion.OpenApi3_0, OpenApiFormat.Json);
- return Ok(outputString);
+ return Task.FromResult(Ok(outputString));
}
///
@@ -92,7 +92,7 @@ public async Task ContractSwaggerDoc(string address)
/// A success response.
[HttpPost]
[Route("api/swagger/contracts")]
- public async Task AddContractToSwagger([FromBody] AddContractRequest address)
+ public Task AddContractToSwagger([FromBody] AddContractRequest address)
{
// Check that the contract exists
var code = this.stateRepository.GetCode(address.Address.ToUint160(this.network));
@@ -111,7 +111,7 @@ public async Task AddContractToSwagger([FromBody] AddContractRequ
this.uiOptions.ConfigObject.Urls = newUrls;
- return Ok();
+ return Task.FromResult(Ok());
}
public class AddContractRequest
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/DynamicContractController.cs b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/DynamicContractController.cs
index baafbda91b..42dc7fd444 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/DynamicContractController.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/DynamicContractController.cs
@@ -62,7 +62,7 @@ public DynamicContractController(
///
[Route("api/contract/{address}/method/{method}")]
[HttpPost]
- public async Task CallMethod([FromRoute] string address, [FromRoute] string method, [FromBody] JObject requestData)
+ public Task CallMethod([FromRoute] string address, [FromRoute] string method, [FromBody] JObject requestData)
{
var contractCode = this.stateRoot.GetCode(address.ToUint160(this.network));
@@ -88,7 +88,7 @@ public async Task CallMethod([FromRoute] string address, [FromRou
BuildCallContractTransactionRequest request = this.MapCallRequest(address, method, methodParams, this.Request.Headers);
// Proxy to the actual SC controller.
- return this.smartContractWalletController.Call(request);
+ return Task.FromResult(this.smartContractWalletController.Call(request));
}
///
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/SmartContractsController.cs b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/SmartContractsController.cs
index cb02a86981..436ad4ba94 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/SmartContractsController.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Controllers/SmartContractsController.cs
@@ -190,7 +190,7 @@ public IActionResult GetStorage([FromQuery] GetStorageRequest request)
if (storageValue == null)
{
- return this.Json(new
+ return this.NotFound(new
{
Message = string.Format("No data at storage with key {0}", request.StorageKey)
});
@@ -300,16 +300,16 @@ public List ReceiptSearch(string contractAddress, string eventN
/// A list of receipts for transactions relating to a specific smart contract and a specific event in that smart contract.
[Route("api/[controller]/receipt-search")]
[HttpGet]
- public async Task ReceiptSearchAPI([FromQuery] string contractAddress, [FromQuery] string eventName, [FromQuery] List topics = null, [FromQuery] int fromBlock = 0, [FromQuery] int? toBlock = null)
+ public Task ReceiptSearchAPI([FromQuery] string contractAddress, [FromQuery] string eventName, [FromQuery] List topics = null, [FromQuery] int fromBlock = 0, [FromQuery] int? toBlock = null)
{
List result = this.smartContractTransactionService.ReceiptSearch(contractAddress, eventName, topics, fromBlock, toBlock);
if (result == null)
{
- return ErrorHelpers.BuildErrorResponse(HttpStatusCode.InternalServerError, "No code exists", $"No contract execution code exists at {contractAddress}");
+ return Task.FromResult(ErrorHelpers.BuildErrorResponse(HttpStatusCode.InternalServerError, "No code exists", $"No contract execution code exists at {contractAddress}"));
}
- return this.Json(result);
+ return Task.FromResult(this.Json(result));
}
///
@@ -366,7 +366,7 @@ public IActionResult BuildCallSmartContractTransaction([FromBody] BuildCallContr
if (!this.ModelState.IsValid)
return ModelStateErrors.BuildErrorResponse(this.ModelState);
- var response = this.smartContractTransactionService.BuildCallTx(request);
+ BuildCallContractTransactionResponse response = this.smartContractTransactionService.BuildCallTx(request);
if (!response.Success)
return ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, response.Message, string.Empty);
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Swagger/ContractSwaggerDocGenerator.cs b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Swagger/ContractSwaggerDocGenerator.cs
index 0459937117..72850e5d80 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Swagger/ContractSwaggerDocGenerator.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/ReflectionExecutor/Swagger/ContractSwaggerDocGenerator.cs
@@ -267,7 +267,6 @@ private List GetCallMetadataHeaderParams()
/// The name of the swagger document to use.
///
///
- ///
///
public OpenApiDocument GetSwagger(string documentName, string host = null, string basePath = null)
{
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs b/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
index 90000154f2..39c3e0acae 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/SmartContractFeature.cs
@@ -18,7 +18,6 @@
using Stratis.Bitcoin.Features.SmartContracts.PoW;
using Stratis.Bitcoin.Features.SmartContracts.ReflectionExecutor.Controllers;
using Stratis.Bitcoin.Features.SmartContracts.Wallet;
-using Stratis.Bitcoin.Interfaces;
using Stratis.Bitcoin.Utilities;
using Stratis.SmartContracts;
using Stratis.SmartContracts.CLR;
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj b/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
index af83e6538e..c558051c57 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/Stratis.Bitcoin.Features.SmartContracts.csproj
@@ -2,7 +2,7 @@
netcoreapp3.1
- 1.1.1.1
+ 1.2.0.0
Stratis Group Ltd.
Stratis.Features.SmartContracts
Stratis.Features.SmartContracts
@@ -10,6 +10,7 @@
bin\Debug\netcoreapp3.1\Stratis.Bitcoin.Features.SmartContracts.xml
+ 1701;1702;1591;1572;1573
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs
index 26255afe8d..f21b591f19 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletController.cs
@@ -121,9 +121,7 @@ public IActionResult GetAccountAddresses(string walletName)
/// The function can be used to query the balance at a smart contract account address
/// supplied by /api/SmartContractWallet/account-addresses.
///
- ///
- /// The address at which to retrieve the balance.
- ///
+ /// The address at which to retrieve the balance.
/// The balance at a specific wallet address in STRAT (or the sidechain coin).
/// Returns address balance
[Route("address-balance")]
@@ -147,8 +145,7 @@ public IActionResult GetAddressBalance(string address)
/// a list of all smart contract interactions for a wallet will be returned.
///
///
- /// The name of the wallet holding the address.
- /// The address to retrieve the history for.
+ /// See .
/// A list of smart contract create and call transaction items as well as transaction items at a specific wallet address.
/// Returns transaction history
/// Invalid request or unexpected exception occurred
@@ -230,7 +227,7 @@ public IActionResult GetHistory(GetHistoryRequest request)
transactionItems.Add(result);
}
- return this.Json(transactionItems.OrderByDescending(x => x.BlockHeight ?? Int32.MaxValue));
+ return this.Json(transactionItems.OrderByDescending(x => x.BlockHeight ?? int.MaxValue));
}
catch (Exception e)
{
diff --git a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletFeature.cs b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletFeature.cs
index b102535cd4..f7bd563423 100644
--- a/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletFeature.cs
+++ b/src/Stratis.Bitcoin.Features.SmartContracts/Wallet/SmartContractWalletFeature.cs
@@ -1,8 +1,8 @@
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
+using Microsoft.Extensions.Logging;
using NBitcoin.Policy;
-using NLog;
using Stratis.Bitcoin.Builder;
using Stratis.Bitcoin.Builder.Feature;
using Stratis.Bitcoin.Configuration.Logging;
@@ -27,7 +27,7 @@ public override Task InitializeAsync()
{
ILogger logger = LogManager.GetCurrentClassLogger();
- logger.Info("Smart Contract Feature Wallet Injected.");
+ logger.LogInformation("Smart Contract Feature Wallet Injected.");
return Task.CompletedTask;
}
diff --git a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs
index b299424ed3..6c21602770 100644
--- a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletControllerTest.cs
@@ -52,7 +52,7 @@ public async Task GenerateMnemonicWithoutParametersCreatesMnemonicWithDefaultsAs
{
var controller = this.GetWalletController();
- IActionResult result = await controller.GenerateMnemonic();
+ IActionResult result = await controller.GenerateMnemonicAsync();
var viewResult = Assert.IsType(result);
@@ -71,7 +71,7 @@ public async Task GenerateMnemonicWithDifferentWordCountCreatesMnemonicWithCorre
{
var controller = this.GetWalletController();
- IActionResult result = await controller.GenerateMnemonic(wordCount: 24);
+ IActionResult result = await controller.GenerateMnemonicAsync(wordCount: 24);
var viewResult = Assert.IsType(result);
@@ -94,7 +94,7 @@ public async Task GenerateMnemonicWithStrangeLanguageCasingReturnsCorrectMnemoni
var controller = this.GetWalletController();
var wordList = (Wordlist)WordLists[language].GetValue(null, null);
- IActionResult result = await controller.GenerateMnemonic(language);
+ IActionResult result = await controller.GenerateMnemonicAsync(language);
var viewResult = Assert.IsType(result);
@@ -110,7 +110,7 @@ public async Task GenerateMnemonicWithUnknownLanguageReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
- IActionResult result = await controller.GenerateMnemonic("invalidlanguage");
+ IActionResult result = await controller.GenerateMnemonicAsync("invalidlanguage");
var errorResult = Assert.IsType(result);
var errorResponse = Assert.IsType(errorResult.Value);
@@ -138,7 +138,7 @@ public async Task CreateWalletSuccessfullyReturnsMnemonicAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Create(new WalletCreationRequest
+ IActionResult result = await controller.CreateAsync(new WalletCreationRequest
{
Name = "myName",
Password = "",
@@ -158,7 +158,7 @@ public async Task CreateWalletWithInvalidModelStateReturnsBadRequestAsync()
controller.ModelState.AddModelError("Name", "Name cannot be empty.");
- IActionResult result = await controller.Create(new WalletCreationRequest
+ IActionResult result = await controller.CreateAsync(new WalletCreationRequest
{
Name = "",
Password = "",
@@ -189,7 +189,7 @@ public async Task CreateWalletWithInvalidOperationExceptionReturnsConflictAsync(
var controller = this.GetWalletController();
- IActionResult result = await controller.Create(new WalletCreationRequest
+ IActionResult result = await controller.CreateAsync(new WalletCreationRequest
{
Name = "myName",
Password = "",
@@ -221,7 +221,7 @@ public async Task CreateWalletWithNotSupportedExceptionExceptionReturnsBadReques
var controller = this.GetWalletController();
- IActionResult result = await controller.Create(new WalletCreationRequest
+ IActionResult result = await controller.CreateAsync(new WalletCreationRequest
{
Name = "myName",
Password = "",
@@ -260,7 +260,7 @@ public async Task RecoverWalletSuccessfullyReturnsWalletModelAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -277,6 +277,7 @@ public async Task RecoverWalletSuccessfullyReturnsWalletModelAsync()
/// and the user recovers a new wallet at height X + Y.
/// The wallet should continue syncing from X without jumpoing forward.
///
+ /// The asynchronous task.
[Fact]
public async Task RecoverWalletWithDatedAfterCurrentSyncHeightDoesNotMoveSyncHeightAsync()
{
@@ -303,7 +304,7 @@ public async Task RecoverWalletWithDatedAfterCurrentSyncHeightDoesNotMoveSyncHei
var controller = this.GetWalletController();
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -324,7 +325,7 @@ public async Task RecoverWalletWithInvalidModelStateReturnsBadRequestAsync()
controller.ModelState.AddModelError("Password", "A password is required.");
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -355,7 +356,7 @@ public async Task RecoverWalletWithInvalidOperationExceptionReturnsConflictAsync
var controller = this.GetWalletController();
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -385,7 +386,7 @@ public async Task RecoverWalletWithFileNotFoundExceptionReturnsNotFoundAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -416,7 +417,7 @@ public async Task RecoverWalletWithExceptionReturnsBadRequestAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Recover(new WalletRecoveryRequest
+ IActionResult result = await controller.RecoverAsync(new WalletRecoveryRequest
{
Name = "myWallet",
Password = "",
@@ -473,7 +474,7 @@ private async Task RecoverWithExtPubAndCheckSuccessfulResponseAsync(string walle
var controller = this.GetWalletController();
- IActionResult result = await controller.RecoverViaExtPubKey(new WalletExtPubRecoveryRequest
+ IActionResult result = await controller.RecoverViaExtPubKeyAsync(new WalletExtPubRecoveryRequest
{
Name = walletName,
ExtPubKey = extPubKey,
@@ -522,7 +523,7 @@ public async Task RecoverWalletWithExtPubDatedAfterCurrentSyncHeightDoesNotMoveS
var controller = this.GetWalletController();
- IActionResult result = await controller.RecoverViaExtPubKey(new WalletExtPubRecoveryRequest
+ IActionResult result = await controller.RecoverViaExtPubKeyAsync(new WalletExtPubRecoveryRequest
{
Name = walletName,
ExtPubKey = extPubKey,
@@ -549,7 +550,7 @@ public async Task LoadWalletSuccessfullyReturnsWalletModelAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Load(new WalletLoadRequest
+ IActionResult result = await controller.LoadAsync(new WalletLoadRequest
{
Name = "myWallet",
Password = ""
@@ -567,7 +568,7 @@ public async Task LoadWalletWithInvalidModelReturnsBadRequestAsync()
controller.ModelState.AddModelError("Password", "A password is required.");
- IActionResult result = await controller.Load(new WalletLoadRequest
+ IActionResult result = await controller.LoadAsync(new WalletLoadRequest
{
Name = "myWallet",
Password = ""
@@ -591,7 +592,7 @@ public async Task LoadWalletWithFileNotFoundExceptionandReturnsNotFoundAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Load(new WalletLoadRequest
+ IActionResult result = await controller.LoadAsync(new WalletLoadRequest
{
Name = "myName",
Password = ""
@@ -617,7 +618,7 @@ public async Task LoadWalletWithSecurityExceptionandReturnsForbiddenAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Load(new WalletLoadRequest
+ IActionResult result = await controller.LoadAsync(new WalletLoadRequest
{
Name = "myName",
Password = ""
@@ -643,7 +644,7 @@ public async Task LoadWalletWithOtherExceptionandReturnsBadRequestAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.Load(new WalletLoadRequest
+ IActionResult result = await controller.LoadAsync(new WalletLoadRequest
{
Name = "myName",
Password = ""
@@ -847,7 +848,7 @@ public async Task GetBalanceWithValidModelStateReturnsWalletBalanceModelAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetBalance(new WalletBalanceRequest
+ IActionResult result = await controller.GetBalanceAsync(new WalletBalanceRequest
{
WalletName = "myWallet"
});
@@ -876,7 +877,7 @@ public async Task GetBalanceWithValidModelStateReturnsWalletBalanceModelAsync()
}
[Fact]
- public async Task WalletSyncFromDateReturnsOK()
+ public async Task WalletSyncFromDateReturnsOKAsync()
{
string walletName = "myWallet";
DateTime syncDate = DateTime.Now.Subtract(new TimeSpan(1)).Date;
@@ -888,7 +889,7 @@ public async Task WalletSyncFromDateReturnsOK()
var controller = this.GetWalletController();
- IActionResult result = await controller.SyncFromDate(new WalletSyncRequest
+ IActionResult result = await controller.SyncFromDateAsync(new WalletSyncRequest
{
WalletName = walletName,
Date = DateTime.Now.Subtract(new TimeSpan(1)).Date
@@ -897,11 +898,11 @@ public async Task WalletSyncFromDateReturnsOK()
var viewResult = Assert.IsType(result);
mockWalletSyncManager.Verify();
Assert.NotNull(viewResult);
- Assert.NotNull(viewResult.StatusCode == (int)HttpStatusCode.OK);
+ Assert.Equal((int)HttpStatusCode.OK, viewResult.StatusCode);
}
[Fact]
- public async Task WalletSyncAllReturnsOK()
+ public async Task WalletSyncAllReturnsOKAsync()
{
string walletName = "myWallet";
@@ -912,7 +913,7 @@ public async Task WalletSyncAllReturnsOK()
var controller = this.GetWalletController();
- IActionResult result = await controller.SyncFromDate(new WalletSyncRequest
+ IActionResult result = await controller.SyncFromDateAsync(new WalletSyncRequest
{
WalletName = walletName,
All = true
@@ -921,11 +922,11 @@ public async Task WalletSyncAllReturnsOK()
var viewResult = Assert.IsType(result);
mockWalletSyncManager.Verify();
Assert.NotNull(viewResult);
- Assert.NotNull(viewResult.StatusCode == (int)HttpStatusCode.OK);
+ Assert.Equal((int)HttpStatusCode.OK, viewResult.StatusCode);
}
[Fact]
- public async Task GetBalanceWithEmptyListOfAccountsReturnsWalletBalanceModel()
+ public async Task GetBalanceWithEmptyListOfAccountsReturnsWalletBalanceModelAsync()
{
var accounts = new List();
var mockWalletManager = new Mock();
@@ -934,7 +935,7 @@ public async Task GetBalanceWithEmptyListOfAccountsReturnsWalletBalanceModel()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetBalance(new WalletBalanceRequest
+ IActionResult result = await controller.GetBalanceAsync(new WalletBalanceRequest
{
WalletName = "myWallet",
AccountName = null
@@ -948,12 +949,12 @@ public async Task GetBalanceWithEmptyListOfAccountsReturnsWalletBalanceModel()
}
[Fact]
- public async Task GetBalanceWithInvalidValidModelStateReturnsBadRequest()
+ public async Task GetBalanceWithInvalidValidModelStateReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("WalletName", "A walletname is required.");
- IActionResult result = await controller.GetBalance(new WalletBalanceRequest
+ IActionResult result = await controller.GetBalanceAsync(new WalletBalanceRequest
{
WalletName = ""
});
@@ -968,7 +969,7 @@ public async Task GetBalanceWithInvalidValidModelStateReturnsBadRequest()
}
[Fact]
- public async Task GetBalanceWithExceptionReturnsBadRequest()
+ public async Task GetBalanceWithExceptionReturnsBadRequestAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetBalances("myWallet", WalletManager.DefaultAccount, It.IsAny()))
@@ -976,7 +977,7 @@ public async Task GetBalanceWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetBalance(new WalletBalanceRequest
+ IActionResult result = await controller.GetBalanceAsync(new WalletBalanceRequest
{
WalletName = "myWallet"
});
@@ -992,7 +993,7 @@ public async Task GetBalanceWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task GetAddressBalanceWithValidModelStateReturnsAddressBalanceModel()
+ public async Task GetAddressBalanceWithValidModelStateReturnsAddressBalanceModelAsync()
{
HdAccount account = WalletTestsHelpers.CreateAccount("account 1");
HdAddress accountAddress = WalletTestsHelpers.CreateAddress(true);
@@ -1011,7 +1012,7 @@ public async Task GetAddressBalanceWithValidModelStateReturnsAddressBalanceModel
var controller = this.GetWalletController();
- IActionResult result = await controller.GetReceivedByAddress(new ReceivedByAddressRequest
+ IActionResult result = await controller.GetReceivedByAddressAsync(new ReceivedByAddressRequest
{
Address = accountAddress.Address
});
@@ -1027,7 +1028,7 @@ public async Task GetAddressBalanceWithValidModelStateReturnsAddressBalanceModel
}
[Fact]
- public async Task GetAddressBalanceWithExceptionReturnsBadRequest()
+ public async Task GetAddressBalanceWithExceptionReturnsBadRequestAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetAddressBalance("MyAddress"))
@@ -1035,7 +1036,7 @@ public async Task GetAddressBalanceWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetReceivedByAddress(new ReceivedByAddressRequest
+ IActionResult result = await controller.GetReceivedByAddressAsync(new ReceivedByAddressRequest
{
Address = "MyAddress"
});
@@ -1051,12 +1052,12 @@ public async Task GetAddressBalanceWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task GetAddressBalanceWithInvalidModelStateReturnsBadRequest()
+ public async Task GetAddressBalanceWithInvalidModelStateReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("Address", "An address is required.");
- IActionResult result = await controller.GetReceivedByAddress(new ReceivedByAddressRequest
+ IActionResult result = await controller.GetReceivedByAddressAsync(new ReceivedByAddressRequest
{
Address = ""
});
@@ -1071,7 +1072,7 @@ public async Task GetAddressBalanceWithInvalidModelStateReturnsBadRequest()
}
[Fact]
- public async Task BuildTransactionWithValidRequestAllowingUnconfirmedReturnsWalletBuildTransactionModel()
+ public async Task BuildTransactionWithValidRequestAllowingUnconfirmedReturnsWalletBuildTransactionModelAsync()
{
var mockWalletTransactionHandler = this.ConfigureMock();
@@ -1082,7 +1083,7 @@ public async Task BuildTransactionWithValidRequestAllowingUnconfirmedReturnsWall
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 1",
AllowUnconfirmed = true,
@@ -1108,7 +1109,7 @@ public async Task BuildTransactionWithValidRequestAllowingUnconfirmedReturnsWall
}
[Fact]
- public async Task BuildTransactionWithCustomFeeAmountAndFeeTypeReturnsWalletBuildTransactionModelWithFeeAmount()
+ public async Task BuildTransactionWithCustomFeeAmountAndFeeTypeReturnsWalletBuildTransactionModelWithFeeAmountAsync()
{
var key = new Key();
this.ConfigureMock(mock =>
@@ -1120,7 +1121,7 @@ public async Task BuildTransactionWithCustomFeeAmountAndFeeTypeReturnsWalletBuil
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 1",
AllowUnconfirmed = true,
@@ -1147,7 +1148,7 @@ public async Task BuildTransactionWithCustomFeeAmountAndFeeTypeReturnsWalletBuil
[Fact]
public async Task
- BuildTransactionWithCustomFeeAmountAndNoFeeTypeReturnsWalletBuildTransactionModelWithFeeAmount()
+ BuildTransactionWithCustomFeeAmountAndNoFeeTypeReturnsWalletBuildTransactionModelWithFeeAmountAsync()
{
var key = new Key();
this.ConfigureMock(mock =>
@@ -1159,7 +1160,7 @@ public async Task
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 1",
AllowUnconfirmed = true,
@@ -1184,7 +1185,7 @@ public async Task
}
[Fact]
- public async Task BuildTransactionWithValidRequestNotAllowingUnconfirmedReturnsWalletBuildTransactionModel()
+ public async Task BuildTransactionWithValidRequestNotAllowingUnconfirmedReturnsWalletBuildTransactionModelAsync()
{
var key = new Key();
var sentTrx = new Transaction();
@@ -1196,7 +1197,7 @@ public async Task BuildTransactionWithValidRequestNotAllowingUnconfirmedReturnsW
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 1",
AllowUnconfirmed = false,
@@ -1222,7 +1223,7 @@ public async Task BuildTransactionWithValidRequestNotAllowingUnconfirmedReturnsW
}
[Fact]
- public async Task BuildTransactionWithChangeAddressReturnsWalletBuildTransactionModel()
+ public async Task BuildTransactionWithChangeAddressReturnsWalletBuildTransactionModelAsync()
{
string walletName = "myWallet";
@@ -1245,7 +1246,7 @@ public async Task BuildTransactionWithChangeAddressReturnsWalletBuildTransaction
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 0",
Recipients = new List() { new RecipientModel() { Amount = "1.0", DestinationAddress = new Key().PubKey.Hash.GetAddress(this.Network).ToString() } },
@@ -1265,7 +1266,7 @@ public async Task BuildTransactionWithChangeAddressReturnsWalletBuildTransaction
}
[Fact]
- public async Task BuildTransactionWithChangeAddressNotInWalletReturnsBadRequest()
+ public async Task BuildTransactionWithChangeAddressNotInWalletReturnsBadRequestAsync()
{
string walletName = "myWallet";
@@ -1281,7 +1282,7 @@ public async Task BuildTransactionWithChangeAddressNotInWalletReturnsBadRequest(
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 0",
Recipients = new List() { new RecipientModel() { Amount = "1.0", DestinationAddress = new Key().PubKey.Hash.GetAddress(this.Network).ToString() } },
@@ -1303,7 +1304,7 @@ public async Task BuildTransactionWithChangeAddressNotInWalletReturnsBadRequest(
}
[Fact]
- public async Task BuildTransactionWithChangeAddressAccountNotInWalletReturnsBadRequest()
+ public async Task BuildTransactionWithChangeAddressAccountNotInWalletReturnsBadRequestAsync()
{
string walletName = "myWallet";
@@ -1319,7 +1320,7 @@ public async Task BuildTransactionWithChangeAddressAccountNotInWalletReturnsBadR
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 0",
Recipients = new List() { new RecipientModel() { Amount = "1.0", DestinationAddress = new Key().PubKey.Hash.GetAddress(this.Network).ToString() } },
@@ -1341,12 +1342,12 @@ public async Task BuildTransactionWithChangeAddressAccountNotInWalletReturnsBadR
}
[Fact]
- public async Task BuildTransactionWithInvalidModelStateReturnsBadRequest()
+ public async Task BuildTransactionWithInvalidModelStateReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("WalletName", "A walletname is required.");
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
WalletName = ""
});
@@ -1361,7 +1362,7 @@ public async Task BuildTransactionWithInvalidModelStateReturnsBadRequest()
}
[Fact]
- public async Task BuildTransactionWithExceptionReturnsBadRequest()
+ public async Task BuildTransactionWithExceptionReturnsBadRequestAsync()
{
var key = new Key();
this.ConfigureMock(mock =>
@@ -1372,7 +1373,7 @@ public async Task BuildTransactionWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.BuildTransaction(new BuildTransactionRequest
+ IActionResult result = await controller.BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "Account 1",
AllowUnconfirmed = false,
@@ -1400,7 +1401,7 @@ public async Task BuildTransactionWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task SendTransactionSuccessfulReturnsWalletSendTransactionModelResponse()
+ public async Task SendTransactionSuccessfulReturnsWalletSendTransactionModelResponseAsync()
{
string transactionHex =
"010000000189c041f79aac3aa7e7a72804a9a55cd9eceba41a0586640f602eb9823540ce89010000006b483045022100ab9597b37cb8796aefa30b207abb248c8003d4d153076997e375b0daf4f9f7050220546397fee1cefe54c49210ea653e9e61fb88adf51b68d2c04ad6d2b46ddf97a30121035cc9de1f233469dad8a3bbd1e61b699a7dd8e0d8370c6f3b1f2a16167da83546ffffffff02f6400a00000000001976a914accf603142aaa5e22dc82500d3e187caf712f11588ac3cf61700000000001976a91467872601dda216fbf4cab7891a03ebace87d8e7488ac00000000";
@@ -1417,7 +1418,7 @@ public async Task SendTransactionSuccessfulReturnsWalletSendTransactionModelResp
var controller = this.GetWalletController();
- IActionResult result = await controller.SendTransaction(new SendTransactionRequest(transactionHex));
+ IActionResult result = await controller.SendTransactionAsync(new SendTransactionRequest(transactionHex));
var viewResult = Assert.IsType(result);
var model = viewResult.Value as WalletSendTransactionModel;
@@ -1441,7 +1442,7 @@ public async Task SendTransactionFailedBecauseNoNodesConnectedAsync()
var controller = this.GetWalletController();
- IActionResult result = await controller.SendTransaction(new SendTransactionRequest(new uint256(15555).ToString()));
+ IActionResult result = await controller.SendTransactionAsync(new SendTransactionRequest(new uint256(15555).ToString()));
var errorResult = Assert.IsType(result);
var errorResponse = Assert.IsType(errorResult.Value);
@@ -1453,12 +1454,12 @@ public async Task SendTransactionFailedBecauseNoNodesConnectedAsync()
}
[Fact]
- public async Task SendTransactionWithInvalidModelStateReturnsBadRequest()
+ public async Task SendTransactionWithInvalidModelStateReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("Hex", "Hex required.");
- IActionResult result = await controller.SendTransaction(new SendTransactionRequest(""));
+ IActionResult result = await controller.SendTransactionAsync(new SendTransactionRequest(""));
var errorResult = Assert.IsType(result);
var errorResponse = Assert.IsType(errorResult.Value);
@@ -1470,9 +1471,8 @@ public async Task SendTransactionWithInvalidModelStateReturnsBadRequest()
}
[Fact]
- public async Task ListWalletFilesWithExistingWalletFilesReturnsWalletFileModel()
+ public async Task ListWalletFilesWithExistingWalletFilesReturnsWalletFileModelAsync()
{
- string walletPath = "walletPath";
var walletManager = this.ConfigureMock();
walletManager.Setup(m => m.GetWalletsNames())
.Returns(new[] { "wallet1.wallet.json", "wallet2.wallet.json" });
@@ -1481,7 +1481,7 @@ public async Task ListWalletFilesWithExistingWalletFilesReturnsWalletFileModel()
var controller = this.GetWalletController();
- IActionResult result = await controller.ListWallets();
+ IActionResult result = await controller.ListWalletsAsync();
var viewResult = Assert.IsType(result);
var model = viewResult.Value as WalletInfoModel;
@@ -1493,7 +1493,7 @@ public async Task ListWalletFilesWithExistingWalletFilesReturnsWalletFileModel()
}
[Fact]
- public async Task ListWalletFilesWithoutExistingWalletFilesReturnsWalletFileModel()
+ public async Task ListWalletFilesWithoutExistingWalletFilesReturnsWalletFileModelAsync()
{
var walletManager = this.ConfigureMock();
@@ -1502,7 +1502,7 @@ public async Task ListWalletFilesWithoutExistingWalletFilesReturnsWalletFileMode
var controller = this.GetWalletController();
- IActionResult result = await controller.ListWallets();
+ IActionResult result = await controller.ListWalletsAsync();
var viewResult = Assert.IsType(result);
var model = viewResult.Value as WalletInfoModel;
@@ -1512,7 +1512,7 @@ public async Task ListWalletFilesWithoutExistingWalletFilesReturnsWalletFileMode
}
[Fact]
- public async Task ListWalletFilesWithExceptionReturnsBadRequest()
+ public async Task ListWalletFilesWithExceptionReturnsBadRequestAsync()
{
var walletManager = this.ConfigureMock();
walletManager.Setup(m => m.GetWalletsNames())
@@ -1520,7 +1520,7 @@ public async Task ListWalletFilesWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.ListWallets();
+ IActionResult result = await controller.ListWalletsAsync();
var errorResult = Assert.IsType(result);
var errorResponse = Assert.IsType(errorResult.Value);
@@ -1532,7 +1532,7 @@ public async Task ListWalletFilesWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task CreateNewAccountWithValidModelReturnsAccountName()
+ public async Task CreateNewAccountWithValidModelReturnsAccountNameAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test"))
@@ -1540,7 +1540,7 @@ public async Task CreateNewAccountWithValidModelReturnsAccountName()
var controller = this.GetWalletController();
- IActionResult result = await controller.CreateNewAccount(new GetUnusedAccountModel
+ IActionResult result = await controller.CreateNewAccountAsync(new GetUnusedAccountModel
{
WalletName = "myWallet",
Password = "test"
@@ -1551,7 +1551,7 @@ public async Task CreateNewAccountWithValidModelReturnsAccountName()
}
[Fact]
- public async Task CreateNewAccountWithInvalidValidModelReturnsBadRequest()
+ public async Task CreateNewAccountWithInvalidValidModelReturnsBadRequestAsync()
{
var mockWalletManager = new Mock();
@@ -1559,7 +1559,7 @@ public async Task CreateNewAccountWithInvalidValidModelReturnsBadRequest()
controller.ModelState.AddModelError("Password", "A password is required.");
- IActionResult result = await controller.CreateNewAccount(new GetUnusedAccountModel
+ IActionResult result = await controller.CreateNewAccountAsync(new GetUnusedAccountModel
{
WalletName = "myWallet",
Password = ""
@@ -1575,7 +1575,7 @@ public async Task CreateNewAccountWithInvalidValidModelReturnsBadRequest()
}
[Fact]
- public async Task CreateNewAccountWithExceptionReturnsBadRequest()
+ public async Task CreateNewAccountWithExceptionReturnsBadRequestAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetUnusedAccount("myWallet", "test"))
@@ -1583,7 +1583,7 @@ public async Task CreateNewAccountWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.CreateNewAccount(new GetUnusedAccountModel
+ IActionResult result = await controller.CreateNewAccountAsync(new GetUnusedAccountModel
{
WalletName = "myWallet",
Password = "test"
@@ -1600,7 +1600,7 @@ public async Task CreateNewAccountWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task ListAccountsWithValidModelStateReturnsAccounts()
+ public async Task ListAccountsWithValidModelStateReturnsAccountsAsync()
{
string walletName = "wallet 1";
Wallet wallet = WalletTestsHelpers.CreateWallet(walletName);
@@ -1614,7 +1614,7 @@ public async Task ListAccountsWithValidModelStateReturnsAccounts()
var controller = this.GetWalletController();
- IActionResult result = await controller.ListAccounts(new ListAccountsModel
+ IActionResult result = await controller.ListAccountsAsync(new ListAccountsModel
{
WalletName = "wallet 1"
});
@@ -1629,13 +1629,13 @@ public async Task ListAccountsWithValidModelStateReturnsAccounts()
}
[Fact]
- public async Task ListAccountsWithInvalidModelReturnsBadRequest()
+ public async Task ListAccountsWithInvalidModelReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("WalletName", "A wallet name is required.");
- IActionResult result = await controller.ListAccounts(new ListAccountsModel
+ IActionResult result = await controller.ListAccountsAsync(new ListAccountsModel
{
WalletName = ""
});
@@ -1650,7 +1650,7 @@ public async Task ListAccountsWithInvalidModelReturnsBadRequest()
}
[Fact]
- public async Task ListAccountsWithExceptionReturnsBadRequest()
+ public async Task ListAccountsWithExceptionReturnsBadRequestAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetAccounts("wallet 0"))
@@ -1658,7 +1658,7 @@ public async Task ListAccountsWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.ListAccounts(new ListAccountsModel
+ IActionResult result = await controller.ListAccountsAsync(new ListAccountsModel
{
WalletName = "wallet 0",
});
@@ -1674,7 +1674,7 @@ public async Task ListAccountsWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task GetUnusedAddressWithValidModelReturnsUnusedAddress()
+ public async Task GetUnusedAddressWithValidModelReturnsUnusedAddressAsync()
{
HdAddress address = WalletTestsHelpers.CreateAddress();
var mockWalletManager = this.ConfigureMock();
@@ -1683,7 +1683,7 @@ public async Task GetUnusedAddressWithValidModelReturnsUnusedAddress()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetUnusedAddress(new GetUnusedAddressModel
+ IActionResult result = await controller.GetUnusedAddressAsync(new GetUnusedAddressModel
{
WalletName = "myWallet",
AccountName = "Account 1"
@@ -1694,13 +1694,13 @@ public async Task GetUnusedAddressWithValidModelReturnsUnusedAddress()
}
[Fact]
- public async Task GetUnusedAddressWithInvalidValidModelReturnsBadRequest()
+ public async Task GetUnusedAddressWithInvalidValidModelReturnsBadRequestAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("AccountName", "An account name is required.");
- IActionResult result = await controller.GetUnusedAddress(new GetUnusedAddressModel
+ IActionResult result = await controller.GetUnusedAddressAsync(new GetUnusedAddressModel
{
WalletName = "myWallet",
AccountName = ""
@@ -1716,7 +1716,7 @@ public async Task GetUnusedAddressWithInvalidValidModelReturnsBadRequest()
}
[Fact]
- public async Task GetUnusedAddressWithExceptionReturnsBadRequest()
+ public async Task GetUnusedAddressWithExceptionReturnsBadRequestAsync()
{
var mockWalletManager = this.ConfigureMock();
mockWalletManager.Setup(m => m.GetUnusedAddress(new WalletAccountReference("myWallet", "Account 1")))
@@ -1724,7 +1724,7 @@ public async Task GetUnusedAddressWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetUnusedAddress(new GetUnusedAddressModel
+ IActionResult result = await controller.GetUnusedAddressAsync(new GetUnusedAddressModel
{
WalletName = "myWallet",
AccountName = "Account 1"
@@ -1741,7 +1741,7 @@ public async Task GetUnusedAddressWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task GetAllAddressesWithValidModelReturnsAllAddresses()
+ public async Task GetAllAddressesWithValidModelReturnsAllAddressesAsync()
{
string walletName = "myWallet";
@@ -1787,7 +1787,7 @@ public async Task GetAllAddressesWithValidModelReturnsAllAddresses()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetAllAddresses(new GetAllAddressesModel
+ IActionResult result = await controller.GetAllAddressesAsync(new GetAllAddressesModel
{ WalletName = "myWallet", AccountName = "Account 0" });
var viewResult = Assert.IsType(result);
@@ -1824,13 +1824,13 @@ public async Task GetAllAddressesWithValidModelReturnsAllAddresses()
}
[Fact]
- public async Task GetMaximumBalanceWithValidModelStateReturnsMaximumBalance()
+ public async Task GetMaximumBalanceWithValidModelStateReturnsMaximumBalanceAsync()
{
var controller = this.GetWalletController();
controller.ModelState.AddModelError("Error in model", "There was an error in the model.");
- IActionResult result = await controller.GetMaximumSpendableBalance(new WalletMaximumBalanceRequest
+ IActionResult result = await controller.GetMaximumSpendableBalanceAsync(new WalletMaximumBalanceRequest
{
WalletName = "myWallet",
AccountName = "account 1",
@@ -1849,7 +1849,7 @@ public async Task GetMaximumBalanceWithValidModelStateReturnsMaximumBalance()
}
[Fact]
- public async Task GetMaximumBalanceSuccessfullyReturnsMaximumBalanceAndFee()
+ public async Task GetMaximumBalanceSuccessfullyReturnsMaximumBalanceAndFeeAsync()
{
var mockWalletTransactionHandler = this.ConfigureMock();
mockWalletTransactionHandler
@@ -1858,7 +1858,7 @@ public async Task GetMaximumBalanceSuccessfullyReturnsMaximumBalanceAndFee()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetMaximumSpendableBalance(new WalletMaximumBalanceRequest
+ IActionResult result = await controller.GetMaximumSpendableBalanceAsync(new WalletMaximumBalanceRequest
{
WalletName = "myWallet",
AccountName = "account 1",
@@ -1875,7 +1875,7 @@ public async Task GetMaximumBalanceSuccessfullyReturnsMaximumBalanceAndFee()
}
[Fact]
- public async Task GetMaximumBalanceWithExceptionReturnsBadRequest()
+ public async Task GetMaximumBalanceWithExceptionReturnsBadRequestAsync()
{
var mockWalletTransactionHandler = this.ConfigureMock();
mockWalletTransactionHandler
@@ -1884,7 +1884,7 @@ public async Task GetMaximumBalanceWithExceptionReturnsBadRequest()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetMaximumSpendableBalance(new WalletMaximumBalanceRequest
+ IActionResult result = await controller.GetMaximumSpendableBalanceAsync(new WalletMaximumBalanceRequest
{
WalletName = "myWallet",
AccountName = "account 1",
@@ -1900,7 +1900,7 @@ public async Task GetMaximumBalanceWithExceptionReturnsBadRequest()
}
[Fact]
- public async Task GetTransactionFeeEstimateWithValidRequestReturnsFee()
+ public async Task GetTransactionFeeEstimateWithValidRequestReturnsFeeAsync()
{
var mockWalletManager = this.ConfigureMock();
var mockWalletTransactionHandler = this.ConfigureMock();
@@ -1911,7 +1911,7 @@ public async Task GetTransactionFeeEstimateWithValidRequestReturnsFee()
var controller = this.GetWalletController();
- IActionResult result = await controller.GetTransactionFeeEstimate(new TxFeeEstimateRequest
+ IActionResult result = await controller.GetTransactionFeeEstimateAsync(new TxFeeEstimateRequest
{
AccountName = "Account 1",
Recipients = new List
@@ -1934,7 +1934,7 @@ public async Task GetTransactionFeeEstimateWithValidRequestReturnsFee()
}
[Fact]
- public async Task RemoveAllTransactionsWithSyncEnabledSyncsAfterRemoval()
+ public async Task RemoveAllTransactionsWithSyncEnabledSyncsAfterRemovalAsync()
{
// Arrange.
string walletName = "wallet1";
@@ -1963,7 +1963,7 @@ public async Task RemoveAllTransactionsWithSyncEnabledSyncsAfterRemoval()
};
// Act.
- IActionResult result = await controller.RemoveTransactions(requestModel);
+ IActionResult result = await controller.RemoveTransactionsAsync(requestModel);
// Assert.
walletManager.VerifyAll();
@@ -1979,7 +1979,7 @@ public async Task RemoveAllTransactionsWithSyncEnabledSyncsAfterRemoval()
}
[Fact]
- public async Task RemoveAllTransactionsWithSyncDisabledDoesNotSyncAfterRemoval()
+ public async Task RemoveAllTransactionsWithSyncDisabledDoesNotSyncAfterRemovalAsync()
{
// Arrange.
string walletName = "wallet1";
@@ -2004,7 +2004,7 @@ public async Task RemoveAllTransactionsWithSyncDisabledDoesNotSyncAfterRemoval()
};
// Act.
- IActionResult result = await controller.RemoveTransactions(requestModel);
+ IActionResult result = await controller.RemoveTransactionsAsync(requestModel);
// Assert.
walletManager.VerifyAll();
@@ -2020,7 +2020,7 @@ public async Task RemoveAllTransactionsWithSyncDisabledDoesNotSyncAfterRemoval()
}
[Fact]
- public async Task RemoveTransactionsWithIdsRemovesAllTransactionsByIds()
+ public async Task RemoveTransactionsWithIdsRemovesAllTransactionsByIdsAsync()
{
// Arrange.
string walletName = "wallet1";
@@ -2048,7 +2048,7 @@ public async Task RemoveTransactionsWithIdsRemovesAllTransactionsByIds()
};
// Act.
- IActionResult result = await controller.RemoveTransactions(requestModel);
+ IActionResult result = await controller.RemoveTransactionsAsync(requestModel);
// Assert.
walletManager.VerifyAll();
diff --git a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletManagerTest.cs b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletManagerTest.cs
index 5564e1d267..1ff9a5af7c 100644
--- a/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletManagerTest.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet.Tests/WalletManagerTest.cs
@@ -1432,7 +1432,7 @@ public void ProcessTransactionWithValidTransactionLoadsTransactionsIntoWalletIfM
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions);
TransactionData destinationAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions.ElementAt(0);
@@ -1494,7 +1494,7 @@ public void ProcessTransactionWithValidSegwitTransactionLoadsTransactionsIntoWal
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions);
TransactionData destinationAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions.ElementAt(0);
@@ -1668,7 +1668,7 @@ public void ProcessTransactionWithDestinationAsMultisigAddTransactionAsPayment()
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions);
TransactionData changeAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).InternalAddresses.ElementAt(0).Transactions.ElementAt(0);
@@ -1731,7 +1731,7 @@ public void ProcessTransactionWithBlockHeightSetsBlockHeightOnTransactionData()
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Equal(blockHeight - 1, spentAddressResult.Transactions.ElementAt(0).BlockHeight);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions);
@@ -1798,7 +1798,7 @@ public void ProcessTransactionWithBlockSetsBlockHash()
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Equal(chainInfo.block.GetHash(), spentAddressResult.Transactions.ElementAt(0).BlockHash);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions);
@@ -1816,12 +1816,14 @@ public void ProcessTransactionWithBlockSetsBlockHash()
Assert.Equal(transaction.Outputs[0].ScriptPubKey, changeAddressResult.ScriptPubKey);
}
+ /*
///
/// TODO: [SENDTRANSACTION] Conceptual changes had been introduced to tx sending.
///
/// These tests don't make sense anymore, it must be either removed or refactored.
///
///
+ */
//[Fact(Skip = "See TODO")]
//public void SendTransactionWithoutMempoolValidatorProcessesTransactionAndBroadcastsTransactionToConnectionManagerNodes()
//{
@@ -1929,12 +1931,14 @@ public void ProcessTransactionWithBlockSetsBlockHash()
//}
//}
+ /*
///
/// TODO: [SENDTRANSACTION] Conceptual changes had been introduced to tx sending.
///
/// These tests don't make sense anymore, it must be either removed or refactored.
///
///
+ */
//[Fact(Skip = "See TODO")]
//public void SendTransactionWithMempoolValidatorWithAcceptToMemoryPoolSuccessProcessesTransaction()
//{
@@ -2045,12 +2049,14 @@ public void ProcessTransactionWithBlockSetsBlockHash()
//}
//}
+ /*
///
/// TODO: [SENDTRANSACTION] Conceptual changes had been introduced to tx sending.
///
/// These tests don't make sense anymore, it must be either removed or refactored.
///
///
+ */
//[Fact(Skip = "See TODO")]
//public void SendTransactionWithMempoolValidatorWithAcceptToMemoryPoolFailedDoesNotProcessesTransaction()
//{
@@ -2147,8 +2153,7 @@ public void ProcessTransactionWithBlockSetsBlockHash()
// Assert.Equal(0, payloads.Count);
// }
//}
- //}
-
+ //}
private void AdvanceWalletTipToChainTip(IWalletRepository walletRepository, ChainIndexer concurrentchain)
{
var block0 = this.Network.CreateBlock();
@@ -2314,7 +2319,7 @@ public void ProcessBlockWithWalletsProcessesTransactionsOfBlockToWallet()
HdAddress spentAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(0);
Assert.Single(spendingAddress.Transactions);
Assert.Equal(transaction.GetHash(), spentAddressResult.Transactions.ElementAt(0).SpendingDetails.TransactionId);
- Assert.True(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments.Any(p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value));
+ Assert.Contains(spentAddressResult.Transactions.ElementAt(0).SpendingDetails.Payments, p => p.DestinationScriptPubKey == transaction.Outputs[1].ScriptPubKey && p.Amount == transaction.Outputs[1].Value);
Assert.Single(wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions);
TransactionData destinationAddressResult = wallet.AccountsRoot.ElementAt(0).Accounts.ElementAt(0).ExternalAddresses.ElementAt(1).Transactions.ElementAt(0);
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletClient.cs b/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletClient.cs
index 06aecbf1a6..d576473051 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletClient.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletClient.cs
@@ -9,7 +9,7 @@ namespace Stratis.Bitcoin.Features.Wallet.Controllers
/// Rest client for .
public interface IWalletClient : IRestApiClientBase
{
- ///
+ ///
Task SignMessageAsync(SignMessageRequest request, CancellationToken cancellation = default);
}
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletController.cs b/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletController.cs
index 7589161c57..4a82b28ae1 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletController.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Controllers/WalletController.cs
@@ -53,7 +53,7 @@ public WalletController(
[HttpGet]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
- public async Task GenerateMnemonic([FromQuery] string language = "English", int wordCount = 12,
+ public async Task GenerateMnemonicAsync([FromQuery] string language = "English", int wordCount = 12,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(new { Language = language, WordCount = wordCount },
@@ -78,10 +78,10 @@ public async Task GenerateMnemonic([FromQuery] string language =
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Conflict)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task Create([FromBody] WalletCreationRequest request,
+ public async Task CreateAsync([FromBody] WalletCreationRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.CreateWallet(req, token)));
}
@@ -99,7 +99,7 @@ public async Task Create([FromBody] WalletCreationRequest request
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task SignMessage([FromBody] SignMessageRequest request,
+ public async Task SignMessageAsync([FromBody] SignMessageRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -124,7 +124,7 @@ public async Task SignMessage([FromBody] SignMessageRequest reque
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetPubKey([FromBody] PubKeyRequest request,
+ public async Task GetPubKeyAsync([FromBody] PubKeyRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -149,7 +149,7 @@ public async Task GetPubKey([FromBody] PubKeyRequest request,
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task VerifyMessage([FromBody] VerifyRequest request,
+ public async Task VerifyMessageAsync([FromBody] VerifyRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -178,10 +178,10 @@ public async Task VerifyMessage([FromBody] VerifyRequest request,
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task Load([FromBody] WalletLoadRequest request,
+ public async Task LoadAsync([FromBody] WalletLoadRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken, async (req, token) =>
+ return await this.ExecuteAsync(request, cancellationToken, async (req, token) =>
{
await this.walletService.LoadWallet(req, token);
return Ok();
@@ -206,10 +206,10 @@ public async Task Load([FromBody] WalletLoadRequest request,
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.Conflict)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task Recover([FromBody] WalletRecoveryRequest request,
+ public async Task RecoverAsync([FromBody] WalletRecoveryRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken, async (req, token) =>
+ return await this.ExecuteAsync(request, cancellationToken, async (req, token) =>
{
await this.walletService.RecoverWallet(req, token);
return Ok();
@@ -235,10 +235,10 @@ public async Task Recover([FromBody] WalletRecoveryRequest reques
[ProducesResponseType((int)HttpStatusCode.NotFound)]
[ProducesResponseType((int)HttpStatusCode.Conflict)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task RecoverViaExtPubKey([FromBody] WalletExtPubRecoveryRequest request,
+ public async Task RecoverViaExtPubKeyAsync([FromBody] WalletExtPubRecoveryRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken, async (req, token) =>
+ return await this.ExecuteAsync(request, cancellationToken, async (req, token) =>
{
await this.walletService.RecoverViaExtPubKey(req, token);
return Ok();
@@ -264,7 +264,7 @@ public async Task RecoverViaExtPubKey([FromBody] WalletExtPubReco
public Task GetGeneralInfo([FromQuery] WalletName request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return this.Execute(request, cancellationToken, async (req, token) =>
+ return this.ExecuteAsync(request, cancellationToken, async (req, token) =>
this.Json(await this.walletService.GetWalletGeneralInfo(req.Name, token)));
}
@@ -276,7 +276,7 @@ public Task GetGeneralInfo([FromQuery] WalletName request,
/// Transaction Count
[Route("transactionCount")]
[HttpGet]
- public async Task GetTransactionCount([FromQuery] WalletTransactionCountRequest request,
+ public async Task GetTransactionCountAsync([FromQuery] WalletTransactionCountRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken,
@@ -313,10 +313,10 @@ public IActionResult GetHistory([FromQuery] WalletHistoryRequest request)
/// Request is null
[Route("balance")]
[HttpGet]
- public async Task GetBalance([FromQuery] WalletBalanceRequest request,
+ public async Task GetBalanceAsync([FromQuery] WalletBalanceRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.GetBalance(req.WalletName, req.AccountName,
req.IncludeBalanceByAddress, token))
);
@@ -336,10 +336,10 @@ public async Task GetBalance([FromQuery] WalletBalanceRequest req
/// Request is null
[Route("received-by-address")]
[HttpGet]
- public async Task GetReceivedByAddress([FromQuery] ReceivedByAddressRequest request,
+ public async Task GetReceivedByAddressAsync([FromQuery] ReceivedByAddressRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) =>
this.Json(await this.walletService.GetReceivedByAddress(request.Address, cancellationToken)));
}
@@ -357,10 +357,10 @@ public async Task GetReceivedByAddress([FromQuery] ReceivedByAddr
/// Request is null
[Route("maxbalance")]
[HttpGet]
- public async Task GetMaximumSpendableBalance([FromQuery] WalletMaximumBalanceRequest request,
+ public async Task GetMaximumSpendableBalanceAsync([FromQuery] WalletMaximumBalanceRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) =>
this.Json(await this.walletService.GetMaximumSpendableBalance(request, cancellationToken)));
}
@@ -381,10 +381,10 @@ public async Task GetMaximumSpendableBalance([FromQuery] WalletMa
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetSpendableTransactions([FromQuery] SpendableTransactionsRequest request,
+ public async Task GetSpendableTransactionsAsync([FromQuery] SpendableTransactionsRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => Json(await this.walletService.GetSpendableTransactions(req, token)));
}
@@ -405,10 +405,10 @@ public async Task GetSpendableTransactions([FromQuery] SpendableT
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetTransactionFeeEstimate([FromBody] TxFeeEstimateRequest request,
+ public async Task GetTransactionFeeEstimateAsync([FromBody] TxFeeEstimateRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => Json(await this.walletService.GetTransactionFeeEstimate(req, token)));
}
@@ -427,16 +427,18 @@ public async Task GetTransactionFeeEstimate([FromBody] TxFeeEstim
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task BuildTransaction([FromBody] BuildTransactionRequest request,
+ public async Task BuildTransactionAsync([FromBody] BuildTransactionRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => Json(await this.walletService.BuildTransaction(req, token)));
}
///
- /// Same as but overrides OP_RETURN data and encodes destination chain and address for InterFlux transaction.
+ /// Same as but overrides OP_RETURN data and encodes destination chain and address for InterFlux transaction.
///
+ /// See .
+ /// The asynchronous task returning an .
[Route("build-interflux-transaction")]
[HttpPost]
[ProducesResponseType((int)HttpStatusCode.OK)]
@@ -456,7 +458,7 @@ public async Task BuildInterFluxTransactionAsync([FromBody] Build
request.OpReturnData = InterFluxOpReturnEncoder.Encode((DestinationChain)request.DestinationChain, request.DestinationAddress);
- return await this.Execute(request, default, async (req, token) => Json(await this.walletService.BuildTransaction(req, token)));
+ return await this.ExecuteAsync(request, default, async (req, token) => Json(await this.walletService.BuildTransaction(req, token)));
}
///
@@ -476,10 +478,10 @@ public async Task BuildInterFluxTransactionAsync([FromBody] Build
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task SendTransaction([FromBody] SendTransactionRequest request,
+ public async Task SendTransactionAsync([FromBody] SendTransactionRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => Json(await this.walletService.SendTransaction(req, token)));
}
@@ -491,7 +493,7 @@ public async Task SendTransaction([FromBody] SendTransactionReque
/// The Cancellation Token
[Route("list-wallets")]
[HttpGet]
- public async Task ListWallets(CancellationToken cancellationToken = default(CancellationToken))
+ public async Task ListWalletsAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync((object)null, cancellationToken, (req, token) =>
this.Json(new WalletInfoModel(this.walletManager.GetWalletsNames(), this.walletManager.GetWatchOnlyWalletsNames())), false);
@@ -522,7 +524,7 @@ public async Task SendTransaction([FromBody] SendTransactionReque
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Forbidden)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task CreateNewAccount([FromBody] GetUnusedAccountModel request,
+ public async Task CreateNewAccountAsync([FromBody] GetUnusedAccountModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -554,7 +556,7 @@ public async Task CreateNewAccount([FromBody] GetUnusedAccountMod
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task ListAccounts([FromQuery] ListAccountsModel request,
+ public async Task ListAccountsAsync([FromQuery] ListAccountsModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -580,7 +582,7 @@ public async Task ListAccounts([FromQuery] ListAccountsModel requ
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetUnusedAddress([FromQuery] GetUnusedAddressModel request,
+ public async Task GetUnusedAddressAsync([FromQuery] GetUnusedAddressModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -609,7 +611,7 @@ public async Task GetUnusedAddress([FromQuery] GetUnusedAddressMo
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetUnusedAddresses([FromQuery] GetUnusedAddressesModel request,
+ public async Task GetUnusedAddressesAsync([FromQuery] GetUnusedAddressesModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -640,7 +642,7 @@ public async Task GetUnusedAddresses([FromQuery] GetUnusedAddress
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.InternalServerError)]
- public async Task GetNewAddresses([FromQuery] GetNewAddressesModel request,
+ public async Task GetNewAddressesAsync([FromQuery] GetNewAddressesModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -665,10 +667,10 @@ public async Task GetNewAddresses([FromQuery] GetNewAddressesMode
/// Request is null
[Route("addresses")]
[HttpGet]
- public async Task GetAllAddresses([FromQuery] GetAllAddressesModel request,
+ public async Task GetAllAddressesAsync([FromQuery] GetAllAddressesModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.GetAllAddresses(req, token)));
}
@@ -694,19 +696,19 @@ public async Task GetAllAddresses([FromQuery] GetAllAddressesMode
/// Request is null
[Route("remove-transactions")]
[HttpDelete]
- public async Task RemoveTransactions([FromQuery] RemoveTransactionsModel request,
+ public async Task RemoveTransactionsAsync([FromQuery] RemoveTransactionsModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.RemoveTransactions(req, token)));
}
[Route("remove-wallet")]
[HttpDelete]
- public async Task RemoveWallet([FromQuery] RemoveWalletModel request,
+ public async Task RemoveWalletAsync([FromQuery] RemoveWalletModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) =>
{
await this.walletService.RemoveWallet(req, token);
@@ -726,7 +728,7 @@ public async Task RemoveWallet([FromQuery] RemoveWalletModel requ
/// Request is null
[Route("extpubkey")]
[HttpGet]
- public async Task GetExtPubKey([FromQuery] GetExtPubKeyModel request,
+ public async Task GetExtPubKeyAsync([FromQuery] GetExtPubKeyModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken,
@@ -746,7 +748,7 @@ public async Task GetExtPubKey([FromQuery] GetExtPubKeyModel requ
/// Request is null
[Route("privatekey")]
[HttpPost]
- public async Task RetrievePrivateKey([FromBody] RetrievePrivateKeyModel request,
+ public async Task RetrievePrivateKeyAsync([FromBody] RetrievePrivateKeyModel request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken,
@@ -766,7 +768,7 @@ public async Task RetrievePrivateKey([FromBody] RetrievePrivateKe
[Route("sync")]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest)]
- public async Task Sync([FromBody] HashModel model,
+ public async Task SyncAsync([FromBody] HashModel model,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(model, cancellationToken, (req, token) =>
@@ -796,7 +798,7 @@ public async Task Sync([FromBody] HashModel model,
/// Invalid request
[HttpPost]
[Route("sync-from-date")]
- public async Task SyncFromDate([FromBody] WalletSyncRequest request,
+ public async Task SyncFromDateAsync([FromBody] WalletSyncRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
return await this.ExecuteAsAsync(request, cancellationToken, (req, token) =>
@@ -818,16 +820,17 @@ public async Task SyncFromDate([FromBody] WalletSyncRequest reque
/// Retrieves information about the wallet
///
/// Parameters to request wallet stats
+ /// See .
/// Stats about the wallet
/// Returns wallet stats
/// Invalid request, or unexpected exception occurred
/// Request is null
[Route("wallet-stats")]
[HttpGet]
- public async Task WalletStats([FromQuery] WalletStatsRequest request,
+ public async Task WalletStatsAsync([FromQuery] WalletStatsRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.GetWalletStats(req, token)));
}
@@ -841,10 +844,10 @@ public async Task WalletStats([FromQuery] WalletStatsRequest requ
/// Request is null
[HttpPost]
[Route("splitcoins")]
- public async Task SplitCoins([FromBody] SplitCoinsRequest request,
+ public async Task SplitCoinsAsync([FromBody] SplitCoinsRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.SplitCoins(req, token)));
}
@@ -854,46 +857,46 @@ public async Task SplitCoins([FromBody] SplitCoinsRequest request
/// The Cancellation Token
[HttpPost]
[Route("distribute-utxos")]
- public async Task DistributeUtxos([FromBody] DistributeUtxosRequest request,
+ public async Task DistributeUtxosAsync([FromBody] DistributeUtxosRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.DistributeUtxos(req, token)));
}
[HttpPost]
[Route("sweep")]
- public async Task Sweep([FromBody] SweepRequest request,
+ public async Task SweepAsync([FromBody] SweepRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.Sweep(req, token)));
}
[Route("build-offline-sign-request")]
[HttpPost]
- public async Task BuildOfflineSignRequest([FromBody] BuildOfflineSignRequest request,
+ public async Task BuildOfflineSignRequestAsync([FromBody] BuildOfflineSignRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.BuildOfflineSignRequest(req, token)));
}
// TODO: Make this support PSBT directly?
[Route("offline-sign-request")]
[HttpPost]
- public async Task OfflineSignRequest([FromBody] OfflineSignRequest request,
+ public async Task OfflineSignRequestAsync([FromBody] OfflineSignRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken, async (req, token) => this.Json(await this.walletService.OfflineSignRequest(req, token)));
+ return await this.ExecuteAsync(request, cancellationToken, async (req, token) => this.Json(await this.walletService.OfflineSignRequest(req, token)));
}
[HttpPost]
[Route("consolidate")]
- public async Task Consolidate([FromBody] ConsolidationRequest request,
+ public async Task ConsolidateAsync([FromBody] ConsolidationRequest request,
CancellationToken cancellationToken = default(CancellationToken))
{
- return await this.Execute(request, cancellationToken,
+ return await this.ExecuteAsync(request, cancellationToken,
async (req, token) => this.Json(await this.walletService.Consolidate(req, token)));
}
}
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs
index 6a80e3352f..7013768cca 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletManager.cs
@@ -273,6 +273,14 @@ public interface IWalletManager
/// The list of accounts in the specified wallet.
IEnumerable GetAccounts(string walletName);
+ ///
+ /// Gets a list of accounts.
+ ///
+ /// The name of the wallet to look into.
+ /// Optional filter for the accounts to return. Defaults to returning normal accounts only.
+ /// The list of accounts in the specified wallet.
+ IEnumerable GetAccounts(string walletName, Func accountFilter);
+
///
/// Gets a list of all the accounts in all wallets.
///
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletTransactionHandler.cs b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletTransactionHandler.cs
index 2abd265982..e66fb9fde3 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletTransactionHandler.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Interfaces/IWalletTransactionHandler.cs
@@ -2,6 +2,9 @@
namespace Stratis.Bitcoin.Features.Wallet.Interfaces
{
+ ///
+ /// A handler that has various functionalities related to transaction operations.
+ ///
public interface IWalletTransactionHandler
{
///
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Models/UnspentCoinModel.cs b/src/Stratis.Bitcoin.Features.Wallet/Models/UnspentCoinModel.cs
index 61e6f480c9..7da4bd8864 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Models/UnspentCoinModel.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Models/UnspentCoinModel.cs
@@ -4,6 +4,7 @@
namespace Stratis.Bitcoin.Features.Wallet.Models
{
+ // TODO: This is similar to the UnspentCoin class in the RPC feature; perhaps one of the two should be removed?
///
/// Model for Json response for listunspent RPC call.
///
@@ -46,6 +47,12 @@ public class UnspentCoinModel
[JsonProperty(PropertyName = "redeemScript")]
public string RedeemScriptHex { get; set; }
+ ///
+ /// If the output is a P2WSH or P2SH-P2WSH whose script belongs to this wallet, this is the redeem script.
+ ///
+ [JsonProperty(PropertyName = "witnessScript")]
+ public string WitnessScriptHex { get; set; }
+
///
/// The transaction amount.
/// Serialized in coins (BTC).
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs
index 43a1754955..895365503b 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/Services/WalletService.cs
@@ -9,7 +9,6 @@
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using NBitcoin;
-using NBitcoin.DataEncoders;
using NBitcoin.Policy;
using Stratis.Bitcoin.Builder.Feature;
using Stratis.Bitcoin.Configuration;
diff --git a/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj b/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj
index d826867cc8..d67e9be299 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj
+++ b/src/Stratis.Bitcoin.Features.Wallet/Stratis.Bitcoin.Features.Wallet.csproj
@@ -14,7 +14,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
index 068264bd80..48dda593df 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/WalletFeature.cs
@@ -54,6 +54,8 @@ public class WalletFeature : BaseWalletFeature
/// The address book manager.
/// The connection manager.
/// The broadcaster behavior.
+ /// See .
+ /// See .
public WalletFeature(
IWalletSyncManager walletSyncManager,
IWalletManager walletManager,
diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs
index 1bbf0362fa..870fae42a1 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/WalletManager.cs
@@ -955,6 +955,12 @@ public AddressBalance GetAddressBalance(string address)
///
public IEnumerable GetAccounts(string walletName)
+ {
+ return GetAccounts(walletName, null);
+ }
+
+ ///
+ public IEnumerable GetAccounts(string walletName, Func accountFilter)
{
Guard.NotEmpty(walletName, nameof(walletName));
@@ -963,7 +969,7 @@ public IEnumerable GetAccounts(string walletName)
HdAccount[] res = null;
lock (this.lockObject)
{
- res = wallet.GetAccounts().ToArray();
+ res = wallet.GetAccounts(accountFilter).ToArray();
}
return res;
@@ -1017,6 +1023,7 @@ public void AddWatchOnlyAddress(string walletName, string accountName, PubKey[]
this.WalletRepository.AddWatchOnlyAddresses(walletName, accountName, 0, pubKeys.Select(pubKey => new HdAddress() { Pubkey = pubKey.ScriptPubKey }).ToList());
}
+ // TODO: Not sure if the intention was to return special accounts too. If not, this method doesn't have much purpose and is essentially a duplicate of GetAccounts(), albeit across all wallets
public IEnumerable GetAllAccounts()
{
HdAccount[] res = null;
diff --git a/src/Stratis.Bitcoin.Features.Wallet/WalletRPCController.cs b/src/Stratis.Bitcoin.Features.Wallet/WalletRPCController.cs
index cee13e9a05..1572567a54 100644
--- a/src/Stratis.Bitcoin.Features.Wallet/WalletRPCController.cs
+++ b/src/Stratis.Bitcoin.Features.Wallet/WalletRPCController.cs
@@ -126,8 +126,6 @@ public bool LockWallet()
[ActionDescription("Sends money to an address. Requires wallet to be unlocked using walletpassphrase.")]
public async Task SendToAddressAsync(BitcoinAddress address, decimal amount, string commentTx, string commentDest)
{
- WalletAccountReference account = this.GetWalletAccountReference();
-
TransactionBuildContext context = new TransactionBuildContext(this.FullNode.Network)
{
AccountReference = this.GetWalletAccountReference(),
@@ -154,7 +152,7 @@ public async Task SendToAddressAsync(BitcoinAddress address, decimal am
[ActionName("fundrawtransaction")]
[ActionDescription("Add inputs to a transaction until it has enough in value to meet its out value. Note that signing is performed separately.")]
- public async Task FundRawTransactionAsync(string rawHex, FundRawTransactionOptions options = null, bool? isWitness = null)
+ public Task FundRawTransactionAsync(string rawHex, FundRawTransactionOptions options = null, bool? isWitness = null)
{
try
{
@@ -300,12 +298,12 @@ public async Task FundRawTransactionAsync(string raw
}
}
- return new FundRawTransactionResponse()
+ return Task.FromResult(new FundRawTransactionResponse()
{
ChangePos = foundChange,
Fee = context.TransactionFee,
Transaction = rawTx
- };
+ });
}
catch (SecurityException)
{
@@ -325,7 +323,7 @@ public async Task FundRawTransactionAsync(string raw
/// The hex format of the transaction once it has been signed.
[ActionName("signrawtransaction")]
[ActionDescription("Sign inputs for raw transaction. Requires all affected wallets to be unlocked using walletpassphrase.")]
- public async Task SignRawTransactionAsync(string rawHex)
+ public Task SignRawTransactionAsync(string rawHex)
{
try
{
@@ -372,11 +370,11 @@ public async Task SignRawTransactionAsync(string raw
builder.AddKeys(signingKeys.ToArray());
builder.SignTransactionInPlace(rawTx);
- return new SignRawTransactionResponse()
+ return Task.FromResult(new SignRawTransactionResponse()
{
Transaction = rawTx,
Complete = true
- };
+ });
}
catch (SecurityException)
{
@@ -461,10 +459,11 @@ public decimal GetBalance(string accountName, int minConfirmations = 0)
/// Uses the default wallet if specified, or the first wallet found.
///
/// Identifier of the transaction to find.
+ /// Set to true to search the watch-only account.
/// Transaction information.
[ActionName("gettransaction")]
[ActionDescription("Get detailed information about an in-wallet transaction.")]
- public async Task
/// Peer to get chain from.
/// The highest block wanted.
- ///
+ /// See .
/// The chain of headers.
private ChainIndexer GetChain(INetworkPeer peer, uint256 hashStop = null, CancellationToken cancellationToken = default(CancellationToken))
{
@@ -610,8 +613,8 @@ public async Task GenerateAsync(int blockCount, bool includeUnbroadcast
/// Node to synchronize the chain for.
/// The chain to synchronize.
/// The location until which it synchronize.
- ///
- ///
+ /// See .
+ /// An enumeration of objects added to the fork point.
private IEnumerable SynchronizeChain(INetworkPeer peer, ChainIndexer chain, uint256 hashStop = null, CancellationToken cancellationToken = default(CancellationToken))
{
ChainedHeader oldTip = chain.Tip;
diff --git a/src/Stratis.Bitcoin.IntegrationTests.Common/Stratis.Bitcoin.IntegrationTests.Common.csproj b/src/Stratis.Bitcoin.IntegrationTests.Common/Stratis.Bitcoin.IntegrationTests.Common.csproj
index c2e3ef116f..d42ca8c63a 100644
--- a/src/Stratis.Bitcoin.IntegrationTests.Common/Stratis.Bitcoin.IntegrationTests.Common.csproj
+++ b/src/Stratis.Bitcoin.IntegrationTests.Common/Stratis.Bitcoin.IntegrationTests.Common.csproj
@@ -13,7 +13,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
diff --git a/src/Stratis.Bitcoin.IntegrationTests.Common/TestHelper.cs b/src/Stratis.Bitcoin.IntegrationTests.Common/TestHelper.cs
index 2a8a5bfe2a..09fe7fc22f 100644
--- a/src/Stratis.Bitcoin.IntegrationTests.Common/TestHelper.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests.Common/TestHelper.cs
@@ -525,7 +525,7 @@ public static void SendCoins(CoreNode miner, CoreNode sender, CoreNode[] receive
var transaction = sender.FullNode.WalletTransactionHandler().BuildTransaction(context);
- sender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction.ToHex())).GetAwaiter().GetResult();
+ sender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction.ToHex())).GetAwaiter().GetResult();
MineBlocks(miner, 1);
diff --git a/src/Stratis.Bitcoin.IntegrationTests/API/ApiSteps.cs b/src/Stratis.Bitcoin.IntegrationTests/API/ApiSteps.cs
index 04943f0f28..e68e672e0b 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/API/ApiSteps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/API/ApiSteps.cs
@@ -533,14 +533,14 @@ private async Task SendTransaction(IActionResult transactionResult)
var walletTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
this.transaction = this.firstStratisPowApiNode.FullNode.Network.CreateTransaction(walletTransactionModel.Hex);
await this.firstStratisPowApiNode.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(walletTransactionModel.Hex));
+ .SendTransactionAsync(new SendTransactionRequest(walletTransactionModel.Hex));
}
private async Task BuildTransaction()
{
IActionResult transactionResult = await this.firstStratisPowApiNode.FullNode
.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = WalletAccountName,
AllowUnconfirmed = true,
diff --git a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/BlockStoreSignaledTests.cs b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/BlockStoreSignaledTests.cs
index 278b3c83d2..dc243643fa 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/BlockStoreSignaledTests.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/BlockStoreSignaledTests.cs
@@ -48,12 +48,14 @@ private async Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage mes
}
}
- private async Task ProcessMessageAsync(INetworkPeer peer, IncomingMessage message)
+ private Task ProcessMessageAsync(INetworkPeer peer, IncomingMessage message)
{
if (!this.receivedMessageTracker.ContainsKey(message.Message.Payload.Command))
this.receivedMessageTracker[message.Message.Payload.Command] = new List();
this.receivedMessageTracker[message.Message.Payload.Command].Add(message);
+
+ return Task.CompletedTask;
}
public override object Clone()
diff --git a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ProofOfWorkSpendingSteps.cs b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ProofOfWorkSpendingSteps.cs
index beb87a1096..c23a47e913 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ProofOfWorkSpendingSteps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ProofOfWorkSpendingSteps.cs
@@ -91,7 +91,7 @@ private async Task spending_the_coins_from_original_block()
.BuildTransaction(transactionBuildContext);
await this.sendingStratisBitcoinNode.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(this.lastTransaction.ToHex()));
+ .SendTransactionAsync(new SendTransactionRequest(this.lastTransaction.ToHex()));
}
catch (Exception exception)
{
diff --git a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ReorgToLongestChainSteps.cs b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ReorgToLongestChainSteps.cs
index 57e4048aec..4f46848d1a 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ReorgToLongestChainSteps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/ReorgToLongestChainSteps.cs
@@ -100,7 +100,7 @@ private void bob_creates_a_transaction_and_broadcasts()
this.shorterChainTransaction = this.bobNode.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);
Money shortChainTransactionFee = this.bobNode.FullNode.WalletTransactionHandler().EstimateFee(transactionBuildContext);
- this.bobNode.FullNode.NodeController().SendTransaction(new SendTransactionRequest(this.shorterChainTransaction.ToHex()));
+ this.bobNode.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(this.shorterChainTransaction.ToHex()));
}
private HdAddress GetSecondUnusedAddressToAvoidClashWithMiningAddress(CoreNode node)
diff --git a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/RetrieveFromBlockStoreSteps.cs b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/RetrieveFromBlockStoreSteps.cs
index 68d9646b73..31a021a8d8 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/BlockStore/RetrieveFromBlockStoreSteps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/BlockStore/RetrieveFromBlockStoreSteps.cs
@@ -114,7 +114,7 @@ private async Task a_real_transaction()
this.transaction = this.node.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);
await this.node.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(this.transaction.ToHex()));
+ .SendTransactionAsync(new SendTransactionRequest(this.transaction.ToHex()));
}
private void the_block_with_the_transaction_is_mined()
diff --git a/src/Stratis.Bitcoin.IntegrationTests/MinerTests.cs b/src/Stratis.Bitcoin.IntegrationTests/MinerTests.cs
index cde8ac0094..1fae271277 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/MinerTests.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/MinerTests.cs
@@ -181,7 +181,7 @@ public async Task InitializeAsync()
foreach (var ruleType in this.network.Consensus.ConsensusRules.HeaderValidationRules)
consensusRulesContainer.HeaderValidationRules.Add(Activator.CreateInstance(ruleType) as HeaderValidationConsensusRule);
- foreach (var ruleType in network.Consensus.ConsensusRules.FullValidationRules)
+ foreach (var ruleType in this.network.Consensus.ConsensusRules.FullValidationRules)
{
FullValidationConsensusRule rule = null;
if (ruleType == typeof(FlushCoinviewRule))
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Miners/ProofOfStakeMintCoinsTest.cs b/src/Stratis.Bitcoin.IntegrationTests/Miners/ProofOfStakeMintCoinsTest.cs
index 0d29b70dab..31a782901d 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Miners/ProofOfStakeMintCoinsTest.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Miners/ProofOfStakeMintCoinsTest.cs
@@ -124,6 +124,7 @@ public void Staking_Wallet_Can_Mint_New_Coins()
///
/// Returns a snapshot of the current transactions by coin type in the first wallet.
///
+ /// See .
/// A list of TransactionData.
private List GetTransactionsSnapshot(CoreNode node)
{
diff --git a/src/Stratis.Bitcoin.IntegrationTests/RPC/ListAddressGroupingsTest.cs b/src/Stratis.Bitcoin.IntegrationTests/RPC/ListAddressGroupingsTest.cs
index 0d03030a8e..52a9a4bf3b 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/RPC/ListAddressGroupingsTest.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/RPC/ListAddressGroupingsTest.cs
@@ -135,7 +135,7 @@ private void SendCoins(CoreNode from, CoreNode to, Money coins, HdAddress toAddr
// Send 10 coins to node.
var transaction = from.FullNode.WalletTransactionHandler().BuildTransaction(WalletTests.CreateContext(from.FullNode.Network, new WalletAccountReference(walletName, accountName), password, toAddress.ScriptPubKey, coins, FeeType.Medium, 10));
- from.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction.ToHex()));
+ from.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction.ToHex()));
TestBase.WaitLoop(() => from.CreateRPCClient().GetRawMempool().Length > 0);
diff --git a/src/Stratis.Bitcoin.IntegrationTests/RPC/RPCTestsMutable.cs b/src/Stratis.Bitcoin.IntegrationTests/RPC/RPCTestsMutable.cs
index 46ece73aa7..a5c0c65f5e 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/RPC/RPCTestsMutable.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/RPC/RPCTestsMutable.cs
@@ -72,6 +72,64 @@ public void TestRpcImportPubkeyIsSuccessful()
TestHelper.ConnectAndSync(node, node2);
+ UnspentOutputReference tx = node2.FullNode.WalletManager().GetUnspentTransactionsInWallet("mywallet", 0, Features.Wallet.Wallet.NormalAccounts).First();
+
+ RPCClient rpc = node.CreateRPCClient();
+
+ PubKey pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(tx.Address.Pubkey);
+ PubKey pubKey2 = new Key().PubKey;
+
+ uint256 blockHash = rpc.GenerateToAddress(1, pubKey2.GetAddress(rpc.Network)).First();
+ Block block = rpc.GetBlock(blockHash);
+ uint256 tx2 = block.Transactions.First().GetHash();
+
+ Assert.Throws(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true));
+ Assert.Throws(() => rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), true));;
+
+ // Test that adding the same pubkey twice doesn't throw.
+ rpc.ImportPubKey(pubKey.ToHex());
+ rpc.ImportPubKey(pubKey.ToHex());
+
+ // Add a second pubkey and ensure it doesn't throw.
+ rpc.ImportPubKey(pubKey2.ToHex());
+
+ // Add an arbitrary pubkey and ensure it doesn't throw.
+ rpc.ImportPubKey(new Key().PubKey.ToHex());
+
+ TestBase.WaitLoop(() => node.FullNode.WalletManager().WalletTipHeight == node2.FullNode.WalletManager().WalletTipHeight);
+
+ TestBase.WaitLoop(() =>
+ {
+ try
+ {
+ // Check if gettransaction can now find the transactions in the watch only account.
+ RPCResponse walletTx = rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true);
+ RPCResponse walletTx2 = rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), true);
+
+ return walletTx != null && walletTx2 != null;
+ }
+ catch (RPCException)
+ {
+ return false;
+ }
+ });
+
+ // Check that when include_watchonly is not set, the watched addresses' transactions cannot be located in the normal wallet accounts.
+ Assert.Throws(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), false));
+ Assert.Throws(() => rpc.SendCommand(RPCOperations.gettransaction, tx2.ToString(), false));
+ }
+ }
+
+ [Fact]
+ public void TestRpcListUnspentForWatchOnlyIsSuccessful()
+ {
+ using (NodeBuilder builder = NodeBuilder.Create(this))
+ {
+ CoreNode node = builder.CreateStratisPowNode(new BitcoinRegTest()).AlwaysFlushBlocks().WithWallet().Start();
+ CoreNode node2 = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start();
+
+ TestHelper.ConnectAndSync(node, node2);
+
UnspentOutputReference tx = node2.FullNode.WalletManager().GetUnspentTransactionsInWallet("mywallet", 0, Features.Wallet.Wallet.NormalAccounts).First();
RPCClient rpc = node.CreateRPCClient();
@@ -82,25 +140,39 @@ public void TestRpcImportPubkeyIsSuccessful()
rpc.ImportPubKey(pubKey.ToHex());
+ // ListUnspent will not regard the outputs as spendable if they are not sufficiently mature.
+ rpc.Generate((int)node.FullNode.Network.Consensus.CoinbaseMaturity);
+
TestBase.WaitLoop(() => node.FullNode.WalletManager().WalletTipHeight == node2.FullNode.WalletManager().WalletTipHeight);
TestBase.WaitLoop(() =>
{
try
{
- // Check if gettransaction can now find the transaction in the watch only account.
+ // Wait until gettransaction can find the transaction in the watch only account.
RPCResponse walletTx = rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), true);
return walletTx != null;
}
- catch (RPCException e)
+ catch (RPCException)
{
return false;
}
});
- // Check that when include_watchonly is not set, the watched transaction cannot be located in the normal wallet accounts.
- Assert.Throws(() => rpc.SendCommand(RPCOperations.gettransaction, tx.Transaction.Id.ToString(), false));
+ UnspentCoin[] unspent = rpc.ListUnspent(1, 9999999);
+
+ bool found = false;
+
+ foreach (UnspentCoin coin in unspent)
+ {
+ if (coin.OutPoint == tx.ToOutPoint())
+ found = true;
+
+ Assert.Equal(coin.Account, Features.Wallet.Wallet.WatchOnlyAccountName);
+ }
+
+ Assert.True(found);
}
}
diff --git a/src/Stratis.Bitcoin.IntegrationTests/SegWitTests.cs b/src/Stratis.Bitcoin.IntegrationTests/SegWitTests.cs
index 3aa8a83476..6c1b25465c 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/SegWitTests.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/SegWitTests.cs
@@ -44,6 +44,7 @@ public StraxOverrideRegTest() : base()
}
// TODO: This is also used in the block store integration tests, perhaps move it into the common namespace
+
///
/// Used for recording messages coming into a test node. Does not respond to them in any way.
///
@@ -72,12 +73,14 @@ private async Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage mes
}
}
- private async Task ProcessMessageAsync(INetworkPeer peer, IncomingMessage message)
+ private Task ProcessMessageAsync(INetworkPeer peer, IncomingMessage message)
{
if (!this.receivedMessageTracker.ContainsKey(message.Message.Payload.Command))
this.receivedMessageTracker[message.Message.Payload.Command] = new List();
this.receivedMessageTracker[message.Message.Payload.Command].Add(message);
+
+ return Task.CompletedTask;
}
public override object Clone()
@@ -556,7 +559,7 @@ public void SegwitWalletTransactionBuildingAndPropagationTest()
var witAddress = destinationAddress.Bech32Address;
IActionResult transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -568,7 +571,7 @@ public void SegwitWalletTransactionBuildingAndPropagationTest()
var walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
Transaction witFunds = node.FullNode.Network.CreateTransaction(walletBuildTransactionModel.Hex);
uint witIndex = witFunds.Outputs.AsIndexedOutputs().First(o => o.TxOut.ScriptPubKey.IsScriptType(ScriptType.P2WPKH)).N;
@@ -595,7 +598,7 @@ public void SegwitWalletTransactionBuildingAndPropagationTest()
// Send a transaction that has a segwit input, to a segwit address.
transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -608,7 +611,7 @@ public void SegwitWalletTransactionBuildingAndPropagationTest()
walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
TestBase.WaitLoop(() => node.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
TestBase.WaitLoop(() => listener.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
@@ -663,7 +666,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs()
var p2wpkhAmount = Money.Coins(1);
IActionResult transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -675,7 +678,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs()
var walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
Transaction witFunds = node.FullNode.Network.CreateTransaction(walletBuildTransactionModel.Hex);
uint witIndex = witFunds.Outputs.AsIndexedOutputs().First(o => o.TxOut.ScriptPubKey.IsScriptType(ScriptType.P2WPKH)).N;
@@ -696,7 +699,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs()
// By sending more than the size of the P2WPKH UTXO, we guarantee that at least one non-P2WPKH UTXO gets included
transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -712,7 +715,7 @@ public void SegwitWalletTransactionBuildingTest_SpendP2WPKHAndNormalUTXOs()
walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
TestBase.WaitLoop(() => node.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
TestBase.WaitLoop(() => listener.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
@@ -748,7 +751,7 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination
var nonWitAddress = destinationAddress.Address;
IActionResult transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -760,7 +763,7 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination
var walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
Transaction witFunds = node.FullNode.Network.CreateTransaction(walletBuildTransactionModel.Hex);
uint witIndex = witFunds.Outputs.AsIndexedOutputs().First(o => o.TxOut.ScriptPubKey.IsScriptType(ScriptType.P2WPKH)).N;
@@ -779,7 +782,7 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination
// By sending more than the size of the P2WPKH UTXO, we guarantee that at least one non-P2WPKH UTXO gets included
transactionResult = node.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = "account 0",
AllowUnconfirmed = true,
@@ -796,7 +799,7 @@ public void SegwitWalletTransactionBuildingTest_SendToBech32AndNormalDestination
walletBuildTransactionModel = (WalletBuildTransactionModel)(transactionResult as JsonResult)?.Value;
- node.FullNode.NodeController().SendTransaction(new SendTransactionRequest(walletBuildTransactionModel.Hex));
+ _ = node.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(walletBuildTransactionModel.Hex));
TestBase.WaitLoop(() => node.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
TestBase.WaitLoop(() => listener.CreateRPCClient().GetRawMempool().Length > 0, cancellationToken: new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token);
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/ColdWalletTests.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/ColdWalletTests.cs
index ae6c9a6196..43dbf82c30 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/ColdWalletTests.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/ColdWalletTests.cs
@@ -108,6 +108,7 @@ private CoreNode CreatePowPosMiningNode(NodeBuilder nodeBuilder, Network network
/// the cold staking setup using a cold staking address obtained from the cold wallet node.
/// Success is determined by whether the balance in the cold wallet increases.
///
+ /// The asynchronous task.
[Fact]
[Trait("Unstable", "True")]
public async Task WalletCanMineWithColdWalletCoinsAsync()
@@ -151,7 +152,7 @@ public async Task WalletCanMineWithColdWalletCoinsAsync()
Transaction transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, amountToSend, FeeType.Medium, 1));
// Broadcast to the other node
- await stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction1.ToHex()));
+ await stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction1.ToHex()));
// Wait for the transaction to arrive
TestBase.WaitLoop(() => stratisHotStake.CreateRPCClient().GetRawMempool().Length > 0);
@@ -168,7 +169,7 @@ public async Task WalletCanMineWithColdWalletCoinsAsync()
coldWalletAddress.Address, hotWalletAddress.Address, WalletName, Account, Password, amountToSend2, new Money(0.02m, MoneyUnit.BTC), false, false, 1, false);
// Broadcast to the other node
- await stratisHotStake.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction2.ToHex()));
+ await stratisHotStake.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction2.ToHex()));
// Wait for the transaction to arrive
TestBase.WaitLoop(() => coldWalletManager.GetSpendableTransactionsInColdWallet(WalletName, true).Any());
@@ -233,7 +234,7 @@ public async Task CanRetrieveFilteredUtxosAsync()
Transaction transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, coldWalletAddress.ScriptPubKey, amountToSend, FeeType.Medium, 1));
// Broadcast to the other nodes.
- await stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction1.ToHex()));
+ await stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction1.ToHex()));
// Wait for the transaction to arrive.
TestBase.WaitLoop(() => stratisColdStake.CreateRPCClient().GetRawMempool().Length > 0);
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingStakedCoinsBeforeMaturity_Steps.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingStakedCoinsBeforeMaturity_Steps.cs
index e2c31d8209..c1caca5694 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingStakedCoinsBeforeMaturity_Steps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingStakedCoinsBeforeMaturity_Steps.cs
@@ -73,13 +73,13 @@ private IActionResult SendTransaction(IActionResult transactionResult)
return null;
return this.proofOfStakeSteps.PremineNodeWithCoins.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(walletTransactionModel.Hex)).GetAwaiter().GetResult();
+ .SendTransactionAsync(new SendTransactionRequest(walletTransactionModel.Hex)).GetAwaiter().GetResult();
}
private IActionResult BuildTransaction()
{
IActionResult transactionResult = this.proofOfStakeSteps.PremineNodeWithCoins.FullNode.NodeController()
- .BuildTransaction(new BuildTransactionRequest
+ .BuildTransactionAsync(new BuildTransactionRequest
{
AccountName = this.proofOfStakeSteps.PremineWalletAccount,
AllowUnconfirmed = true,
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTransactionOverPolicyByteLimitSpecification_Steps.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTransactionOverPolicyByteLimitSpecification_Steps.cs
index bf785619bd..1c73e2e56f 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTransactionOverPolicyByteLimitSpecification_Steps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTransactionOverPolicyByteLimitSpecification_Steps.cs
@@ -80,7 +80,7 @@ private void node1_builds_oversize_tx_to_send_to_node2()
private void sending_the_transaction()
{
- this.firstNode.FullNode.NodeController().SendTransaction(new SendTransactionRequest(this.transaction.ToHex(this.firstNode.FullNode.Network)));
+ this.firstNode.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(this.transaction.ToHex(this.firstNode.FullNode.Network)));
}
private void Node1BuildsTransactionToSendToNode2(int txoutputs)
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTxWithDoubleSpendSpecification_Steps.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTxWithDoubleSpendSpecification_Steps.cs
index 4c7e59e8de..9aa92f28f5 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTxWithDoubleSpendSpecification_Steps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/SendingTxWithDoubleSpendSpecification_Steps.cs
@@ -68,7 +68,7 @@ private void coins_first_sent_to_receiving_wallet()
this.transaction = this.stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(WalletTests.CreateContext(this.stratisSender.FullNode.Network,
new WalletAccountReference(Name, AccountName), Password, this.receivingAddress.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));
- this.stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(this.transaction.ToHex()));
+ this.stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(this.transaction.ToHex()));
TestBase.WaitLoop(() => this.stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
TestBase.WaitLoop(() => this.stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet(Name).Any());
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs
index 32f845b8d7..4ca3f5d3fd 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletAddressGenerationAndFundsVisibility_Steps.cs
@@ -97,7 +97,7 @@ private async Task a_wallet_with_funds_at_index_20_which_is_beyond_default_gap_l
.BuildTransaction(transactionBuildContext);
await this.sendingStratisBitcoinNode.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(transaction.ToHex()));
+ .SendTransactionAsync(new SendTransactionRequest(transaction.ToHex()));
TestHelper.MineBlocks(this.sendingStratisBitcoinNode, 1);
diff --git a/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletTests.cs b/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletTests.cs
index 2cc4e94482..ab69e7e4ab 100644
--- a/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletTests.cs
+++ b/src/Stratis.Bitcoin.IntegrationTests/Wallet/WalletTests.cs
@@ -56,7 +56,7 @@ public async Task WalletCanReceiveAndSendCorrectlyAsync()
new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));
// Broadcast to the other node
- await stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(trx.ToHex()));
+ await stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(trx.ToHex()));
// Wait for the transaction to arrive
TestBase.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
@@ -108,7 +108,7 @@ public void WalletBalanceCorrectWhenOnlySomeUnconfirmedAreIncludedInABlock()
new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));
// Broadcast to the other node
- stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(trx.ToHex()));
+ stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(trx.ToHex()));
// Wait for the transaction to arrive
TestBase.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
@@ -126,7 +126,7 @@ public void WalletBalanceCorrectWhenOnlySomeUnconfirmedAreIncludedInABlock()
sendto = stratisSender.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(WalletName, Account));
Transaction testTx1 = stratisReceiver.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network,
new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, Money.COIN * 10, FeeType.Medium, 0));
- stratisReceiver.FullNode.NodeController().SendTransaction(new SendTransactionRequest(testTx1.ToHex()));
+ stratisReceiver.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(testTx1.ToHex()));
TestBase.WaitLoop(() => stratisSender.CreateRPCClient().GetRawMempool().Length > 0);
// Disconnect so the first node doesn't get any more transactions.
@@ -228,7 +228,7 @@ public void WalletCanReorg()
Transaction transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));
// Broadcast to the other node.
- stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction1.ToHex()));
+ stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction1.ToHex()));
// Wait for the transaction to arrive.
TestBase.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
@@ -261,7 +261,7 @@ public void WalletCanReorg()
// Send more coins to the wallet
sendto = stratisReceiver.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(WalletName, Account));
Transaction transaction2 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(stratisSender.FullNode.Network, new WalletAccountReference(WalletName, Account), Password, sendto.ScriptPubKey, Money.COIN * 10, FeeType.Medium, 101));
- stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction2.ToHex()));
+ stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction2.ToHex()));
// Wait for the transaction to arrive
TestBase.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
@@ -305,7 +305,7 @@ public void WalletCanReorg()
// ReBuild Transaction 2.
// After the reorg transaction2 was returned back to mempool.
- stratisSender.FullNode.NodeController().SendTransaction(new SendTransactionRequest(transaction2.ToHex()));
+ stratisSender.FullNode.NodeController().SendTransactionAsync(new SendTransactionRequest(transaction2.ToHex()));
TestBase.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
// Mine the transaction again.
@@ -359,7 +359,7 @@ public void BuildTransaction_From_ManyUtxos_EnoughFundsForFee()
Assert.Equal(utxosToSend * howManyTimes, transactionsToSpend.Count());
// Firstly, build a tx with value 1. Previously this would fail as the WalletTransactionHandler didn't pass enough UTXOs.
- IActionResult result = node2.FullNode.NodeController().BuildTransaction(
+ IActionResult result = node2.FullNode.NodeController().BuildTransactionAsync(
new BuildTransactionRequest
{
WalletName = WalletName,
@@ -543,7 +543,7 @@ private static Result SendManyUtxosTransaction(CoreN
// Broadcast to the other node.
IActionResult result = node.FullNode.NodeController()
- .SendTransaction(new SendTransactionRequest(trx.ToHex())).GetAwaiter().GetResult();
+ .SendTransactionAsync(new SendTransactionRequest(trx.ToHex())).GetAwaiter().GetResult();
if (result is ErrorResult errorResult)
{
var errorResponse = (ErrorResponse)errorResult.Value;
diff --git a/src/Stratis.Bitcoin.Networks/Stratis.Bitcoin.Networks.csproj b/src/Stratis.Bitcoin.Networks/Stratis.Bitcoin.Networks.csproj
index e74cb1bc2b..769c576832 100644
--- a/src/Stratis.Bitcoin.Networks/Stratis.Bitcoin.Networks.csproj
+++ b/src/Stratis.Bitcoin.Networks/Stratis.Bitcoin.Networks.csproj
@@ -14,9 +14,9 @@
false
false
false
- 1.1.1.1
- 1.1.1.1
- 1.1.1.1
+ 1.2.0.0
+ 1.2.0.0
+ 1.2.0.0
False
Stratis Group Ltd.
diff --git a/src/Stratis.Bitcoin.Networks/StraxMain.cs b/src/Stratis.Bitcoin.Networks/StraxMain.cs
index 8fcd763833..12e729b574 100644
--- a/src/Stratis.Bitcoin.Networks/StraxMain.cs
+++ b/src/Stratis.Bitcoin.Networks/StraxMain.cs
@@ -167,7 +167,8 @@ public StraxMain()
{ 300_000, new CheckpointInfo(new uint256("0x35cb635c4f286b233fab6252c30f3df7813c0a76ca7ea2a90249cad73958e2d3"), new uint256("0x42e5a29b035296e3dee4f675f92c5790e0ac6cd0c9390fcf6bac9ac28ccaa850")) },
{ 450_000, new CheckpointInfo(new uint256("0xc08db6151e2f341360a28e6a796d9c4356e14085e81aed2338c05f1964ef3e27"), new uint256("0x0cfc40a07819297a39be5460f805ce391d7f9b8d5794b18c97384a6b832deb4b")) },
{ 600_000, new CheckpointInfo(new uint256("0xde6e45862b53aa12e68ebe1ce58962a35dc44c9b6357d6137d6f4d72a7799262"), new uint256("0xc1b1e2c3417c1d41e906a53028421bec3a1f8969cf38516671433c2c85ef09d3")) },
- { 700_000, new CheckpointInfo(new uint256("0x9383c8d2cb72273ec784c8bca40fd8aedb5014080b30e664e7025f9733e28cd4"), new uint256("0x2a90ab7ce85e1733631282f9cc392aa8b6f8a352234a8c992d38ff1651b039af")) }
+ { 700_000, new CheckpointInfo(new uint256("0x9383c8d2cb72273ec784c8bca40fd8aedb5014080b30e664e7025f9733e28cd4"), new uint256("0x2a90ab7ce85e1733631282f9cc392aa8b6f8a352234a8c992d38ff1651b039af")) },
+ { 750_000, new CheckpointInfo(new uint256("0x16a24a00b59bf1f0a366be26f6da9bc12814f315cbaac6b536494555f065f5d0"), new uint256("0x54426d468d84dd4b54adbedf62458c175235e23af537876150853738b6adfacf")) }
};
this.Bech32Encoders = new Bech32Encoder[2];
diff --git a/src/Stratis.Bitcoin.Networks/StraxTest.cs b/src/Stratis.Bitcoin.Networks/StraxTest.cs
index 53a28f46dc..9aeffdcc57 100644
--- a/src/Stratis.Bitcoin.Networks/StraxTest.cs
+++ b/src/Stratis.Bitcoin.Networks/StraxTest.cs
@@ -155,6 +155,7 @@ public StraxTest()
{ 500_000, new CheckpointInfo(new uint256("0xda5da5c0ac8f34e89d6d308e1a046e98e46080941670e327d9eb84dc859d153f"), new uint256("0x1f73717627345bdc6d7b9b521dcea85df2586208a6d3a90fcd2efd16dcf9c591")) },
{ 650_000, new CheckpointInfo(new uint256("0x50b2ddb88c5efe942d8bf6a07bed996f44b3b663df0f77d5d88ad1adba48329b"), new uint256("0xb507c86a412b9e50d0bed3be52a9042c2dbaca6653ff6ccb3e2e355c24c73a70")) },
{ 750_000, new CheckpointInfo(new uint256("0x592842f3e5af517b0ce6f451f6b61738a6dea1007ccbaab39f22878de8de78dc"), new uint256("0x6ee053737f80a3a5173c10a507b1d1ea2ec9f6fa6be07b2b9d26558e4622f4a4")) },
+ { 800_000, new CheckpointInfo(new uint256("0x70c51661a4b358c42984019ee5dac9faee2f724860f651f8d78ed309e137f957"), new uint256("0x82ddde3f4e73a2eb69907b3f07f1f70f4c3b7e95812590fdef1050afb253cf84")) },
};
this.Bech32Encoders = new Bech32Encoder[2];
diff --git a/src/Stratis.Bitcoin.Tests.Common/ReflectionExtensions.cs b/src/Stratis.Bitcoin.Tests.Common/ReflectionExtensions.cs
index c677c4a895..3df78c9d47 100644
--- a/src/Stratis.Bitcoin.Tests.Common/ReflectionExtensions.cs
+++ b/src/Stratis.Bitcoin.Tests.Common/ReflectionExtensions.cs
@@ -30,7 +30,11 @@ public static object GetMemberValue(this object obj, string memberName)
throw new Exception();
}
- /// Gets private constant member of specified type.
+ /// Gets a static private constant member of specified type.
+ /// The type containing the static private constant.
+ /// The name of the static private constant.
+ /// The type of the static private constant.
+ /// The value of the static private constant.
public static T GetPrivateConstantValue(this Type type, string constantName)
{
T value = type
@@ -71,6 +75,11 @@ private static MemberInfo GetMemberInfo(object obj, string memberName)
}
/// Calls private method using reflection.
+ /// The object containing the method to invoke.
+ /// The name of the method to invoke.
+ /// The arguments to be passed to .
+ /// The type of the object containing the method to invoke.
+ /// An object containing the return value of the invoked method, or null in the case of a constructor.
public static object InvokeMethod(this T obj, string methodName, params object[] args)
{
Type type = typeof(T);
diff --git a/src/Stratis.Bitcoin.Tests.Common/Stratis.Bitcoin.Tests.Common.csproj b/src/Stratis.Bitcoin.Tests.Common/Stratis.Bitcoin.Tests.Common.csproj
index 43125911d7..44f9525e99 100644
--- a/src/Stratis.Bitcoin.Tests.Common/Stratis.Bitcoin.Tests.Common.csproj
+++ b/src/Stratis.Bitcoin.Tests.Common/Stratis.Bitcoin.Tests.Common.csproj
@@ -13,7 +13,7 @@
false
false
false
- 1.1.1.1
+ 1.2.0.0
False
diff --git a/src/Stratis.Bitcoin.Tests.Common/TestBase.cs b/src/Stratis.Bitcoin.Tests.Common/TestBase.cs
index 517f31855a..74619dccb9 100644
--- a/src/Stratis.Bitcoin.Tests.Common/TestBase.cs
+++ b/src/Stratis.Bitcoin.Tests.Common/TestBase.cs
@@ -20,6 +20,7 @@ public class TestBase
///
/// Initializes logger factory for inherited tests.
///
+ /// The network context.
public TestBase(Network network)
{
this.Network = network;
@@ -37,6 +38,7 @@ public static DirectoryInfo AssureEmptyDir(string dir)
///
/// The calling object, from which we derive the namespace in which the test is contained.
/// The name of the test being executed. A directory with the same name will be created.
+ /// The network context.
/// The that was initialized.
public static DataFolder CreateDataFolder(object caller, [System.Runtime.CompilerServices.CallerMemberName] string callingMethod = "", Network network = null)
{
@@ -153,6 +155,7 @@ public ProvenBlockHeader CreateNewProvenBlockHeaderMock(PosBlock posBlock = null
/// Creates a list of Proof of Stake blocks.
///
/// The amount of blocks to create.
+ /// The list of Pos entries.
public List CreatePosBlocks(int amount)
{
var blocks = new List();
diff --git a/src/Stratis.Bitcoin.Tests/Base/ChainRepositoryTest.cs b/src/Stratis.Bitcoin.Tests/Base/ChainRepositoryTest.cs
index 26a3c968b2..a6a406cb78 100644
--- a/src/Stratis.Bitcoin.Tests/Base/ChainRepositoryTest.cs
+++ b/src/Stratis.Bitcoin.Tests/Base/ChainRepositoryTest.cs
@@ -74,8 +74,7 @@ public void LoadChainFromDisk()
foreach (ChainedHeader block in blocks)
{
batch.Put(1, BitConverter.GetBytes(block.Height),
- new ChainRepository.ChainRepositoryData()
- { Hash = block.HashBlock, Work = block.ChainWorkBytes }
+ new ChainRepository.ChainRepositoryData(block.HashBlock, block.ChainWorkBytes)
.ToBytes(this.Network.Consensus.ConsensusFactory));
ConsensusFactory consensusFactory = KnownNetworks.StraxRegTest.Consensus.ConsensusFactory;
diff --git a/src/Stratis.Bitcoin.Tests/BlockPulling/BlockPullerTestsHelper.cs b/src/Stratis.Bitcoin.Tests/BlockPulling/BlockPullerTestsHelper.cs
index c1dd127997..d1695052df 100644
--- a/src/Stratis.Bitcoin.Tests/BlockPulling/BlockPullerTestsHelper.cs
+++ b/src/Stratis.Bitcoin.Tests/BlockPulling/BlockPullerTestsHelper.cs
@@ -50,12 +50,18 @@ public BlockPullerTestsHelper()
}
/// Creates a peer with extended puller behavior.
+ /// The .
+ /// Iff true overrides the version with .
+ /// The .
public INetworkPeer CreatePeer(out ExtendedBlockPullerBehavior mockedBehavior, bool notSupportedVersion = false)
{
return this.CreatePeerMock(out mockedBehavior, notSupportedVersion).Object;
}
/// Creates a peer with extended puller behavior.
+ /// The .
+ /// Iff true overrides the version with .
+ /// The mocked .
public Mock CreatePeerMock(out ExtendedBlockPullerBehavior mockedBehavior, bool notSupportedVersion = false)
{
var peer = new Mock();
@@ -100,6 +106,8 @@ private ExtendedBlockPullerBehavior CreateBlockPullerBehavior()
}
/// Creates a new block with mocked serialized size.
+ /// The value for .
+ /// The .
public Block GenerateBlock(long size)
{
Block block = new StraxMain().Consensus.ConsensusFactory.CreateBlock();
diff --git a/src/Stratis.Bitcoin.Tests/Consensus/CheckpointsTest.cs b/src/Stratis.Bitcoin.Tests/Consensus/CheckpointsTest.cs
index df42af9f72..32d8550539 100644
--- a/src/Stratis.Bitcoin.Tests/Consensus/CheckpointsTest.cs
+++ b/src/Stratis.Bitcoin.Tests/Consensus/CheckpointsTest.cs
@@ -74,7 +74,7 @@ public void GetLastCheckPointHeight_StraxMainnet_ReturnsLastCheckPointHeight()
int result = checkpoints.GetLastCheckpointHeight();
- Assert.Equal(700_000, result);
+ Assert.Equal(750_000, result);
}
[Fact]
@@ -84,7 +84,7 @@ public void GetLastCheckPointHeight_StraxTestnet_ReturnsLastCheckPointHeight()
int result = checkpoints.GetLastCheckpointHeight();
- Assert.Equal(750_000, result);
+ Assert.Equal(800_000, result);
}
[Fact]
diff --git a/src/Stratis.Bitcoin.Tests/Controllers/NodeControllerTest.cs b/src/Stratis.Bitcoin.Tests/Controllers/NodeControllerTest.cs
index df7a3dba37..8b6c538072 100644
--- a/src/Stratis.Bitcoin.Tests/Controllers/NodeControllerTest.cs
+++ b/src/Stratis.Bitcoin.Tests/Controllers/NodeControllerTest.cs
@@ -526,7 +526,7 @@ public void GetBlockHeader_NotUsingJsonFormat_ThrowsNotImplementedException()
Assert.Single(errorResponse.Errors);
ErrorModel error = errorResponse.Errors[0];
Assert.Equal(400, error.Status);
- Assert.StartsWith("System.NotImplementedException", error.Description);
+ Assert.StartsWith("Binary serialization is not", error.Description);
}
[Fact]
@@ -555,10 +555,7 @@ public void GetBlockHeader_BlockHeaderNotFound_ReturnsNull()
string hash = new uint256(2562).ToString();
bool isJsonFormat = true;
- var json = (JsonResult)this.controller.GetBlockHeader(hash, isJsonFormat);
- var resultModel = (BlockHeaderModel)json.Value;
-
- Assert.Null(resultModel);
+ Assert.IsType(this.controller.GetBlockHeader(hash, isJsonFormat));
}
[Fact]
diff --git a/src/Stratis.Bitcoin.Tests/Utilities/AsyncProviderTest.cs b/src/Stratis.Bitcoin.Tests/Utilities/AsyncProviderTest.cs
index cc258e15b2..30533be405 100644
--- a/src/Stratis.Bitcoin.Tests/Utilities/AsyncProviderTest.cs
+++ b/src/Stratis.Bitcoin.Tests/Utilities/AsyncProviderTest.cs
@@ -36,6 +36,7 @@ public AsyncProviderTest()
///
/// Tests that