diff --git a/.vs/ProjectSettings.json b/.vs/ProjectSettings.json new file mode 100644 index 0000000..f8b4888 --- /dev/null +++ b/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": null +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6b61141 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..e8a4873 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/IotaApi.Standard.Tests/IotaApi.Standard.Tests.csproj b/IotaApi.Standard.IntegrationTests/IotaApi.Standard.IntegrationTests.csproj similarity index 56% rename from IotaApi.Standard.Tests/IotaApi.Standard.Tests.csproj rename to IotaApi.Standard.IntegrationTests/IotaApi.Standard.IntegrationTests.csproj index 895f697..c4247ae 100644 --- a/IotaApi.Standard.Tests/IotaApi.Standard.Tests.csproj +++ b/IotaApi.Standard.IntegrationTests/IotaApi.Standard.IntegrationTests.csproj @@ -5,14 +5,14 @@ false - Iota.Api.Standard.Tests + Iota.Api.Standard.IntegrationTests - - - - + + + + diff --git a/IotaApi.Standard.Tests/IotaApiTests.cs b/IotaApi.Standard.IntegrationTests/IotaApiTests.cs similarity index 57% rename from IotaApi.Standard.Tests/IotaApiTests.cs rename to IotaApi.Standard.IntegrationTests/IotaApiTests.cs index 3870ded..f116352 100644 --- a/IotaApi.Standard.Tests/IotaApiTests.cs +++ b/IotaApi.Standard.IntegrationTests/IotaApiTests.cs @@ -2,48 +2,46 @@ using System.Collections.Generic; using Iota.Api.Standard.Exception; using Iota.Api.Standard.Model; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Xunit; -namespace Iota.Api.Standard.Tests +namespace Iota.Api.Standard.IntegrationTests { - [TestClass] public class IotaApiTests { - private static readonly string TEST_SEED1 = + private const string TEST_SEED1 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static readonly string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1 = + private const string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1 = "MALAZGDVZIAQQRTNYJDSZMY9VE9LAHQKTVCUOAGZUCX9IBUMODFFTMGUIUAXGLWZQ9CYRSLYBM9QBIBYAEIAOPKXEA"; - private static readonly string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2 = + private const string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; - private static readonly string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3 = + private const string TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3 = "ASCZZOBQDMNHLELQKWJBMRETMHBTF9V9TNKYDIFW9PDXPUHPVVGHMSWPVMNJHSJF99QFCMNTPCPGS9DT9XAFKJVO9X"; - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1 = + private const string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1 = "MALAZGDVZIAQQRTNYJDSZMY9VE9LAHQKTVCUOAGZUCX9IBUMODFFTMGUIUAXGLWZQ9CYRSLYBM9QBIBYA"; - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = + private const string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3 = + private const string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3 = "ASCZZOBQDMNHLELQKWJBMRETMHBTF9V9TNKYDIFW9PDXPUHPVVGHMSWPVMNJHSJF99QFCMNTPCPGS9DT9"; - private static readonly string TEST_SEED2 = + private const string TEST_SEED2 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static readonly string TEST_HASH = - "9XWWWXVQYPKLVMAMFPXFSE9UCAGVY9RZO9NHGAZEXIRIJRZULGMFOJNDKUNFUCSURWRDDPVMYG9X99999"; //06/02/2018,04:36 + private const string TEST_HASH = + "9XWWWXVQYPKLVMAMFPXFSE9UCAGVY9RZO9NHGAZEXIRIJRZULGMFOJNDKUNFUCSURWRDDPVMYG9X99999"; - private static readonly string TEST_TRYTES = + private const string TEST_TRYTES = "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCQ9CA9TA99999999999999999999XC9999999999999999999999999TPLCUYD99999999999B99999999WFVTNIRLVFIVKAQEEDFRWWLXIPHRQNG9EAY9QEWRFDLECXDGJLIKBAKBYPTAZPISWVXJLBJISGGLWTBVDNBEBXBG9PZHPK9SVNH99LZVXYZSVODZZIIXNJJQAYXCNKISVFVXGVQMURVEMSDGLRLZADQCOHRHW99999K9SYJTSNRZVYWGSV9AXVTPKMTLHPCTIJGNNAMALVPQUCGCZXZFFUQSXCHPSJLXBADVOIZO9PSZYTA9999XC9999999999999999999999999WWF9MWCJE999999999MMMMMMMMMPRQAGSHN9ZHEWVAANNPXSDRRROY"; - private static readonly string TEST_MESSAGE = "COTA"; - private static readonly string TEST_TAG = "COTASPAM9999999999999999999"; + private const string TEST_MESSAGE = "COTA"; + private const string TEST_TAG = "COTASPAM9999999999999999999"; - // ReSharper disable once InconsistentNaming - private static readonly string[] TEST_ADDRESSES = + private readonly string[] TEST_ADDRESSES = { "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC", "P9UDUZMN9DEXCRQEKLJYSBSBZFCHOBPJSDKMLCCVJDOVOFDWMNBZRIRRZJGINOUMPJBMYYZEGRTIDUABD", @@ -68,190 +66,154 @@ public class IotaApiTests "KVEBCGMEOPDPRCQBPIEMZTTXYBURGZVNH9PLHKPMM9D9FUKWIGLKZROGNSYIFHULLWQWXCNAW9HKKVIDC" }; - private static readonly string TestTrytesValid = + private const string TESTTRYTESVALID = "JUSTANOTHERTEST999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTH999999999999999999999999999COTASPAM9999999999999999999VISYF9DGE999999999999999999FB9CRHGOHK9EIDHDUWSGDDONYQAABTRXXMFUKRZHMVJAPCAADTRDCWZJRHAPL9LRIVZFVKQV9GAWSSJZDPWGPQTPWCPNYONYGGSJLJAQYXLZ9FMOTUJT9RIXAOXFDQZSTZYBCHSNLSM9JAXTMNQBUHAAZIIR999999PWGPQTPWCPNYONYGGSJLJAQYXLZ9FMOTUJT9RIXAOXFDQZSTZYBCHSNLSM9JAXTMNQBUHAAZIIR999999KXOQZNGXOCACOVYKPWWJFQQMEWDQVUZRI99WFQEJANSOPVLZGQHLUEYKPYPMSTLDRDVEBMCQMKQLL9JFS"; - private static int MIN_WEIGHT_MAGNITUDE = 14; - private static int DEPTH = 9; + private const int MIN_WEIGHT_MAGNITUDE = 14; + private const int DEPTH = 9; private IotaApi _iotaClient; - [TestInitialize] - public void CreateApiClientInstance() + public IotaApiTests() { _iotaClient = new IotaApi("node.iotawallet.info", 14265); } - [TestMethod] + [Fact] public void ShouldGetInputs() { - var res = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 0); - Console.WriteLine(res); - Assert.IsNotNull(res); - Assert.IsNotNull(res.TotalBalance); - Assert.IsNotNull(res.InputsList); + Inputs response = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 0); + + Assert.NotNull(response); + Assert.True(response.TotalBalance >= 0); + Assert.NotNull(response.InputsList); } - [TestMethod] + [Fact] public void ShouldCreateANewAddressWithChecksum() { - // ReSharper disable RedundantArgumentDefaultValue - var res1 = _iotaClient.GetNewAddress(TEST_SEED1, 1, 0, true, 5, false); - Assert.AreEqual(res1[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1); - - var res2 = _iotaClient.GetNewAddress(TEST_SEED1, 2, 0, true, 5, false); - Assert.AreEqual(res2[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2); - - var res3 = _iotaClient.GetNewAddress(TEST_SEED1, 3, 0, true, 5, false); - Assert.AreEqual(res3[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3); - // ReSharper restore RedundantArgumentDefaultValue + string[] addressesFromSeed_01 = _iotaClient.GetNewAddress(TEST_SEED1, 1, 0, true, 5, false); + string[] addressesFromSeed_02 = _iotaClient.GetNewAddress(TEST_SEED1, 2, 0, true, 5, false); + string[] addressesFromSeed_03 = _iotaClient.GetNewAddress(TEST_SEED1, 3, 0, true, 5, false); + + Assert.NotEmpty(addressesFromSeed_01); + Assert.NotEmpty(addressesFromSeed_02); + Assert.NotEmpty(addressesFromSeed_03); + Assert.Equal(addressesFromSeed_01[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1); + Assert.Equal(addressesFromSeed_02[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2); + Assert.Equal(addressesFromSeed_03[0], TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3); } - [TestMethod] + [Fact] public void ShouldCreateANewAddressWithoutChecksum() { - // ReSharper disable RedundantArgumentDefaultValue - var res1 = _iotaClient.GetNewAddress(TEST_SEED1, 1, 0, false, 5, false); - Assert.AreEqual(res1[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1); - - var res2 = _iotaClient.GetNewAddress(TEST_SEED1, 2, 0, false, 5, false); - Assert.AreEqual(res2[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2); - - var res3 = _iotaClient.GetNewAddress(TEST_SEED1, 3, 0, false, 5, false); - Assert.AreEqual(res3[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3); - // ReSharper restore RedundantArgumentDefaultValue + string[] addressesFromSeed_01 = _iotaClient.GetNewAddress(TEST_SEED1, 1, 0, false, 5, false); + string[] addressesFromSeed_02 = _iotaClient.GetNewAddress(TEST_SEED1, 2, 0, false, 5, false); + string[] addressesFromSeed_03 = _iotaClient.GetNewAddress(TEST_SEED1, 3, 0, false, 5, false); + + Assert.NotEmpty(addressesFromSeed_01); + Assert.NotEmpty(addressesFromSeed_02); + Assert.NotEmpty(addressesFromSeed_03); + Assert.Equal(addressesFromSeed_01[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1); + Assert.Equal(addressesFromSeed_02[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2); + Assert.Equal(addressesFromSeed_03[0], TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3); } - [TestMethod] + [Fact] public void ShouldCreate100Addresses() { - // ReSharper disable RedundantArgumentDefaultValue var res = _iotaClient.GetNewAddress(TEST_SEED1, 2, 0, false, 100, false); - Assert.AreEqual(res.Length, 100); - // ReSharper restore RedundantArgumentDefaultValue + + Assert.Equal(100, res.Length); } - [TestMethod] - [ExpectedException(typeof(NotEnoughBalanceException))] - public void ShouldPrepareTransfer() + [Fact] + public void ShouldPrepareTransferWithoutInputs() { - var transfers = new List + List transfers = new List { - new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 100, TEST_MESSAGE, TEST_TAG), + new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG), }; - var trytes = _iotaClient.PrepareTransfers(TEST_SEED1, 2, transfers.ToArray(), null, null, false); + List trytes = _iotaClient.PrepareTransfers(TEST_SEED1, 2, transfers.ToArray(), null, null, false); - Assert.IsNotNull(trytes); - Assert.IsFalse(trytes.Count == 0); + Assert.NotNull(trytes); + Assert.False(trytes.Count == 0); } - //seed contains 0 balance - [TestMethod] - [ExpectedException(typeof(NotEnoughBalanceException))] - public void ShouldPrepareTransferWithInputs() + [Fact] + public void ShouldFailToPrepareTransferWithoutEnoughBalance() { List inputlist = new List(); List transfers = new List(); - var inputs = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 0); - + Inputs inputs = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 0); inputlist.AddRange(inputs.InputsList); transfers.Add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 100, TEST_MESSAGE, TEST_TAG)); - List trytes = - _iotaClient.PrepareTransfers(TEST_SEED1, 2, transfers.ToArray(), null, inputlist, true); - Assert.IsNotNull(trytes); - Assert.IsFalse(trytes.Count == 0); + Assert.Throws( + () => _iotaClient.PrepareTransfers(TEST_SEED1, 2, transfers.ToArray(), null, inputlist, true) + ); } - [TestMethod] + [Fact] public void ShouldGetLastInclusionState() { - var res = _iotaClient.GetLatestInclusion(new[] {TEST_HASH}); - Assert.IsNotNull(res.States); + Core.GetInclusionStatesResponse response = _iotaClient.GetLatestInclusion(new[] {TEST_HASH}); + + Assert.NotNull(response.States); } - [TestMethod] + [Fact] public void ShouldFindTransactionObjects() { - var ftr = _iotaClient.FindTransactionObjects(TEST_ADDRESSES); - Assert.IsNotNull(ftr); - } + List foundTransactions = _iotaClient.FindTransactionObjects(TEST_ADDRESSES); - [TestMethod] - public void ShouldGetAccountData() - { - var accountData = _iotaClient.GetAccountData(TEST_SEED1, 2, 0, true, 0, true, 0, 0, true, 0); - Assert.IsNotNull(accountData); + Assert.NotNull(foundTransactions); } - [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void ShouldNotGetBundle() + [Fact] + public void ShouldGetAccountData() { - var bundle = _iotaClient.GetBundle("SADASD"); - Assert.IsNotNull(bundle); - } + AccountData accountData = _iotaClient.GetAccountData(TEST_SEED1, 2, 0, true, 0, true, 0, 0, true, 0); - [TestMethod] - public void ShouldGetBundle() - { - var bundle = _iotaClient.GetBundle(TEST_HASH); - Assert.IsNotNull(bundle); + Assert.NotNull(accountData); } - [TestMethod] + //[Fact] + //public void ShouldNotGetBundle() + //{ + // Bundle bundle = _iotaClient.GetBundle("SADASD"); + // Assert.NotNull(bundle); + //} + + //[Fact] + //public void ShouldGetBundle() + //{ + // var bundle = _iotaClient.GetBundle(TEST_HASH); + // Assert.NotNull(bundle); + //} + + [Fact] public void ShouldGetTransfers() { - // ReSharper disable RedundantArgumentDefaultValue var gtr = _iotaClient.GetTransfers(TEST_SEED1, 2, 0, 0, false); - // ReSharper restore RedundantArgumentDefaultValue - - foreach (var b in gtr) Assert.IsTrue(b.Transactions.TrueForAll(t => t != null)); - } - - [Ignore] - [TestMethod] - public void ShouldReplayBundle() - { - var replayedList = _iotaClient.ReplayBundle(TEST_HASH, DEPTH, MIN_WEIGHT_MAGNITUDE); - Assert.IsNotNull(replayedList); - } - [Ignore] - [TestMethod] - [ExpectedException(typeof(ArgumentException))] - public void ShouldNotSendTrytes() - { - _iotaClient.SendTrytes(new[] {TEST_TRYTES}, 9); + foreach (var b in gtr) Assert.True(b.Transactions.TrueForAll(t => t != null)); } - [TestMethod] - public void ShouldGetTrytes() - { - _iotaClient.GetTrytes(TEST_HASH); - } + //[Fact] + //public void ShouldReplayBundle() + //{ + // var replayedList = _iotaClient.ReplayBundle(TEST_HASH, DEPTH, MIN_WEIGHT_MAGNITUDE); - [TestMethod] - public void ShouldBroadcastAndStore() - { - _iotaClient.BroadcastAndStore(new List {TEST_TRYTES}); - } - - [Ignore] - [TestMethod] - public void ShouldSendTrytes() - { - _iotaClient.SendTrytes(new[] {TestTrytesValid}, 9); - } + // Assert.NotNull(replayedList); + //} - [Ignore] - [TestMethod] - [ExpectedException(typeof(IllegalStateException))] + [Fact] public void ShouldNotSendTransfer() { Transfer[] transfers = @@ -259,43 +221,39 @@ public void ShouldNotSendTransfer() new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 2, TEST_MESSAGE, TEST_TAG) }; - var result = _iotaClient.SendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null, - false, true); - Assert.IsNotNull(result); + Assert.Throws( + () => _iotaClient.SendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null,false, true) + ); } - [Ignore] - [TestMethod] - public void ShouldSendTransferWithoutInputs() - { - var transfers = new List - { - new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, "JUSTANOTHERTEST", TEST_TAG) - }; + //[Fact] + //public void ShouldSendTransferWithoutInputs() + //{ + // var transfers = new List + // { + // new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, "JUSTANOTHERTEST", TEST_TAG) + // }; - var str = _iotaClient.SendTransfer(TEST_SEED2, 2, 9, 14, transfers.ToArray(), null, null, false, true); + // var str = _iotaClient.SendTransfer(TEST_SEED2, 2, 9, 14, transfers.ToArray(), null, null, false, true); - Assert.IsNotNull(str); - } + // Assert.NotNull(str); + //} - [Ignore] - [TestMethod] - public void ShouldSendTransferWithInputs() - { - List inputlist = new List(); - List transfers = new List(); + //[Fact] + //public void ShouldSendTransferWithInputs() + //{ + // List inputlist = new List(); + // List transfers = new List(); - var inputs = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 1); + // Inputs inputs = _iotaClient.GetInputs(TEST_SEED1, 2, 0, 0, 1); - inputlist.AddRange(inputs.InputsList); + // inputlist.AddRange(inputs.InputsList); - transfers.Add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, TEST_MESSAGE, TEST_TAG)); + // transfers.Add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, TEST_MESSAGE, TEST_TAG)); - var str = _iotaClient.SendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), - inputlist.ToArray(), null, - true, true); + // var str = _iotaClient.SendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), inputlist.ToArray(), null, true, true); - Assert.IsNotNull(str); - } + // Assert.NotNull(str); + //} } } \ No newline at end of file diff --git a/IotaApi.Standard.IntegrationTests/IotaCoreApiTest.cs b/IotaApi.Standard.IntegrationTests/IotaCoreApiTest.cs new file mode 100644 index 0000000..2dc1370 --- /dev/null +++ b/IotaApi.Standard.IntegrationTests/IotaCoreApiTest.cs @@ -0,0 +1,154 @@ +using System.Linq; +using Iota.Api.Standard.Exception; +using Xunit; + +namespace Iota.Api.Standard.IntegrationTests +{ + public class IotaCoreApiTest + { + private static readonly string TEST_BUNDLE = + "XZKJUUMQOYUQFKMWQZNTFMSS9FKJLOEV9DXXXWPMQRTNCOUSUQNTBIJTVORLOQPLYZOTMLFRHYKMTGZZU"; + + private static readonly string TEST_ADDRESS_WITH_CHECKSUM = + "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA"; + + private static readonly string TEST_HASH = + "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"; + + private static IotaApi _iotaApi; + + public IotaCoreApiTest() + { + _iotaApi = new IotaApi("node.iotawallet.info", 14265); + } + + [Fact] + public void ShouldGetNodeInfo() + { + var nodeInfo = _iotaApi.GetNodeInfo(); + Assert.NotNull(nodeInfo.AppVersion); + Assert.NotNull(nodeInfo.AppName); + Assert.NotNull(nodeInfo.JreVersion); + } + + [Fact] + public void ShouldGetNeighbors() + { + var neighbors = _iotaApi.GetNeighbors(); + Assert.NotNull(neighbors.Neighbors); + } + + [Fact] + public void ShouldAddNeighbors() + { + try + { + var response = _iotaApi.AddNeighbors("udp://8.8.8.8:14265"); + Assert.NotNull(response); + } + catch (IotaApiException e) + { + Assert.Contains("not available on this node", e.Message); + } + } + + [Fact] + public void ShouldRemoveNeighbors() + { + try + { + var response = _iotaApi.RemoveNeighbors("udp://8.8.8.8:14265"); + Assert.NotNull(response); + } + catch (IotaApiException e) + { + Assert.Contains("not available on this node", e.Message); + } + } + + [Fact] + public void ShouldGetTips() + { + var tips = _iotaApi.GetTips(); + Assert.NotNull(tips); + } + + [Fact] + public void ShouldFindTransactionsByAddresses() + { + var trans = _iotaApi.FindTransactionsByAddresses(TEST_ADDRESS_WITH_CHECKSUM); + Assert.NotNull(trans.Hashes); + Assert.True(trans.Hashes.Count > 0); + } + + [Fact] + public void ShouldFindTransactionsByApprovees() + { + var trans = _iotaApi.FindTransactionsByApprovees(TEST_HASH); + Assert.NotNull(trans.Hashes); + } + + [Fact] + public void ShouldFindTransactionsByBundles() + { + var trans = _iotaApi.FindTransactionsByBundles(TEST_HASH); + Assert.NotNull(trans.Hashes); + } + + [Fact] + public void ShouldFindTransactionsByDigests() + { + var trans = _iotaApi.FindTransactionsByDigests(TEST_HASH); + Assert.NotNull(trans.Hashes); + } + + [Fact] + public void ShouldGetTrytes() + { + var response = _iotaApi.GetTrytes(TEST_HASH); + Assert.NotNull(response.Trytes); + } + + [Fact] + public void ShouldThrowOnInvalidMileStone() + { + Assert.Throws( + () => _iotaApi.GetInclusionStates(new[] { TEST_HASH }, new[] { "DNSBRJWNOVUCQPILOQIFDKBFJMVOTGHLIMLLRXOHFTJZGRHJUEDAOWXQRYGDI9KHYFGYDWQJZKX999999" }) + ); + } + + [Fact] + public void ShouldGetInclusionStates() + { + var response = _iotaApi.GetInclusionStates( new[] {TEST_HASH}, new[] {_iotaApi.GetNodeInfo().LatestSolidSubtangleMilestone}); + Assert.NotNull(response.States); + } + + [Fact] + public void ShouldGetTransactionsToApprove() + { + var response = _iotaApi.GetTransactionsToApprove(7); + + Assert.NotNull(response.TrunkTransaction); + Assert.NotNull(response.BranchTransaction); + } + + [Fact] + public void ShouldFindTransactions() + { + var test = TEST_BUNDLE; + // responseharper disable once UnusedVariable + var responsep = _iotaApi.FindTransactions(new[] {test}.ToList(), + new[] {test}.ToList(), new[] {test}.ToList(), new[] {test}.ToList()); + } + + [Fact] + public void ShouldGetBalances() + { + var response = _iotaApi.GetBalances(new[] {TEST_ADDRESS_WITH_CHECKSUM}.ToList(), 100); + Assert.NotNull(response.Balances); + Assert.NotNull(response.References); + Assert.False(response.MilestoneIndex == 0); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard.IntegrationTests/LocalPoWTest.cs b/IotaApi.Standard.IntegrationTests/LocalPoWTest.cs new file mode 100644 index 0000000..4767637 --- /dev/null +++ b/IotaApi.Standard.IntegrationTests/LocalPoWTest.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using Iota.Api.Standard.Model; +using Iota.Api.Standard.Pow; +using Xunit; + +namespace Iota.Api.Standard.IntegrationTests +{ + public class LocalPoWTest + { + private const string TEST_SEED1 = + "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; + + private const string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = + "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; + + private const string TEST_MESSAGE = "JUSTANOTHERJOTATEST"; + private const string TEST_TAG = "JOTASPAM9999999999999999999"; + private const int MIN_WEIGHT_MAGNITUDE = 14; + private const int DEPTH = 9; + + private IotaApi _iotaClient; + + public LocalPoWTest() + { + _iotaClient = new IotaApi("node.iotawallet.info", 14265) + { + LocalPow = new PearlDiverLocalPoW() + }; + } + + [Fact] + public void ShouldSendTransfer() + { + var transfers = new List + { + new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG) + }; + var result = _iotaClient.SendTransfer( TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), null, null, false, false); + Assert.NotNull(result); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Utils/MultisigTest.cs b/IotaApi.Standard.IntegrationTests/MultisigTest.cs similarity index 84% rename from IotaApi.Standard.Tests/Utils/MultisigTest.cs rename to IotaApi.Standard.IntegrationTests/MultisigTest.cs index 51ec308..ac5d440 100644 --- a/IotaApi.Standard.Tests/Utils/MultisigTest.cs +++ b/IotaApi.Standard.IntegrationTests/MultisigTest.cs @@ -3,11 +3,10 @@ using Iota.Api.Standard.Model; using Iota.Api.Standard.Pow; using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Xunit; -namespace Iota.Api.Standard.Tests.Utils +namespace Iota.Api.Standard.IntegrationTests { - [TestClass] public class MultisigTest { private const string TestSeed1 = "ABCDFG"; @@ -24,13 +23,12 @@ public class MultisigTest private IotaApi _iotaClient; - [TestInitialize] - public void CreateApiClientInstance() + public MultisigTest() { _iotaClient = new IotaApi("node.iotawallet.info", 14265); } - [TestMethod] + [Fact] public void BasicMultiSigTest() { Multisig ms = new Multisig(); @@ -58,7 +56,7 @@ public void BasicMultiSigTest() Console.WriteLine("Is a valid multisig address " + isValidMultisigAddress); - Assert.IsTrue(isValidMultisigAddress, "Address is not a valid multisigAddress"); + Assert.True(isValidMultisigAddress, "Address is not a valid multisigAddress"); List transfers = new List { @@ -78,8 +76,8 @@ public void BasicMultiSigTest() Signing sgn = new Signing(new Kerl()); bool isValidSignature = sgn.ValidateSignatures(bundle, multiSigAddress); - Console.WriteLine("Result of multi-signature validation is " + isValidSignature); - Assert.IsTrue(isValidSignature, "MultiSignature not valid"); + + Assert.True(isValidSignature, "MultiSignature not valid"); } } diff --git a/IotaApi.Standard.Tests/IotaCoreApiTest.cs b/IotaApi.Standard.Tests/IotaCoreApiTest.cs deleted file mode 100644 index 5e75e72..0000000 --- a/IotaApi.Standard.Tests/IotaCoreApiTest.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System.Linq; -using Iota.Api.Standard.Exception; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests -{ - [TestClass] - public class IotaCoreApiTest - { - private static readonly string TEST_BUNDLE = - "XZKJUUMQOYUQFKMWQZNTFMSS9FKJLOEV9DXXXWPMQRTNCOUSUQNTBIJTVORLOQPLYZOTMLFRHYKMTGZZU"; - - private static readonly string TEST_ADDRESS_WITH_CHECKSUM = - "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA"; - - private static readonly string TEST_HASH = - "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"; - - private static IotaApi _iotaApi; - - [TestInitialize] - public void CreateProxyInstance() - { - _iotaApi = new IotaApi("node.iotawallet.info", 14265); - } - - [TestMethod] - public void ShouldGetNodeInfo() - { - var nodeInfo = _iotaApi.GetNodeInfo(); - Assert.IsNotNull(nodeInfo.AppVersion); - Assert.IsNotNull(nodeInfo.AppName); - Assert.IsNotNull(nodeInfo.JreVersion); - Assert.IsNotNull(nodeInfo.JreAvailableProcessors); - Assert.IsNotNull(nodeInfo.JreFreeMemory); - Assert.IsNotNull(nodeInfo.JreMaxMemory); - Assert.IsNotNull(nodeInfo.JreTotalMemory); - Assert.IsNotNull(nodeInfo.LatestMilestone); - Assert.IsNotNull(nodeInfo.LatestMilestoneIndex); - Assert.IsNotNull(nodeInfo.LatestSolidSubtangleMilestone); - Assert.IsNotNull(nodeInfo.LatestSolidSubtangleMilestoneIndex); - Assert.IsNotNull(nodeInfo.Neighbors); - Assert.IsNotNull(nodeInfo.PacketsQueueSize); - Assert.IsNotNull(nodeInfo.Time); - Assert.IsNotNull(nodeInfo.Tips); - Assert.IsNotNull(nodeInfo.TransactionsToRequest); - } - - [TestMethod] - public void ShouldGetNeighbors() - { - var neighbors = _iotaApi.GetNeighbors(); - Assert.IsNotNull(neighbors.Neighbors); - } - - [TestMethod] - public void ShouldAddNeighbors() - { - try - { - var res = _iotaApi.AddNeighbors("udp://8.8.8.8:14265"); - Assert.IsNotNull(res); - } - catch (IotaApiException e) - { - Assert.IsTrue(e.Message.Contains("not available on this node")); - } - } - - [TestMethod] - public void ShouldRemoveNeighbors() - { - try - { - var res = _iotaApi.RemoveNeighbors("udp://8.8.8.8:14265"); - Assert.IsNotNull(res); - } - catch (IotaApiException e) - { - Assert.IsTrue(e.Message.Contains("not available on this node")); - } - } - - [TestMethod] - public void ShouldGetTips() - { - var tips = _iotaApi.GetTips(); - Assert.IsNotNull(tips); - } - - [TestMethod] - public void ShouldFindTransactionsByAddresses() - { - var trans = _iotaApi.FindTransactionsByAddresses(TEST_ADDRESS_WITH_CHECKSUM); - Assert.IsNotNull(trans.Hashes); - Assert.IsTrue(trans.Hashes.Count > 0); - } - - [TestMethod] - public void ShouldFindTransactionsByApprovees() - { - var trans = _iotaApi.FindTransactionsByApprovees(TEST_HASH); - Assert.IsNotNull(trans.Hashes); - } - - [TestMethod] - public void ShouldFindTransactionsByBundles() - { - var trans = _iotaApi.FindTransactionsByBundles(TEST_HASH); - Assert.IsNotNull(trans.Hashes); - } - - [TestMethod] - public void ShouldFindTransactionsByDigests() - { - var trans = _iotaApi.FindTransactionsByDigests(TEST_HASH); - Assert.IsNotNull(trans.Hashes); - } - - [TestMethod] - public void ShouldGetTrytes() - { - var res = _iotaApi.GetTrytes(TEST_HASH); - Assert.IsNotNull(res.Trytes); - } - - [TestMethod] - [ExpectedException(typeof(IotaApiException), "One of the tips absents")] - public void ShouldNotGetInclusionStates() - { - var res = _iotaApi.GetInclusionStates(new[] {TEST_HASH}, - new[] {"DNSBRJWNOVUCQPILOQIFDKBFJMVOTGHLIMLLRXOHFTJZGRHJUEDAOWXQRYGDI9KHYFGYDWQJZKX999999"}); - Assert.IsNotNull(res.States); - } - - [TestMethod] - public void ShouldGetInclusionStates() - { - var res = - _iotaApi.GetInclusionStates( - new[] {TEST_HASH}, - new[] {_iotaApi.GetNodeInfo().LatestSolidSubtangleMilestone}); - Assert.IsNotNull(res.States); - } - - [TestMethod] // very long execution - public void ShouldGetTransactionsToApprove() - { - var res = _iotaApi.GetTransactionsToApprove(27); - Assert.IsNotNull(res.TrunkTransaction); - Assert.IsNotNull(res.BranchTransaction); - } - - [TestMethod] - public void ShouldFindTransactions() - { - var test = TEST_BUNDLE; - // ReSharper disable once UnusedVariable - var resp = _iotaApi.FindTransactions(new[] {test}.ToList(), - new[] {test}.ToList(), new[] {test}.ToList(), new[] {test}.ToList()); - } - - [TestMethod] - public void ShouldGetBalances() - { - var res = _iotaApi.GetBalances(new[] {TEST_ADDRESS_WITH_CHECKSUM}.ToList(), 100); - Assert.IsNotNull(res.Balances); - Assert.IsNotNull(res.References); - Assert.IsNotNull(res.MilestoneIndex); - } - } -} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Pow/KerlTest.cs b/IotaApi.Standard.Tests/Pow/KerlTest.cs deleted file mode 100644 index f79d434..0000000 --- a/IotaApi.Standard.Tests/Pow/KerlTest.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Iota.Api.Standard.Pow; -using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Pow -{ - [TestClass] - public class KerlTest - { - [TestMethod] - public void ShouldCreateValidHash1() - { - var trits = Converter.ToTrits( - "GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"); - var kerl = new Kerl(); - kerl.Reset(); - kerl.Absorb(trits, 0, trits.Length); - var hashTrits = new int[trits.Length]; - kerl.Squeeze(hashTrits, 0, 243); - var hash = Converter.ToTrytes(hashTrits); - Assert.AreEqual(hash, "OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW"); - } - - [TestMethod] - public void ShouldCreateValidHash2() - { - var trits = Converter.ToTrits( - "9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH"); - var kerl = new Kerl(); - kerl.Reset(); - kerl.Absorb(trits, 0, trits.Length); - var hashTrits = new int[trits.Length * 2]; - kerl.Squeeze(hashTrits, 0, 243 * 2); - var hash = Converter.ToTrytes(hashTrits); - Assert.AreEqual(hash, - "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); - } - - [TestMethod] - public void ShouldCreateValidHash3() - { - var trits = Converter.ToTrits( - "G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); - var kerl = new Kerl(); - kerl.Reset(); - kerl.Absorb(trits, 0, trits.Length); - var hashTrits = new int[trits.Length]; - kerl.Squeeze(hashTrits, 0, 243 * 2); - var hash = Converter.ToTrytes(hashTrits); - Assert.AreEqual(hash, - "LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX"); - } - } -} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Pow/LocalPoWTest.cs b/IotaApi.Standard.Tests/Pow/LocalPoWTest.cs deleted file mode 100644 index af85382..0000000 --- a/IotaApi.Standard.Tests/Pow/LocalPoWTest.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; -using Iota.Api.Standard.Model; -using Iota.Api.Standard.Pow; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Pow -{ - [TestClass] - public class LocalPoWTest - { - private static readonly string TEST_SEED1 = - "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = - "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; - - private static readonly string TEST_MESSAGE = "JUSTANOTHERJOTATEST"; - private static readonly string TEST_TAG = "JOTASPAM9999999999999999999"; - private static readonly int MIN_WEIGHT_MAGNITUDE = 14; - private static readonly int DEPTH = 9; - - private IotaApi _iotaClient; - - [TestInitialize] - public void Setup() - { - _iotaClient = new IotaApi("node.iotawallet.info", 14265) - { - LocalPow = new PearlDiverLocalPoW() - }; - } - - [TestMethod] - public void ShouldSendTransfer() - { - var transfers = new List - { - new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG) - }; - var result = _iotaClient.SendTransfer( - TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers.ToArray(), - null, null, false, false); - Assert.IsNotNull(result); - } - } -} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Pow/PearlDiverTest.cs b/IotaApi.Standard.Tests/Pow/PearlDiverTest.cs deleted file mode 100644 index 6ed6e67..0000000 --- a/IotaApi.Standard.Tests/Pow/PearlDiverTest.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Text; -using Iota.Api.Standard.Pow; -using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Pow -{ - [TestClass] - public class PearlDiverTest - { - - private const int TryteLength = 2673; - private const int MinWeightMagnitude = 9; - private const int NumCores = -1; // use n-1 cores - - private static readonly Random Random = new Random(); - private PearlDiver _pearlDiver; - private int[] _hashTrits; - - [TestInitialize] - public void Setup() - { - _pearlDiver = new PearlDiver(); - _hashTrits = new int[Sponge.HashLength]; - } - - - [TestMethod] - public void TestRandomTryteHash() - { - string testTrytes = GetRandomTrytes(); - - string hash = GetHashFor(testTrytes); - - string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); - - bool success = InputValidator.IsNinesTrytes(subHash,subHash.Length); - if (!success) - { - Console.WriteLine(testTrytes); - } - - Assert.IsTrue(success, "The hash should have n nines"); - } - - [TestMethod] - [Ignore] - public void TestRandomTryteHash100() - { - for (int i = 0; i < 100; i++) - { - string testTrytes = GetRandomTrytes(); - - string hash = GetHashFor(testTrytes); - - string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); - - bool success = InputValidator.IsNinesTrytes(subHash, subHash.Length); - if (!success) - { - Console.WriteLine(testTrytes); - } - - Assert.IsTrue(success, "The hash should have n nines"); - } - } - - private string GetRandomTrytes() - { - var trytes = new StringBuilder(); - - for (int i = 0; i < TryteLength; i++) - { - trytes.Append(Constants.TryteAlphabet[Random.Next(27)]); - } - - return trytes.ToString(); - } - - private string GetHashFor(string trytes) - { - Sponge curl = new Curl(CurlMode.CurlP81); - int[] myTrits = Converter.ToTrits(trytes); - - bool result = _pearlDiver.Search(myTrits, MinWeightMagnitude, NumCores); - - Assert.IsTrue(result,"Search Failed"); - - curl.Absorb(myTrits, 0, myTrits.Length); - curl.Squeeze(_hashTrits, 0, Sponge.HashLength); - curl.Reset(); - - return Converter.ToTrytes(_hashTrits); - } - } -} diff --git a/IotaApi.Standard.Tests/Utils/ChecksumTest.cs b/IotaApi.Standard.Tests/Utils/ChecksumTest.cs deleted file mode 100644 index 77a5334..0000000 --- a/IotaApi.Standard.Tests/Utils/ChecksumTest.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Utils -{ - [TestClass] - public class ChecksumTest - { - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM = - "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; - - private static readonly string TEST_ADDRESS_WITH_CHECKSUM = - "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; - - [TestMethod] - public void ShouldAddChecksum() - { - Assert.AreEqual(Checksum.AddChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); - } - - [TestMethod] - public void ShouldRemoveChecksum() - { - Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.RemoveChecksum(), TEST_ADDRESS_WITHOUT_CHECKSUM); - } - - [TestMethod] - public void ShouldIsValidChecksum() - { - Assert.AreEqual(TEST_ADDRESS_WITH_CHECKSUM.IsValidChecksum(), true); - } - } -} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Utils/IotaUnitConverterTests.cs b/IotaApi.Standard.Tests/Utils/IotaUnitConverterTests.cs deleted file mode 100644 index 7ce33a3..0000000 --- a/IotaApi.Standard.Tests/Utils/IotaUnitConverterTests.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Utils -{ - [TestClass] - public class IotaUnitConverterTest - { - [TestMethod] - public void ShouldConvertUnitItoKi() - { - Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Iota, IotaUnits.Kilo), 1); - } - - [TestMethod] - public void ShouldConvertUnitKiToMi() - { - Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Kilo, IotaUnits.Mega), 1); - } - - [TestMethod] - public void ShouldConvertUnitMiToGi() - { - Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Mega, IotaUnits.Giga), 1); - } - - [TestMethod] - public void ShouldConvertUnitGiToTi() - { - Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Giga, IotaUnits.Terra), 1); - } - - [TestMethod] - public void ShouldConvertUnitTiToPi() - { - Assert.AreEqual(IotaUnitConverter.ConvertUnits(1000, IotaUnits.Terra, IotaUnits.Peta), 1); - } - - [TestMethod] - public void ShouldFindOptimizeUnitToDisplay() - { - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1), IotaUnits.Iota); - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000), IotaUnits.Kilo); - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000), IotaUnits.Mega); - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000), IotaUnits.Giga); - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000L), IotaUnits.Terra); - Assert.AreEqual(IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000000L), IotaUnits.Peta); - } - - /*[TestMethod] - public void shouldConvertRawIotaAmountToDisplayText() - { - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1, false), "1 i"); - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000, false), "1 Ki"); - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000, false), "1 Mi"); - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000, false), "1 Gi"); - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L, false), "1 Ti"); - Assert.AreEqual(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L, false), "1 Pi"); - }*/ - } -} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Utils/TrytesConverterTest.cs b/IotaApi.Standard.Tests/Utils/TrytesConverterTest.cs deleted file mode 100644 index 7f40866..0000000 --- a/IotaApi.Standard.Tests/Utils/TrytesConverterTest.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Linq; -using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace Iota.Api.Standard.Tests.Utils -{ - [TestClass] - public class TrytesConverterTest - { - private static readonly Random Random = new Random(); - - [TestMethod] - public void ShouldConvertStringToTrytes() - { - Assert.AreEqual("IC", TrytesConverter.ToTrytes("Z")); - Assert.AreEqual(TrytesConverter.ToTrytes("JOTA JOTA"), "TBYBCCKBEATBYBCCKB"); - } - - [TestMethod] - public void ShouldConvertTrytesToString() - { - Assert.AreEqual("Z", TrytesConverter.ToString("IC")); - Assert.AreEqual(TrytesConverter.ToString("TBYBCCKBEATBYBCCKB"), "JOTA JOTA"); - } - - [TestMethod] - public void ShouldConvertBackAndForth() - { - var str = RandomString(1000); - var back = TrytesConverter.ToString(TrytesConverter.ToTrytes(str)); - Assert.AreEqual(str, back); - } - - public static string RandomString(int length) - { - const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - return new string(Enumerable.Repeat(chars, length) - .Select(s => s[Random.Next(s.Length)]).ToArray()); - } - } -} \ No newline at end of file diff --git a/IotaApi.Standard.UnitTests/IotaApi.Standard.UnitTests.csproj b/IotaApi.Standard.UnitTests/IotaApi.Standard.UnitTests.csproj new file mode 100644 index 0000000..6e9a65f --- /dev/null +++ b/IotaApi.Standard.UnitTests/IotaApi.Standard.UnitTests.csproj @@ -0,0 +1,22 @@ + + + + netcoreapp2.0 + + false + + Iota.Api.Standard.UnitTests + + + + + + + + + + + + + + diff --git a/IotaApi.Standard.UnitTests/Pow/KerlTest.cs b/IotaApi.Standard.UnitTests/Pow/KerlTest.cs new file mode 100644 index 0000000..f4e825f --- /dev/null +++ b/IotaApi.Standard.UnitTests/Pow/KerlTest.cs @@ -0,0 +1,54 @@ +using Iota.Api.Standard.Pow; +using Iota.Api.Standard.Utils; +using Xunit; + +namespace Iota.Api.Standard.UnitTests +{ + public class KerlTest + { + [Fact] + public void ShouldCreateValidHash_1() + { + int[] trits = Converter.ToTrits("GYOMKVTSNHVJNCNFBBAH9AAMXLPLLLROQY99QN9DLSJUHDPBLCFFAIQXZA9BKMBJCYSFHFPXAHDWZFEIZ"); + Kerl kerl = new Kerl(); + int[] hashTrits = new int[trits.Length]; + + kerl.Reset(); + kerl.Absorb(trits, 0, trits.Length); + kerl.Squeeze(hashTrits, 0, 243); + string hash = Converter.ToTrytes(hashTrits); + + Assert.Equal("OXJCNFHUNAHWDLKKPELTBFUCVW9KLXKOGWERKTJXQMXTKFKNWNNXYD9DMJJABSEIONOSJTTEVKVDQEWTW", hash); + } + + [Fact] + public void ShouldCreateValidHash_2() + { + int[] trits = Converter.ToTrits("9MIDYNHBWMBCXVDEFOFWINXTERALUKYYPPHKP9JJFGJEIUY9MUDVNFZHMMWZUYUSWAIOWEVTHNWMHANBH"); + Kerl kerl = new Kerl(); + int[] hashTrits = new int[trits.Length * 2]; + + kerl.Reset(); + kerl.Absorb(trits, 0, trits.Length); + kerl.Squeeze(hashTrits, 0, 243 * 2); + string hash = Converter.ToTrytes(hashTrits); + + Assert.Equal("G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA", hash); + } + + [Fact] + public void ShouldCreateValidHash_3() + { + int[] trits = Converter.ToTrits("G9JYBOMPUXHYHKSNRNMMSSZCSHOFYOYNZRSZMAAYWDYEIMVVOGKPJBVBM9TDPULSFUNMTVXRKFIDOHUXXVYDLFSZYZTWQYTE9SPYYWYTXJYQ9IFGYOLZXWZBKWZN9QOOTBQMWMUBLEWUEEASRHRTNIQWJQNDWRYLCA"); + Kerl kerl = new Kerl(); + int[] hashTrits = new int[trits.Length]; + + kerl.Reset(); + kerl.Absorb(trits, 0, trits.Length); + kerl.Squeeze(hashTrits, 0, 243 * 2); + string hash = Converter.ToTrytes(hashTrits); + + Assert.Equal("LUCKQVACOGBFYSPPVSSOXJEKNSQQRQKPZC9NXFSMQNRQCGGUL9OHVVKBDSKEQEBKXRNUJSRXYVHJTXBPDWQGNSCDCBAIRHAQCOWZEBSNHIJIGPZQITIBJQ9LNTDIBTCQ9EUWKHFLGFUVGGUWJONK9GBCDUIMAYMMQX", hash); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard.UnitTests/Pow/PearlDiverTest.cs b/IotaApi.Standard.UnitTests/Pow/PearlDiverTest.cs new file mode 100644 index 0000000..c2e6f46 --- /dev/null +++ b/IotaApi.Standard.UnitTests/Pow/PearlDiverTest.cs @@ -0,0 +1,47 @@ +using System; +using System.Text; +using Iota.Api.Standard.Pow; +using Iota.Api.Standard.Utils; +using Xunit; + +namespace Iota.Api.Standard.UnitTests +{ + public class PearlDiverTest + { + private const int TryteLength = 2673; + private const int MinWeightMagnitude = 12; + private const int NumCores = -1; + + [Fact] + public void ShouldGenerateHashWithTrytesAtEnd() + { + Sponge curl = new Curl(CurlMode.CurlP81); + PearlDiver pearlDiver = new PearlDiver(); + int[] initialTrits = Converter.ToTrits(GetRandomTrytes()); + int[] tritsAfterPoW = new int[Sponge.HashLength]; + + bool result = pearlDiver.Search(initialTrits, MinWeightMagnitude, NumCores); + curl.Absorb(initialTrits, 0, initialTrits.Length); + curl.Squeeze(tritsAfterPoW, 0, Sponge.HashLength); + string hash = Converter.ToTrytes(tritsAfterPoW); + string subHash = hash.Substring(Sponge.HashLength / 3 - MinWeightMagnitude / 3); + bool success = InputValidator.IsNinesTrytes(subHash,subHash.Length); + + Assert.True(result); //Pearldiver was successfull finding a hash + Assert.True(success); //Hash contains the correct amount of nines at the end + } + + private string GetRandomTrytes() + { + StringBuilder trytes = new StringBuilder(); + Random random = new Random(); + + for (int i = 0; i < TryteLength; i++) + { + trytes.Append(Constants.TRYTE_ALPHABET[random.Next(27)]); + } + + return trytes.ToString(); + } + } +} diff --git a/IotaApi.Standard.Tests/Utils/BigIntConverterTest.cs b/IotaApi.Standard.UnitTests/Utils/BigIntConverterTest.cs similarity index 61% rename from IotaApi.Standard.Tests/Utils/BigIntConverterTest.cs rename to IotaApi.Standard.UnitTests/Utils/BigIntConverterTest.cs index 6337882..ca7d3ab 100644 --- a/IotaApi.Standard.Tests/Utils/BigIntConverterTest.cs +++ b/IotaApi.Standard.UnitTests/Utils/BigIntConverterTest.cs @@ -1,32 +1,29 @@ using System; using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Xunit; using Org.BouncyCastle.Math; -namespace Iota.Api.Standard.Tests.Utils +namespace Iota.Api.Standard.UnitTests { - [TestClass] public class BigIntConverterTest { - private static readonly Random Random = new Random(); - // trits<->BigInteger<->byte + private readonly Random Random = new Random(); - [TestMethod] - public void TestTritsAndBigInt() + [Fact] + public void ShouldConvertTritsAndBigInt() { - var inputTrits = new int[243]; + int[] inputTrits = new int[243]; + int[] outputTrits = new int[243]; for (var i = 0; i < inputTrits.Length; i++) inputTrits[i] = Random.Next(3) - 1; var bigInt = BigIntConverter.BigIntFromTrits(inputTrits, 0, inputTrits.Length); - - var outputTrits = new int[inputTrits.Length]; BigIntConverter.TritsFromBigInt(bigInt, outputTrits, 0, outputTrits.Length); - for (var i = 0; i < inputTrits.Length; i++) Assert.AreEqual(inputTrits[i], outputTrits[i]); + Assert.Equal(inputTrits, outputTrits); } - [TestMethod] - public void TestBigIntAndByte() + [Fact] + public void ShouldConvertBigIntAndByte() { var bytes = new byte[48]; var bigInt0 = new BigInteger("-123456"); @@ -34,11 +31,11 @@ public void TestBigIntAndByte() BigIntConverter.BytesFromBigInt(bigInt0, bytes, 0, bytes.Length); var bigInt1 = BigIntConverter.BigIntFromBytes(bytes, 0, bytes.Length); - Assert.AreEqual(bigInt0, bigInt1); + Assert.Equal(bigInt0, bigInt1); } - [TestMethod] - public void TestFixedBigInt() + [Fact] + public void ShouldConvertFixedBigInt() { var inputTrits = new int[243]; var outputTrits = new int[243]; @@ -51,7 +48,7 @@ public void TestFixedBigInt() FixedBigIntConverter.FromBytesToTrits(bytes, outputTrits); outputTrits[outputTrits.Length - 1] = 0; - for (var i = 0; i < inputTrits.Length; i++) Assert.AreEqual(inputTrits[i], outputTrits[i]); + Assert.Equal(inputTrits, outputTrits); } } } \ No newline at end of file diff --git a/IotaApi.Standard.UnitTests/Utils/ChecksumTest.cs b/IotaApi.Standard.UnitTests/Utils/ChecksumTest.cs new file mode 100644 index 0000000..2be8061 --- /dev/null +++ b/IotaApi.Standard.UnitTests/Utils/ChecksumTest.cs @@ -0,0 +1,32 @@ +using Iota.Api.Standard.Utils; +using Xunit; + +namespace Iota.Api.Standard.UnitTests +{ + public class ChecksumTest + { + private const string TEST_ADDRESS_WITHOUT_CHECKSUM = + "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; + + private const string TEST_ADDRESS_WITH_CHECKSUM = + "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; + + [Fact] + public void ShouldAddChecksum() + { + Assert.Equal(Checksum.AddChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); + } + + [Fact] + public void ShouldRemoveChecksum() + { + Assert.Equal(TEST_ADDRESS_WITH_CHECKSUM.RemoveChecksum(), TEST_ADDRESS_WITHOUT_CHECKSUM); + } + + [Fact] + public void ShouldIsValidChecksum() + { + Assert.True(TEST_ADDRESS_WITH_CHECKSUM.IsValidChecksum()); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Utils/InputValidatorTests.cs b/IotaApi.Standard.UnitTests/Utils/InputValidatorTests.cs similarity index 64% rename from IotaApi.Standard.Tests/Utils/InputValidatorTests.cs rename to IotaApi.Standard.UnitTests/Utils/InputValidatorTests.cs index 45ffbe4..b53bdcf 100644 --- a/IotaApi.Standard.Tests/Utils/InputValidatorTests.cs +++ b/IotaApi.Standard.UnitTests/Utils/InputValidatorTests.cs @@ -1,92 +1,86 @@ using System.Collections.Generic; using Iota.Api.Standard.Model; using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Xunit; -namespace Iota.Api.Standard.Tests.Utils +namespace Iota.Api.Standard.UnitTests { - [TestClass] public class InputValidatorTests { - private static readonly string TEST_ADDRESS_WITHOUT_CHECKSUM = + private const string TEST_ADDRESS_WITHOUT_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA"; - private static readonly string TEST_ADDRESS_WITH_CHECKSUM = + private const string TEST_ADDRESS_WITH_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA"; - private static readonly string TEST_TRYTES = + private const string TEST_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"; - private static readonly string TEST_HASH = + private const string TEST_HASH = "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"; - private static readonly string TEST_MESSAGE = "JOTA"; - private static readonly string TEST_TAG = "JOTASPAM9999999999999999999"; + private const string TEST_MESSAGE = "JOTA"; + private const string TEST_TAG = "JOTASPAM9999999999999999999"; - [TestMethod] - public void ShouldIsAddress() + [Fact] + public void ShouldValidateAddress() { - Assert.AreEqual(InputValidator.IsAddress(TEST_ADDRESS_WITHOUT_CHECKSUM), true); + Assert.True(InputValidator.IsAddress(TEST_ADDRESS_WITHOUT_CHECKSUM)); } - [TestMethod] - public void ShouldCheckAddress() + [Fact] + public void ShouldValidateTryteString() { - Assert.AreEqual(InputValidator.IsAddress(TEST_ADDRESS_WITHOUT_CHECKSUM), true); + Assert.True(InputValidator.IsTrytes(TEST_TRYTES, TEST_TRYTES.Length)); } - [TestMethod] - public void ShouldIsTrytes() + [Fact] + public void ShouldValidatePositiveValue() { - Assert.AreEqual(InputValidator.IsTrytes(TEST_TRYTES, TEST_TRYTES.Length), true); + Assert.True(InputValidator.IsValue("1234")); } - [TestMethod] - public void ShouldIsValue() + [Fact] + public void ShouldValidateNegativeValue() { - Assert.AreEqual(InputValidator.IsValue("1234"), true); + Assert.True(InputValidator.IsValue("-1234")); } - [TestMethod] - public void IsValueNeg() + [Fact] + public void ShouldFailToValidateNegativeValue() { - Assert.AreEqual(InputValidator.IsValue("-1234"), true); + Assert.False(InputValidator.IsValue("-")); } - [TestMethod] - public void IsValueNeg2() + [Fact] + public void ShouldValidateArrayOfHashes() { - Assert.AreEqual(InputValidator.IsValue("-"), false); + Assert.True(InputValidator.IsArrayOfHashes(new[] {TEST_HASH, TEST_HASH})); } - [TestMethod] - public void ShouldIsArrayOfHashes() + [Fact] + public void ShouldValidateArrayOfTrytes() { - Assert.AreEqual(InputValidator.IsArrayOfHashes(new[] {TEST_HASH, TEST_HASH}), true); + Assert.True(InputValidator.IsArrayOfTrytes(new[] {TEST_TRYTES, TEST_TRYTES}, 2673)); } - [TestMethod] - public void ShouldIsArrayOfTrytes() + [Fact] + public void ShouldValidateNineTryteString() { - Assert.AreEqual(InputValidator.IsArrayOfTrytes(new[] {TEST_TRYTES, TEST_TRYTES}, 2673), true); + Assert.True(InputValidator.IsNinesTrytes("999999999", 9)); } - [TestMethod] - public void ShouldIsNinesTrytes() - { - Assert.AreEqual(InputValidator.IsNinesTrytes("999999999", 9), true); - } - - [TestMethod] - public void ShouldIsTransfersCollectionCorrect() + [Fact] + public void ShouldValidateTransfersCollection() { var transfers = new List { new Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG), new Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG) }; - Assert.AreEqual(InputValidator.IsTransfersCollectionValid(transfers), true); + + Assert.True(InputValidator.IsTransfersCollectionValid(transfers)); } } } \ No newline at end of file diff --git a/IotaApi.Standard.UnitTests/Utils/IotaUnitConverterTests.cs b/IotaApi.Standard.UnitTests/Utils/IotaUnitConverterTests.cs new file mode 100644 index 0000000..674e684 --- /dev/null +++ b/IotaApi.Standard.UnitTests/Utils/IotaUnitConverterTests.cs @@ -0,0 +1,49 @@ +using Iota.Api.Standard.Utils; +using Xunit; + +namespace Iota.Api.Standard.UnitTests +{ + public class IotaUnitConverterTest + { + [Fact] + public void ShouldConvertUnitItoKi() + { + Assert.Equal(1, IotaUnitConverter.ConvertUnits(1000, IotaUnits.Iota, IotaUnits.Kilo)); + } + + [Fact] + public void ShouldConvertUnitKiToMi() + { + Assert.Equal(1, IotaUnitConverter.ConvertUnits(1000, IotaUnits.Kilo, IotaUnits.Mega)); + } + + [Fact] + public void ShouldConvertUnitMiToGi() + { + Assert.Equal(1, IotaUnitConverter.ConvertUnits(1000, IotaUnits.Mega, IotaUnits.Giga)); + } + + [Fact] + public void ShouldConvertUnitGiToTi() + { + Assert.Equal(1, IotaUnitConverter.ConvertUnits(1000, IotaUnits.Giga, IotaUnits.Terra)); + } + + [Fact] + public void ShouldConvertUnitTiToPi() + { + Assert.Equal(1, IotaUnitConverter.ConvertUnits(1000, IotaUnits.Terra, IotaUnits.Peta)); + } + + [Fact] + public void ShouldFindBestUnitToDisplay() + { + Assert.Equal(IotaUnits.Iota, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1)); + Assert.Equal(IotaUnits.Kilo, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000)); + Assert.Equal(IotaUnits.Mega, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000)); + Assert.Equal(IotaUnits.Giga, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000)); + Assert.Equal(IotaUnits.Terra, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000L)); + Assert.Equal(IotaUnits.Peta, IotaUnitConverter.FindOptimalIotaUnitToDisplay(1000000000000000L)); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard.Tests/Utils/SigningTest.cs b/IotaApi.Standard.UnitTests/Utils/SigningTest.cs similarity index 67% rename from IotaApi.Standard.Tests/Utils/SigningTest.cs rename to IotaApi.Standard.UnitTests/Utils/SigningTest.cs index 0e5a5e8..65c00e5 100644 --- a/IotaApi.Standard.Tests/Utils/SigningTest.cs +++ b/IotaApi.Standard.UnitTests/Utils/SigningTest.cs @@ -2,66 +2,65 @@ using Iota.Api.Standard.Model; using Iota.Api.Standard.Pow; using Iota.Api.Standard.Utils; -using Microsoft.VisualStudio.TestTools.UnitTesting; +using Xunit; -namespace Iota.Api.Standard.Tests.Utils +namespace Iota.Api.Standard.UnitTests { - [TestClass] public class SigningTest { - private static readonly string TEST_SEED = + private const string TEST_SEED = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static readonly string FIRST_ADDR = + private const string FIRST_ADDR = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; - private static readonly string SIXTH_ADDR = + private const string SIXTH_ADDR = "HLHRSJNPUUGRYOVYPSTEQJKETXNXDIWQURLTYDBJADGIYZCFXZTTFSOCECPPPPY9BYWPODZOCWJKXEWXDPUYEOTFQA"; - private static readonly string SIGNATURE1 = + private const string SIGNATURE1 = "PYWFM9MYTPNZ9HTLZBBB9CGQWKPALDUNAQYCAA9VMQ9UMBLLAXSPPHQSNAAKJA9MZBXBHBQBFFKMBSDHDTCVCDWLUYCEQ9YZJAJAXXXZHDWTSLWGIWRE9LJFVWAFUMOAGHDBHJQ9APNBLSX9GPTJNTO9SBJT9UKYCZXYAWVGXEBJANNWEWZSPRYHASHGIFUWOEHUFMP9MWQBYZOZESCPLVJUCWGLEJIDPMEVNPBITBNFSQ9GBWCDTQZOPLPXOWWNQAEIXQRWMHAQDH9C9KKHGNKAX9INMUVVGIK9TPGRHOMDFAB9VICYDMSHHDDBRSTEFSZXMXFJUQRRAFBSCNHSMKRNNTTCMBURKBGC9EDWKLPBSQAKYCUKKSZWRVURZGUA9QVSXXPICIYFHLPJSWEFBZPUTWWNIKSAJM9OMRFFQVFJZZHLQBSEYXM9CN9HCGHSJBTYDGWOQPXOPZZE9EPQAQFT9GDWZCSOPMZHYYZXDDZ9DJDLOOOTIFQANFANNAYVIRUNDXSB9XRNXJYRDBLTEDWSUOVISMCHGKD9KDRSFDWRSVZQQKGAMDXFAWBSLMTTUMH9RAUIVI9HJMTODACSOP9MLHOJMSIWQ9TTNGPXRNWRHLMEMAH9GZHJRNJHQNBBLWKFXIZBMGMATZIZBFDPAFDCLDIFFAIK9JUSFYYC9ANDGXCZFLZYGURTUI9SWYYRGDJAHXDDNHSJZBCENZUSQXSFZMTXSFLRK9RIYAUMHPBOBNOXCHDIMBGIBVOOHIDQ9ORHHDECDTREIEILWDUFMUWYMGIXBIKRZMKGXTYZTX9GKFP9AUXMTUUQXRHHKPYULGJFJLEEYCNKLOWULRIAFM9OYKEDFRXFVTSJMSEMOURCLNOIETIHEUCMPLWKDXDO9TAHVH99MKTBAAKCMYKLJUQIVLLSVTFUM9KDSIHYXYHPRLDADSLSSOIGLLXMPKTHS9YXUNMUTBTBPDWXA9GVTBGLTCLEZEUNNIRBBURDWOFFYXELPFSZRQARVRPHGETKJTRUZIFDDWBOHHGUZTODZFMOVMAGCYCTGBWSGAVZADIPIASCKTRKIUUMHNGUYZKDVOPKKHXD9EXVUVJ9YFNYMLIJLEEGPIZLFS9FIEMG9MIEO9FPW9JZEVDQOECMTESICSMVWXZNXXJILJLVQHEBHQWPOBHKEGRLFCPLB9ZECJOZDAB9DMU9UALBIQDABVDYRRTPMZOCQX9WNGXVNKQZWPA9ACVONQMRHQDPPIQTP9VKP9PAORNOFTZZWGC9RYBWSNLULZGYLMYIWWPDMOHPZTQWRPRCN9RAUOKDSCWBRI9NPUPLBILOZDOOPHSWQGJEGUYWAWJDEBLEOBSYYU9XSRPBHRUQXIDOWJZQQVJTMP9VLWLOGBK9FZFHYLJCNENDATNPSF99DFPVPTNNKIUMHRGEBJXNUVENAHYLFPPHYFTIKCB9DBVCCSJTDMOMISBAAEJVBVLHOADKNFG9NQGIGRDICQCWZVHGGXLTUNQKBUTLDWXIM9REWBLIXFBPTOXBLWBQQUSRLRDHTXQWARPMBQILAJSYLLTDAGTFPCXBCDITDOIZNGKPZQWWHJDZIPYCPFEYFD9CVXYOJHJNUNMCMSIAUVSKCACNNPGDYJJVTZOREJOPIBYCMBULMTSDTJPZNVNYQBQPPABOSSNZJKQQZ9LULSHJUBLHIFMYWSNPGUERCLVFV9LOEBJEERYHI9OMSMSCDFDLNHEMLQXNRJDYSNKTOYCPTAUWAWIGCPJKMAMGLXNBJMO9BZGFIHWDVJWYCNZZV9KBWIFQSMAXBPGVXDW9SLTHOLMJORRXZJSTNOQDRGNBLGTFCCNBJECYZGWTDRJKJRBAJRCULMOUBQJFWCLWMEWGAAVNZWMDWBYDKZMUCZAKXQLRQPIQJPMORKJXKSDTGXWDHAKUOSMXCFXWSZYWXODWFACBMFSWQFVMBELPZMISVWRQQQPNHOTWOEQQAQJDLXFEEBXLJQEECWG9ARRRDLTVBHTPARJMLOZHYWDCSXPTZCNZWTCRUJNZWKFZXAARPHFCBTLWSLERGJJMKIG9NEBADRMZWYNWIRGTMOBRKURUE9GDLRIEODY9BXJOZUVNCXKXFPFDXKUTMXZRJDOQ9YTV9BJDKGZBYTWGVPQQMNVCNARLPSRQWN9TRMHWLNEJZFTCSRD"; - private static readonly string SIGNATURE2 = + private const string SIGNATURE2 = "URKFKLNXFEKDOGSQVMAOPEDIWSMTCKJZ9KEVWYALY9JAO9KHUGNDTMGQLKQJUIPWDIVMPEDSVPLFMDCIXDDT9WBBRTFQENL9AXLSBYHINXCDYBFGRNKJDYHAQVJKWCVOYXHTNBEZUNLVMJLUMZYJFAOW9PVVMJZNZZFJQEQFELVFZVFVWPJ9WQZJLPSGBYECHXSFVFQJGUCPFXC9GATTILVCAANNHOYMLOYX9QSUPCERYCOXPACZEEGLREBRZWXGUTTVTHB9GBRCIFEOBPIRXXPQKRSODEHDSZXLGIKXUQWNTQKIOPVDVSIK9WJUAEFOJBU9MBPBSVYSCLBMINTT9ZCTREZSMSVOPXSZOMCGFEZKMOCNLJ9QUTAPKBHRIAIYLCHUQHOINKSCMXWZVDGDXHNJQXJHPCCGBEWROVKEPAPBFFRCAVXZWIRKCRAWYHIHMDXFAGDJQNJJPYSQUHKFOOCEVQOGRQEIOQFKZWUQ9XVRNXKGMJOQEZHQZXQABWUQRBKXWHYUXEAEMDGXVY9WS9VJOCMGBQASSRNKAYJPTSPQEMYSJMTCLMDQJKDPBGQZZSFBDOKHBYY9UDRXNKTPWBCQTVKUGMEDUXL9TTKPATNIKVAGHACHPFSCRYNIRJBQC9OADPGWBFYYARSVNQCGMYQGCYLZH9KLMUIJPCLPQVS9BORXCJBXPDECJGKDNOUYWTKKFLXZARWKGUSMVMXKJTMRYZRERFCFGTZFZFCAOQSZGPQJUEZUJLJPU9QPMJUTZNLMSMPRGIFHUUZHMPMRBEBATEIIWPCOIMWOYOG9NYFBYOWFDKRXOTREBU99GNCPXKOWGI99LNVPRFFF9FCLFXI9HMUFU9NRLNJVTFNUSUJTAVOG9GKUYYEXIM9HTPIDTWIGLKRAQPKMQVZAPYMPSQIOJ9JZBWDMQHDSSRSHNCWSAJCSRORSEXLLQNZUKPXPGRLYMXOXWCCWWSBALFLXPHSGFLTOAFWPETBKJUMBLHMSKYLPJT9EJAZCPPNZWKPVCGKDJCRCLBBIAKVDSNWGONPLKFAYXZDI9FKPHDPKCB9UUPXLJVQTXOAZOQDRNSONXDVSLQGZYRIPGREYHRAUOSBFZDZPZHFNMWCZQGPXCZVLNCSASB9RQDFHOYMUVYLFKOEEWNREYCDMCTZIAFBFKLKRQWZCJHQZCZGWXIFTKRVMPHMVHAABHBDEV9WDEZBR9FLXLNBVNYKUOUFJQKNZVZVGZDDTFYNYFUVRLZKOLXXQYNV9MDVBLZSERXPGYKRIEZQZD9IBKFDT9AIYGWJJCXFWDUDURGJQLXVEJAVEOMZUVVTNCVBXEVQRDQIEHDUCSLCIJUTSCLFXEGMFYP9YLXELCZPMTBZWBIODZCFNJLVWTPQGLMQIHIABAYGJFFMOEDTCXGEDTNXMVXZYFGXRKVVRTIZ9ISXTDHAFPEKQZSM9XXQLOYBLTMD9MBERBIBEJDEXGMOLDZPZVVEPIRKJBDPAKFAWJPTCJSHZPDUKZEEHRFLMZCUGCOWFJBSTDGPHUIXSPPPHRQARMCFMTWKYPJNJQV9VSFZ9EWB9GVEAFUXHWRNUXQLCSBWROOITBATWUXUYGSMGAXKGEBP9ZJWXQWHBVPOSLDHTWXUOFQNO9EXSYPQF9LQLQAFNRU9MTIIRQLBBBYKUPANWRQKGESFARQIRUTGFMZVUKHZJYKTYOARTDOBIYBFRHJWEFHCYVHRHTLTWBRMUDVIVQVNELQMQRXYDNGVSICZINWIZCIWVFXLYOLYKWDNWCWFZUXHUWOPRDHMTSXOZX9CVHANU9ZXTJOGKEPYR9CHGOTIUQSWIALAOIKHQFXWY9ZWTSZADVXJNNZOLSCXVVFBRHLRBTGMSZOYNIXTAMABKGJTLGTZKRHOPPJMNYIQNVKRGXUQDWYEIEZYM9CSXO9YLSBJLDJUWOLUXDEKBGGEIDEXFLZMESDOITNYTNRLGOMHJH9HOLXJABUNLXCZYTXFPZMHRJPLXSVPDBJBBZX9TBIMZZFZOXUSFEJYHEXPFXGJCQTBBLPEEWAPHUETGXSXYYAF9PCCCOONRMQGAPJ9JO9BZQ9QSKTPFFYIFVHSLAZY9CWYSIMKDOSLRKWBHPGJGVEJEEMLCCWXKSOCMBMZZZJWYBBXE9FTAYJALGWITJRXAXWZEXMECTZEEIWZPHYX"; - private static readonly string ADDR_SEED = + private const string ADDR_SEED = "LIESNFZLPFNWAPWXBLKEABZEEWUDCXKTRKZIRTPCKLKWOMJSEREWKMMMODUOFWM9ELEVXADTSQWMSNFVD"; - private static readonly string ADDR_I0_S1 = + private const string ADDR_I0_S1 = "HIPPOUPZFMHJUQBLBVWORCNJWAOSFLHDWF9IOFEYVHPTTAAF9NIBMRKBICAPHYCDKMEEOXOYHJBMONJ9D"; - private static readonly string ADDR_I0_S2 = + private const string ADDR_I0_S2 = "BPYZABTUMEIOARZTMCDNUDAPUOFCGKNGJWUGUXUKNNBVKQARCZIXFVBZAAMDAFRS9YOIXWOTEUNSXVOG9"; - private static readonly string ADDR_I0_S3 = + private const string ADDR_I0_S3 = "BYWHJJYSHSEGVZKKYTJTYILLEYBSIDLSPXDLDZSWQ9XTTRLOSCBCQ9TKXJYQAVASYCMUCWXZHJYRGDOBW"; - private static readonly string ADDR_LS_I0_S1 = + private const string ADDR_LS_I0_S1 = "VKPCVHWKSCYQNHULMPYDZTNKOQHZNPEGJVPEHPTDIUYUBFKFICDRLLSIULHCVHOHZRHJOHNASOFRWFWZC"; - private static readonly string ADDR_LS_I0_S2 = + private const string ADDR_LS_I0_S2 = "PTHVACKMXOKIERJOFSRPBWCNKVEXQ9CWUTIJGEUORSKWEDDJCBFQCCBQZLTYXQCXEDWLTMRQM9OQPUGNC"; - private static readonly string ADDR_LS_I0_S3 = + private const string ADDR_LS_I0_S3 = "AGSAAETPMSBCDOSNXFXIOBAE9MVEJCSWVP9PAULQ9VABOTWLDMXID9MXCCWQIWRTJBASWPIJDFUC9ISWD"; - [TestMethod] - public void TestAddressGeneration() + [Fact] + public void ShouldGenerateValidAddress() { - Assert.AreEqual(FIRST_ADDR, IotaApiUtils.NewAddress(TEST_SEED, 2, 0, true, null)); - Assert.AreEqual(SIXTH_ADDR, IotaApiUtils.NewAddress(TEST_SEED, 2, 5, true, null)); + Assert.Equal(FIRST_ADDR, IotaApiUtils.NewAddress(TEST_SEED, 2, 0, true, null)); + Assert.Equal(SIXTH_ADDR, IotaApiUtils.NewAddress(TEST_SEED, 2, 5, true, null)); - Assert.AreEqual(ADDR_I0_S1, IotaApiUtils.NewAddress(ADDR_SEED, 1, 0, false, null)); - Assert.AreEqual(ADDR_I0_S2, IotaApiUtils.NewAddress(ADDR_SEED, 2, 0, false, null)); - Assert.AreEqual(ADDR_I0_S3, IotaApiUtils.NewAddress(ADDR_SEED, 3, 0, false, null)); + Assert.Equal(ADDR_I0_S1, IotaApiUtils.NewAddress(ADDR_SEED, 1, 0, false, null)); + Assert.Equal(ADDR_I0_S2, IotaApiUtils.NewAddress(ADDR_SEED, 2, 0, false, null)); + Assert.Equal(ADDR_I0_S3, IotaApiUtils.NewAddress(ADDR_SEED, 3, 0, false, null)); - Assert.AreEqual(ADDR_LS_I0_S1, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 1, 0, false, null)); - Assert.AreEqual(ADDR_LS_I0_S2, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 2, 0, false, null)); - Assert.AreEqual(ADDR_LS_I0_S3, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 3, 0, false, null)); + Assert.Equal(ADDR_LS_I0_S1, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 1, 0, false, null)); + Assert.Equal(ADDR_LS_I0_S2, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 2, 0, false, null)); + Assert.Equal(ADDR_LS_I0_S3, IotaApiUtils.NewAddress(ADDR_SEED + ADDR_SEED, 3, 0, false, null)); } - [TestMethod] - public void TestLongSeedKeyGeneration() + [Fact] + public void ShouldGenerateLongKey() { ICurl curl = new Kerl(); var signing = new Signing(curl); @@ -70,20 +69,17 @@ public void TestLongSeedKeyGeneration() for (var i = 1; i < 5; i++) { var key1 = signing.Key(Converter.ToTrits(seed), 0, i); - Assert.AreEqual(Signing.KeyLength * i, key1.Length); + Assert.Equal(Signing.KeyLength * i, key1.Length); var key2 = signing.Key(Converter.ToTrits(seed + seed), 0, i); - Assert.AreEqual(Signing.KeyLength * i, key2.Length); + Assert.Equal(Signing.KeyLength * i, key2.Length); var key3 = signing.Key(Converter.ToTrits(seed + seed + seed), 0, i); - Assert.AreEqual(Signing.KeyLength * i, key3.Length); + Assert.Equal(Signing.KeyLength * i, key3.Length); } } - [TestMethod] - public void TestSigning() + [Fact] + public void ShouldCreateCorrectSignatures() { - // we can sign any hash, so for convenience we will sign the first - // address of our test seed - // (but remove the checksum) with the key of our fifth address var hashToSign = FIRST_ADDR.RemoveChecksum(); var signing = new Signing(null); var key = signing.Key(Converter.ToTrits(TEST_SEED), 5, 2); @@ -94,44 +90,43 @@ public void TestSigning() Array.Copy(key, 0, subKey, 0, 6561); Array.Copy(normalizedHash, 0, subNormalizedHash, 0, 27); - var signature = signing.SignatureFragment( - subNormalizedHash, - subKey); - Assert.AreEqual(SIGNATURE1, Converter.ToTrytes(signature)); + int[] signature = signing.SignatureFragment(subNormalizedHash, subKey); + + Assert.Equal(SIGNATURE1, Converter.ToTrytes(signature)); Array.Copy(key, 6561, subKey, 0, 6561); Array.Copy(normalizedHash, 27, subNormalizedHash, 0, 27); - var signature2 = signing.SignatureFragment( - subNormalizedHash, - subKey); - Assert.AreEqual(SIGNATURE2, Converter.ToTrytes(signature2)); + int[] signature2 = signing.SignatureFragment(subNormalizedHash, subKey); + + Assert.Equal(SIGNATURE2, Converter.ToTrytes(signature2)); } - [TestMethod] - public void TestKeyLength() + [Fact] + public void ShouldCreateKeyWithCorrectSize() { - var signing = new Signing(null); - var key = signing.Key(Converter.ToTrits(TEST_SEED), 5, 1); - Assert.AreEqual(Signing.KeyLength, key.Length); - key = signing.Key(Converter.ToTrits(TEST_SEED), 5, 2); - Assert.AreEqual(2 * Signing.KeyLength, key.Length); - key = signing.Key(Converter.ToTrits(TEST_SEED), 5, 3); - Assert.AreEqual(3 * Signing.KeyLength, key.Length); + Signing signing = new Signing(null); + int[] key_01, key_02, key_03; + + key_01 = signing.Key(Converter.ToTrits(TEST_SEED), 5, 1); + key_02 = signing.Key(Converter.ToTrits(TEST_SEED), 5, 2); + key_03 = signing.Key(Converter.ToTrits(TEST_SEED), 5, 3); + + Assert.Equal(Signing.KeyLength, key_01.Length); + Assert.Equal(2 * Signing.KeyLength, key_02.Length); + Assert.Equal(3 * Signing.KeyLength, key_03.Length); } - [TestMethod] - public void TestVerifying() + [Fact] + public void ShouldValidateSignatures() { - var signing = new Signing(null); - Assert.IsTrue(signing.ValidateSignatures( - RemoveChecksum(SIXTH_ADDR), - new[] {SIGNATURE1, SIGNATURE2}, - RemoveChecksum(FIRST_ADDR))); + Signing signing = new Signing(null); + + Assert.True(signing.ValidateSignatures(RemoveChecksum(SIXTH_ADDR), new[] {SIGNATURE1, SIGNATURE2}, RemoveChecksum(FIRST_ADDR))); } private string RemoveChecksum(string address) { - Assert.IsTrue(address.IsValidChecksum()); + Assert.True(address.IsValidChecksum()); return address.Substring(0, 81); } } diff --git a/IotaApi.Standard.UnitTests/Utils/TrytesConverterTest.cs b/IotaApi.Standard.UnitTests/Utils/TrytesConverterTest.cs new file mode 100644 index 0000000..07c6a75 --- /dev/null +++ b/IotaApi.Standard.UnitTests/Utils/TrytesConverterTest.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq; +using Iota.Api.Standard.Utils; +using Xunit; + +namespace Iota.Api.Standard.UnitTests +{ + public class TrytesConverterTest + { + private readonly Random Random = new Random(); + + [Fact] + public void ShouldConvertStringToTrytes() + { + Assert.Equal("IC", TrytesConverter.ToTrytes("Z")); + Assert.Equal("TBYBCCKBEATBYBCCKB", TrytesConverter.ToTrytes("JOTA JOTA")); + } + + [Fact] + public void ShouldConvertTrytesToString() + { + Assert.Equal("Z", TrytesConverter.ToString("IC")); + Assert.Equal("JOTA JOTA", TrytesConverter.ToString("TBYBCCKBEATBYBCCKB")); + } + + [Fact] + public void ShouldConvertTryteString() + { + string tryteString = RandomString(1000); + + string back = TrytesConverter.ToString(TrytesConverter.ToTrytes(tryteString)); + + Assert.Equal(tryteString, back); + } + + private string RandomString(int length) + { + const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + return new string(Enumerable.Repeat(chars, length) + .Select(s => s[Random.Next(s.Length)]).ToArray()); + } + } +} \ No newline at end of file diff --git a/IotaApi.Standard/IotaApi.cs b/IotaApi.Standard/IotaApi.cs index b4cf883..221fe3a 100644 --- a/IotaApi.Standard/IotaApi.cs +++ b/IotaApi.Standard/IotaApi.cs @@ -204,10 +204,10 @@ public List PrepareTransfers( var signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) - if (transfer.Message.Length > Constants.MessageLength) + if (transfer.Message.Length > Constants.MESSAGE_LENGTH) { // Get total length, message / maxLength (2187 trytes) - signatureMessageLength += (int) Math.Floor((double) transfer.Message.Length / Constants.MessageLength); + signatureMessageLength += (int) Math.Floor((double) transfer.Message.Length / Constants.MESSAGE_LENGTH); var msgCopy = transfer.Message; @@ -960,11 +960,11 @@ public List InitiateTransfer( int signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add next transaction) - if (transfer.Message.Length > Constants.MessageLength) + if (transfer.Message.Length > Constants.MESSAGE_LENGTH) { // Get total length, message / maxLength (2187 trytes) - signatureMessageLength += (int)Math.Floor((double)transfer.Message.Length / Constants.MessageLength); + signatureMessageLength += (int)Math.Floor((double)transfer.Message.Length / Constants.MESSAGE_LENGTH); String msgCopy = transfer.Message; @@ -973,11 +973,11 @@ public List InitiateTransfer( while (!string.IsNullOrEmpty(msgCopy)) { - string fragment = msgCopy.Substring(0, Constants.MessageLength); - msgCopy = msgCopy.Substring(Constants.MessageLength, msgCopy.Length - Constants.MessageLength); + string fragment = msgCopy.Substring(0, Constants.MESSAGE_LENGTH); + msgCopy = msgCopy.Substring(Constants.MESSAGE_LENGTH, msgCopy.Length - Constants.MESSAGE_LENGTH); // Pad remainder of fragment - fragment = fragment.PadRight(Constants.MessageLength, '9'); + fragment = fragment.PadRight(Constants.MESSAGE_LENGTH, '9'); signatureFragments.Add(fragment); @@ -990,9 +990,9 @@ public List InitiateTransfer( // Else, get single fragment with 2187 of 9's trytes String fragment = transfer.Message; - if (transfer.Message.Length < Constants.MessageLength) + if (transfer.Message.Length < Constants.MESSAGE_LENGTH) { - fragment = fragment.PadRight(Constants.MessageLength, '9'); + fragment = fragment.PadRight(Constants.MESSAGE_LENGTH, '9'); } signatureFragments.Add(fragment); @@ -1002,9 +1002,9 @@ public List InitiateTransfer( tag = transfer.Tag; // pad for required 27 tryte length - if (transfer.Tag.Length < Constants.TagLength) + if (transfer.Tag.Length < Constants.TAG_LENGTH) { - tag = tag.PadRight(Constants.TagLength, '9'); + tag = tag.PadRight(Constants.TAG_LENGTH, '9'); } // get current timestamp in seconds diff --git a/IotaApi.Standard/Model/Bundle.cs b/IotaApi.Standard/Model/Bundle.cs index fcb15bf..9976de2 100644 --- a/IotaApi.Standard/Model/Bundle.cs +++ b/IotaApi.Standard/Model/Bundle.cs @@ -100,7 +100,7 @@ public void AddEntry(int signatureMessageLength, string address, long value, str public void AddTrytes(List signatureFragments) { var emptySignatureFragment = ""; - var emptyHash = Constants.EmptyHash; + var emptyHash = Constants.EMPTY_HASH; long emptyTimestamp = 999999999L; while (emptySignatureFragment.Length < 2187) emptySignatureFragment += '9'; diff --git a/IotaApi.Standard/Pow/Kerl.cs b/IotaApi.Standard/Pow/Kerl.cs index a27b312..3010f60 100644 --- a/IotaApi.Standard/Pow/Kerl.cs +++ b/IotaApi.Standard/Pow/Kerl.cs @@ -102,7 +102,7 @@ public override void Squeeze(int[] trits, int offset, int length) Array.Copy(_tritState, 0, trits, offset, HashLength); //calculate hash again - for (var i = _byteState.Length; i-- > 0;) _byteState[i] = (byte) (_byteState[i] ^ 0xFF); + for (var i = _byteState.Length; i-- > 0;) _byteState[i] = (byte)(_byteState[i] ^ 0xFF); _keccak.BlockUpdate(_byteState, 0, _byteState.Length); offset += HashLength; diff --git a/IotaApi.Standard/Pow/PearlDiver.cs b/IotaApi.Standard/Pow/PearlDiver.cs index 7ed9d7a..c713a9e 100644 --- a/IotaApi.Standard/Pow/PearlDiver.cs +++ b/IotaApi.Standard/Pow/PearlDiver.cs @@ -1,244 +1,267 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; namespace Iota.Api.Standard.Pow { - /// - /// (c) 2016 Come-from-Beyond - /// See https://github.com/iotaledger/iri/blob/dev/src/main/java/com/iota/iri/hash/PearlDiver.java - /// public class PearlDiver { - private const int TransactionLength = 8019; - private const int NumberOfRoundsp81 = 81; + private enum State + { + RUNNING, + CANCELLED, + COMPLETED + } - private const int CurlHashLength = 243; - private const int CurlStateLength = CurlHashLength * 3; + private const int TRANSACTION_LENGTH = 8019; + private const int CURL_HASH_LENGTH = 243; + private const int CURL_STATE_LENGTH = CURL_HASH_LENGTH * 3; - private const long HighBits = -1; - private const long LowBits = 0; - private static readonly object SyncObj = new object(); + private const long HIGH_BITS = -1; + private const long LOW_BITS = 0; - private State _state; + private readonly object SyncObj = new object(); + private State state; - /// - /// - /// - /// - /// - /// - // ReSharper disable once RedundantAssignment - public bool Search(int[] transactionTrits, int minWeightMagnitude, int numberOfThreads) + public void Cancel() { - if (transactionTrits.Length != TransactionLength) - throw new ArgumentException($"Invalid transaction trits length: {transactionTrits.Length}"); + lock (SyncObj) + { + state = State.CANCELLED; + } + } - if (minWeightMagnitude < 0 || minWeightMagnitude > CurlHashLength) - throw new ArgumentException($"Invalid min weight magnitude: {minWeightMagnitude}"); + public bool Search(int[] transactionTrits, int minWeightMagnitude, int numberOfThreads) + { + ValidateParameters(transactionTrits, minWeightMagnitude); - lock (SyncObj) + lock(SyncObj) { - _state = State.Running; + state = State.RUNNING; } - var midCurlStateLow = new long[CurlStateLength]; - var midCurlStateHigh = new long[CurlStateLength]; + long[] midStateLow = new long[CURL_STATE_LENGTH]; + long[] midStateHigh = new long[CURL_STATE_LENGTH]; + + InitializeMidCurlStates(transactionTrits, midStateLow, midStateHigh); + + if (numberOfThreads <= 0) + { + double procsAvail = numberOfThreads * 8 / 10; + numberOfThreads = Convert.ToInt32(Math.Max(1.0, Math.Floor(procsAvail))); + } - // step1 + List workers = new List(numberOfThreads); + while (numberOfThreads-- > 0) + { + long[] midStateCopyLow = midStateLow.Clone() as long[]; + long[] midStateCopyHigh = midStateHigh.Clone() as long[]; + Task worker = new Task(() => Perform(numberOfThreads, transactionTrits, minWeightMagnitude, midStateCopyLow, midStateCopyHigh)); + workers.Add(worker); + worker.Start(); + } + foreach(Task worker in workers) { - for (var i = CurlHashLength; i < CurlStateLength; i++) + try { - midCurlStateLow[i] = HighBits; - midCurlStateHigh[i] = HighBits; + worker.Wait(); } + catch (AggregateException) + { + lock(SyncObj) + { + state = State.CANCELLED; + } + } + } + return state == State.COMPLETED; + } - var offset = 0; - var curlScratchpadLowStep1 = new long[CurlStateLength]; - var curlScratchpadHighStep1 = new long[CurlStateLength]; + private void ValidateParameters(int[] transactionTrits, int minWeightMagnitude) + { + if (transactionTrits.Length != TRANSACTION_LENGTH) + { + throw new ArgumentException("Invalid transaction trits length: " + transactionTrits.Length); + } + if (minWeightMagnitude < 0 || minWeightMagnitude > CURL_HASH_LENGTH) + { + throw new ArgumentException("Invalid min weight magnitude: " + minWeightMagnitude); + } + } - for (var i = (TransactionLength - CurlHashLength) / CurlHashLength; i-- > 0;) - { - for (var j = 0; j < CurlHashLength; j++) - switch (transactionTrits[offset++]) - { - case 0: - midCurlStateLow[j] = HighBits; - midCurlStateHigh[j] = HighBits; - break; - case 1: - midCurlStateLow[j] = LowBits; - midCurlStateHigh[j] = HighBits; - break; - default: - midCurlStateLow[j] = HighBits; - midCurlStateHigh[j] = LowBits; - break; - } + private static void InitializeMidCurlStates(int[] transactionTrits, long[] midStateLow, long[] midStateHigh) + { + for (int i = CURL_HASH_LENGTH; i < CURL_STATE_LENGTH; i++) + { + midStateLow[i] = HIGH_BITS; + midStateHigh[i] = HIGH_BITS; + } - Transform(midCurlStateLow, midCurlStateHigh, - curlScratchpadLowStep1, curlScratchpadHighStep1); - } + int offset = 0; + long[] curlScratchpadLow = new long[CURL_STATE_LENGTH]; + long[] curlScratchpadHigh = new long[CURL_STATE_LENGTH]; + for (int i = (TRANSACTION_LENGTH - CURL_HASH_LENGTH) / CURL_HASH_LENGTH; i-- > 0;) + { - for (var i = 0; i < 162; i++) + for (int j = 0; j < CURL_HASH_LENGTH; j++) + { switch (transactionTrits[offset++]) { case 0: - midCurlStateLow[i] = HighBits; - midCurlStateHigh[i] = HighBits; + midStateLow[j] = HIGH_BITS; + midStateHigh[j] = HIGH_BITS; break; case 1: - midCurlStateLow[i] = LowBits; - midCurlStateHigh[i] = HighBits; + midStateLow[j] = LOW_BITS; + midStateHigh[j] = HIGH_BITS; break; default: - midCurlStateLow[i] = HighBits; - midCurlStateHigh[i] = LowBits; + midStateLow[j] = HIGH_BITS; + midStateHigh[j] = LOW_BITS; break; } + } + Transform(midStateLow, midStateHigh, curlScratchpadLow, curlScratchpadHigh); + } - unchecked + for (int i = 0; i < 162; i++) + { + switch (transactionTrits[offset++]) { - midCurlStateLow[162 + 0] = - (long) 0b1101101101101101101101101101101101101101101101101101101101101101L; - midCurlStateHigh[162 + 0] = - (long) 0b1011011011011011011011011011011011011011011011011011011011011011L; - midCurlStateLow[162 + 1] = - (long) 0b1111000111111000111111000111111000111111000111111000111111000111L; - midCurlStateHigh[162 + 1] = - (long) 0b1000111111000111111000111111000111111000111111000111111000111111L; - midCurlStateLow[162 + 2] = - 0b0111111111111111111000000000111111111111111111000000000111111111L; - midCurlStateHigh[162 + 2] = - (long) 0b1111111111000000000111111111111111111000000000111111111111111111L; - midCurlStateLow[162 + 3] = - (long) 0b1111111111000000000000000000000000000111111111111111111111111111L; - midCurlStateHigh[162 + 3] = - 0b0000000000111111111111111111111111111111111111111111111111111111L; + case 0: + midStateLow[i] = HIGH_BITS; + midStateHigh[i] = HIGH_BITS; + break; + case 1: + midStateLow[i] = LOW_BITS; + midStateHigh[i] = HIGH_BITS; + break; + default: + midStateLow[i] = HIGH_BITS; + midStateHigh[i] = LOW_BITS; + break; } } - // step2 - if (numberOfThreads <= 0) numberOfThreads = Math.Max(Environment.ProcessorCount - 1, 1); + unchecked + { + midStateLow[162 + 0] = (long)0b1101101101101101101101101101101101101101101101101101101101101101L; + midStateHigh[162 + 0] = (long)0b1011011011011011011011011011011011011011011011011011011011011011L; + midStateLow[162 + 1] = (long)0b1111000111111000111111000111111000111111000111111000111111000111L; + midStateHigh[162 + 1] = (long)0b1000111111000111111000111111000111111000111111000111111000111111L; + midStateLow[162 + 2] = (long)0b0111111111111111111000000000111111111111111111000000000111111111L; + midStateHigh[162 + 2] = (long)0b1111111111000000000111111111111111111000000000111111111111111111L; + midStateLow[162 + 3] = (long)0b1111111111000000000000000000000000000111111111111111111111111111L; + midStateHigh[162 + 3] = (long)0b0000000000111111111111111111111111111111111111111111111111111111L; + } + } - Parallel.For(0, numberOfThreads, threadIndex => + private void Perform(int threadIndex, int[] transactionTrits, int minWeightMagnitude, long[] midStateCopyLow, long[] midStateCopyHigh) + { + for (int i = 0; i < threadIndex; i++) { - var midCurlStateCopyLow = new long[CurlStateLength]; - var midCurlStateCopyHigh = new long[CurlStateLength]; - Array.Copy(midCurlStateLow, 0, midCurlStateCopyLow, 0, CurlStateLength); - Array.Copy(midCurlStateHigh, 0, midCurlStateCopyHigh, 0, CurlStateLength); - for (var i = threadIndex; i > 0; i--) - Increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + CurlHashLength / 9, - 162 + CurlHashLength / 9 * 2); - - var curlStateLow = new long[CurlStateLength]; - var curlStateHigh = new long[CurlStateLength]; - var curlScratchpadLowStep2 = new long[CurlStateLength]; - var curlScratchpadHighStep2 = new long[CurlStateLength]; - long outMask = 1; - - while (_state == State.Running) - { - Increment(midCurlStateCopyLow, midCurlStateCopyHigh, 162 + CurlHashLength / 9 * 2, - CurlHashLength); + Increment(midStateCopyLow, midStateCopyHigh, 162 + CURL_HASH_LENGTH / 9, + 162 + (CURL_HASH_LENGTH / 9) * 2); + } - Array.Copy(midCurlStateCopyLow, 0, curlStateLow, 0, CurlStateLength); - Array.Copy(midCurlStateCopyHigh, 0, curlStateHigh, 0, CurlStateLength); + long[] stateLow = new long[CURL_STATE_LENGTH]; + long[] stateHigh = new long[CURL_STATE_LENGTH]; - Transform(curlStateLow, curlStateHigh, curlScratchpadLowStep2, curlScratchpadHighStep2); + long[] scratchpadLow = new long[CURL_STATE_LENGTH]; + long[] scratchpadHigh = new long[CURL_STATE_LENGTH]; - var mask = HighBits; - for (var i = minWeightMagnitude; i-- > 0;) - { - mask &= ~(curlStateLow[CurlHashLength - 1 - i] ^ curlStateHigh[CurlHashLength - 1 - i]); - if (mask == 0) break; - } + int maskStartIndex = CURL_HASH_LENGTH - minWeightMagnitude; + long mask = 0; + while (state == State.RUNNING && mask == 0) + { + + Increment(midStateCopyLow, midStateCopyHigh, 162 + (CURL_HASH_LENGTH / 9) * 2, + CURL_HASH_LENGTH); - if (mask == 0) continue; + Copy(midStateCopyLow, midStateCopyHigh, stateLow, stateHigh); + Transform(stateLow, stateHigh, scratchpadLow, scratchpadHigh); - //sync - lock (SyncObj) + mask = HIGH_BITS; + for (int i = maskStartIndex; i < CURL_HASH_LENGTH && mask != 0; i++) + { + mask &= ~(stateLow[i] ^ stateHigh[i]); + } + } + if (mask != 0) + { + lock (SyncObj) + { + if (state == State.RUNNING) { - if (_state == State.Running) + state = State.COMPLETED; + long outMask = 1; + while ((outMask & mask) == 0) { - _state = State.Completed; - while ((outMask & mask) == 0) outMask <<= 1; - - for (var i = 0; i < CurlHashLength; i++) - transactionTrits[TransactionLength - CurlHashLength + i] = - (midCurlStateCopyLow[i] & outMask) == 0 ? 1 - : (midCurlStateCopyHigh[i] & outMask) == 0 ? -1 : 0; + outMask <<= 1; + } + for (int i = 0; i < CURL_HASH_LENGTH; i++) + { + transactionTrits[TRANSACTION_LENGTH - CURL_HASH_LENGTH + i] = + (midStateCopyLow[i] & outMask) == 0 ? 1 : (midStateCopyHigh[i] & outMask) == 0 ? -1 : 0; } } - - break; } - }); - - return _state == State.Completed; + } } - /// - /// - public void Cancel() + private static void Copy(long[] srcLow, long[] srcHigh, long[] destLow, long[] destHigh) { - lock (SyncObj) - { - _state = State.Cancelled; - } + Array.Copy(srcLow, 0, destLow, 0, CURL_STATE_LENGTH); + Array.Copy(srcHigh, 0, destHigh, 0, CURL_STATE_LENGTH); } - private static void Transform(long[] curlStateLow, long[] curlStateHigh, - long[] curlScratchpadLow, long[] curlScratchpadHigh) + private static void Transform(long[] stateLow, long[] stateHigh, long[] scratchpadLow, long[] scratchpadHigh) { - var curlScratchpadIndex = 0; - for (var round = 0; round < NumberOfRoundsp81; round++) + + for (int round = 0; round < 81; round++) { - Array.Copy(curlStateLow, 0, curlScratchpadLow, 0, CurlStateLength); - Array.Copy(curlStateHigh, 0, curlScratchpadHigh, 0, CurlStateLength); + Copy(stateLow, stateHigh, scratchpadLow, scratchpadHigh); - for (var curlStateIndex = 0; curlStateIndex < CurlStateLength; curlStateIndex++) + int scratchpadIndex = 0; + for (int stateIndex = 0; stateIndex < CURL_STATE_LENGTH; stateIndex++) { - var alpha = curlScratchpadLow[curlScratchpadIndex]; - var beta = curlScratchpadHigh[curlScratchpadIndex]; - if (curlScratchpadIndex < 365) - curlScratchpadIndex += 364; + long alpha = scratchpadLow[scratchpadIndex]; + long beta = scratchpadHigh[scratchpadIndex]; + if (scratchpadIndex < 365) + { + scratchpadIndex += 364; + } else - curlScratchpadIndex -= 365; - - var gamma = curlScratchpadHigh[curlScratchpadIndex]; - var delta = (alpha | (~gamma)) & (curlScratchpadLow[curlScratchpadIndex] ^ beta); + { + scratchpadIndex += -365; + } + long gamma = scratchpadHigh[scratchpadIndex]; + long delta = (alpha | (~gamma)) & (scratchpadLow[scratchpadIndex] ^ beta); - curlStateLow[curlStateIndex] = ~delta; - curlStateHigh[curlStateIndex] = (alpha ^ gamma) | delta; + stateLow[stateIndex] = ~delta; + stateHigh[stateIndex] = (alpha ^ gamma) | delta; } } } - private static void Increment(long[] midCurlStateCopyLow, - long[] midCurlStateCopyHigh, int fromIndex, int toIndex) + private static void Increment(long[] midCurlStateCopyLow, long[] midCurlStateCopyHigh, int fromIndex, int toIndex) { for (var i = fromIndex; i < toIndex; i++) - if (midCurlStateCopyLow[i] == LowBits) + if (midCurlStateCopyLow[i] == LOW_BITS) { - midCurlStateCopyLow[i] = HighBits; - midCurlStateCopyHigh[i] = LowBits; + midCurlStateCopyLow[i] = HIGH_BITS; + midCurlStateCopyHigh[i] = LOW_BITS; } else { - if (midCurlStateCopyHigh[i] == LowBits) - midCurlStateCopyHigh[i] = HighBits; + if (midCurlStateCopyHigh[i] == LOW_BITS) + midCurlStateCopyHigh[i] = HIGH_BITS; else - midCurlStateCopyLow[i] = LowBits; + midCurlStateCopyLow[i] = LOW_BITS; break; } } - private enum State - { - Running, - Cancelled, - Completed - } } } \ No newline at end of file diff --git a/IotaApi.Standard/Utils/ArrayUtils.cs b/IotaApi.Standard/Utils/ArrayUtils.cs index 49f95b9..4f5fd2b 100644 --- a/IotaApi.Standard/Utils/ArrayUtils.cs +++ b/IotaApi.Standard/Utils/ArrayUtils.cs @@ -3,7 +3,7 @@ namespace Iota.Api.Standard.Utils { - internal class ArrayUtils + public class ArrayUtils { public static IEnumerable SliceRow(T[,] array, int row) { @@ -27,5 +27,53 @@ public static T[] SubArray2(T[] data, int index, int length) Array.Copy(data, index, result, 0, length); return result; } + + /// + /// Pads an array of type int with zeros until a given size is reached. + /// + /// The array. + /// The new length. + /// An int array of the new size. + public static int[] PadArrayWithZeros(int[] oldArray, int newLength) + { + if (oldArray.Length > newLength) + { + throw new ArgumentException("The desired length must be larger then the size of the array"); + } + int[] newArray = new int[newLength]; + Array.Copy(oldArray, newArray, oldArray.Length); + + int index = oldArray.Length; + while (index < newLength) + { + newArray[index] = 0; + index++; + } + return newArray; + } + + /// + /// Fills a trit-array with approriate zeroes so that the length can be divided by the RADIX + /// + /// The trit-array + /// The filled trit-array + public static int[] PadTritArrayWithZeroes(int[] trits) + { + List list = new List(trits); + switch (list.Count % Constants.RADIX) + { + case 0: + break; + case 1: + list.Add(0); + list.Add(0); + break; + case 2: + list.Add(0); + break; + } + + return list.ToArray(); + } } } diff --git a/IotaApi.Standard/Utils/Checksum.cs b/IotaApi.Standard/Utils/Checksum.cs index 1ac1cea..13e5d62 100644 --- a/IotaApi.Standard/Utils/Checksum.cs +++ b/IotaApi.Standard/Utils/Checksum.cs @@ -41,7 +41,7 @@ public static string RemoveChecksum(this string address) internal static string GetAddress(string addressWithChecksum) { - return addressWithChecksum.Substring(0, Constants.AddressLengthWithoutChecksum); + return addressWithChecksum.Substring(0, Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM); } /// @@ -63,12 +63,12 @@ public static bool IsValidChecksum(this string addressWithChecksum) private static bool IsAddressWithChecksum(string addressWithChecksum) { return InputValidator.IsAddress(addressWithChecksum) && - addressWithChecksum.Length == Constants.AddressLengthWithChecksum; + addressWithChecksum.Length == Constants.ADDRESS_LENGTH_WITH_CHECKSUM; } private static bool IsAddressWithoutChecksum(string address) { - return InputValidator.CheckAddress(address) && address.Length == Constants.AddressLengthWithoutChecksum; + return InputValidator.CheckAddress(address) && address.Length == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM; } private static string CalculateChecksum(string address) diff --git a/IotaApi.Standard/Utils/Constants.cs b/IotaApi.Standard/Utils/Constants.cs index 76abcb0..9f00658 100644 --- a/IotaApi.Standard/Utils/Constants.cs +++ b/IotaApi.Standard/Utils/Constants.cs @@ -5,39 +5,24 @@ /// public static class Constants { - /// - /// This String contains all possible characters of the tryte alphabet - /// - public static readonly string TryteAlphabet = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - /// - /// The maximum seed length - /// - public static readonly int SeedLengthMax = 81; - - /// - /// This String represents the empty hash consisting of '9' - /// - public static readonly string EmptyHash = - "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; - - /// - /// The length of an address without checksum - /// - public static readonly int AddressLengthWithoutChecksum = 81; - - /// - /// The address length with checksum - /// - public static readonly int AddressLengthWithChecksum = 90; - - /// - /// The length of an message - /// - public static int MessageLength = 2187; - /// - /// - /// - public static int TagLength = 27; + public const string TRYTE_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + public const int SEED_LENGTH_MAX = 81; + + public const string EMPTY_HASH = "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; + + public const int ADDRESS_LENGTH_WITHOUT_CHECKSUM = 81; + + public const int ADDRESS_LENGTH_WITH_CHECKSUM = 90; + + public const int MESSAGE_LENGTH = 2187; + + public const int TAG_LENGTH = 27; + + public const int RADIX = 3; + + public const int MAX_TRIT_VALUE = 1; + + public const int MIN_TRIT_VALUE = -1; } } \ No newline at end of file diff --git a/IotaApi.Standard/Utils/Converter.cs b/IotaApi.Standard/Utils/Converter.cs index 711dc66..c5e51f8 100644 --- a/IotaApi.Standard/Utils/Converter.cs +++ b/IotaApi.Standard/Utils/Converter.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Numerics; using System.Text; +using static Iota.Api.Standard.Utils.Constants; namespace Iota.Api.Standard.Utils { @@ -46,7 +49,7 @@ public class Converter /// public static readonly int NumberOfTritsInATryte = 3; - static readonly int[][] ByteToTritsMappings = new int[243][]; //why 243? max 121 + static readonly int[][] ByteToTritsMappings = new int[243][]; static readonly int[][] TryteToTritsMappings = new int[27][]; static Converter() @@ -166,7 +169,7 @@ public static int[] ToTrits(string trytes) int[] d = new int[3 * trytes.Length]; for (int i = 0; i < trytes.Length; i++) { - Array.Copy(TryteToTritsMappings[Constants.TryteAlphabet.IndexOf(trytes[i])], 0, d, + Array.Copy(TryteToTritsMappings[Constants.TRYTE_ALPHABET.IndexOf(trytes[i])], 0, d, i * NumberOfTritsInATryte, NumberOfTritsInATryte); } @@ -235,7 +238,7 @@ public static int[] CopyTrits(string input, int[] destination) { for (int i = 0; i < input.Length; i++) { - int index = Constants.TryteAlphabet.IndexOf(input[i]); + int index = Constants.TRYTE_ALPHABET.IndexOf(input[i]); destination[i * 3] = TryteToTritsMappings[index][0]; destination[i * 3 + 1] = TryteToTritsMappings[index][1]; destination[i * 3 + 2] = TryteToTritsMappings[index][2]; @@ -291,10 +294,10 @@ public static string ToTrytes(int[] trits, int offset, int size) int j = trits[offset + i * 3] + trits[offset + i * 3 + 1] * 3 + trits[offset + i * 3 + 2] * 9; if (j < 0) { - j += Constants.TryteAlphabet.Length; + j += Constants.TRYTE_ALPHABET.Length; } - trytes.Append(Constants.TryteAlphabet[j]); + trytes.Append(Constants.TRYTE_ALPHABET[j]); } return trytes.ToString(); @@ -355,6 +358,95 @@ public static long ToLongValue(int[] trits) return value; } + /// + /// Converts a trit-array to a BigInteger + /// + /// The trit-array + /// A BigInteger + public static BigInteger ConvertTritsToBigInt(int[] trits) + { + BigInteger value = BigInteger.Zero; + + for (var i = trits.Length; i-- > 0;) + { + value = BigInteger.Add(BigInteger.Multiply(Constants.RADIX, value), new BigInteger(trits[i])); + } + + return value; + } + + /// + /// Converts a BigInteger into a byte-array + /// + /// The BigInteger + /// The length of the returning byte-array + /// A byte-array + public static byte[] ConvertBigIntToBytes(BigInteger value, int outputLength) + { + byte[] result = new byte[outputLength]; + byte[] bytes = value.ToByteArray(); + bytes = bytes.Reverse().ToArray(); + + + var i = 0; + while (i + bytes.Length < outputLength) + { + if (value < 0) + { + result[i++] = 255; + } + else + { + result[i++] = 0; + } + } + + for (int j = bytes.Length; j-- > 0;) + { + result[i++] = bytes[bytes.Length - 1 - j]; + } + + return result; + } + + /// + /// Converts a BigInteger into a trit-array + /// + /// The BigInteger + /// A trit-array + public static int[] ConvertBigIntToTrits(BigInteger value) + { + List trits = new List(); + BigInteger absoluteValue = BigInteger.Abs(value); + int counter = 0; + while (absoluteValue > 0) + { + BigInteger quotient = BigInteger.DivRem(absoluteValue, new BigInteger(RADIX), out BigInteger remainder_as_bi); + + int remainder = (int)remainder_as_bi; + absoluteValue = quotient; + + if (remainder > MAX_TRIT_VALUE) + { + remainder = MIN_TRIT_VALUE; + absoluteValue = BigInteger.Add(absoluteValue, BigInteger.One); + } + trits.Add(remainder); + counter++; + } + + if (value < 0) + { + for (int i = 0; i < trits.Count; i++) + { + trits[i] = -trits[i]; + } + } + + int[] paddedArray = trits.ToArray(); + return ArrayUtils.PadTritArrayWithZeroes(paddedArray); + } + /// /// Increments the specified trits. /// diff --git a/IotaApi.Standard/Utils/InputValidator.cs b/IotaApi.Standard/Utils/InputValidator.cs index 372f9f8..dd84332 100644 --- a/IotaApi.Standard/Utils/InputValidator.cs +++ b/IotaApi.Standard/Utils/InputValidator.cs @@ -21,8 +21,8 @@ public static class InputValidator /// public static bool IsAddress(string address) { - if (address.Length == Constants.AddressLengthWithoutChecksum || - address.Length == Constants.AddressLengthWithChecksum) + if (address.Length == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM || + address.Length == Constants.ADDRESS_LENGTH_WITH_CHECKSUM) { return IsTrytes(address, address.Length); } @@ -101,7 +101,7 @@ public static bool IsArrayOfHashes(string[] hashes) } /// - /// Determines whether the specified string contains only characters from the trytes alphabet (see ) + /// Determines whether the specified string contains only characters from the trytes alphabet (see ) /// /// The trytes. /// The length. @@ -213,7 +213,7 @@ public static void CheckIfValidSeed(string seed) /// public static string PadSeedIfNecessary(string seed) { - while (seed.Length < Constants.AddressLengthWithoutChecksum) seed += 9; + while (seed.Length < Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM) seed += 9; return seed; } diff --git a/IotaApi.Standard/Utils/Multisig.cs b/IotaApi.Standard/Utils/Multisig.cs index 8dcccbd..5831e95 100644 --- a/IotaApi.Standard/Utils/Multisig.cs +++ b/IotaApi.Standard/Utils/Multisig.cs @@ -116,7 +116,7 @@ public Bundle AddSignature(Bundle bundleToSign, string inputAddress, string keyT { // Get the security used for the private key // 1 security level = 2187 trytes - var security = keyTrytes.Length / Constants.MessageLength; + var security = keyTrytes.Length / Constants.MESSAGE_LENGTH; // convert private key trytes into trits var key = Converter.ToTrits(keyTrytes); diff --git a/IotaApi.Standard/Utils/TrytesConverter.cs b/IotaApi.Standard/Utils/TrytesConverter.cs index 4b802ab..29422dc 100644 --- a/IotaApi.Standard/Utils/TrytesConverter.cs +++ b/IotaApi.Standard/Utils/TrytesConverter.cs @@ -23,8 +23,8 @@ public static string ToTrytes(string inputString) // If not recognizable ASCII character, replace with space if (asciiValue > 255) asciiValue = ' '; - trytes.Append(Constants.TryteAlphabet[asciiValue % 27]); - trytes.Append(Constants.TryteAlphabet[asciiValue / 27]); + trytes.Append(Constants.TRYTE_ALPHABET[asciiValue % 27]); + trytes.Append(Constants.TRYTE_ALPHABET[asciiValue / 27]); } return trytes.ToString(); diff --git a/IotaApi.sln b/IotaApi.sln index 0bccfcf..b6f0471 100644 --- a/IotaApi.sln +++ b/IotaApi.sln @@ -7,9 +7,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaCSharpApi", "IotaCSharp EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaCSharpApiUnitTests", "IotaCSharpApiUnitTests\IotaCSharpApiUnitTests.csproj", "{FAE71C0D-C373-4401-B9DE-BC3DC1D4E435}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard", "IotaApi.Standard\IotaApi.Standard.csproj", "{8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IotaApi.Standard", "IotaApi.Standard\IotaApi.Standard.csproj", "{8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard.Tests", "IotaApi.Standard.Tests\IotaApi.Standard.Tests.csproj", "{1797EB77-756A-4B7C-94FD-FC86B7EB7930}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard.IntegrationTests", "IotaApi.Standard.IntegrationTests\IotaApi.Standard.IntegrationTests.csproj", "{473C394B-B8D2-4758-9FDC-139B13388FB9}" + ProjectSection(ProjectDependencies) = postProject + {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900} = {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IotaApi.Standard.UnitTests", "IotaApi.Standard.UnitTests\IotaApi.Standard.UnitTests.csproj", "{A3E3E598-F973-4FB3-803A-5DB121BA1141}" + ProjectSection(ProjectDependencies) = postProject + {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900} = {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -29,10 +37,14 @@ Global {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Debug|Any CPU.Build.0 = Debug|Any CPU {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Release|Any CPU.ActiveCfg = Release|Any CPU {8E8D67DF-1A0E-45AA-8DE7-CBAD2EF4B900}.Release|Any CPU.Build.0 = Release|Any CPU - {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1797EB77-756A-4B7C-94FD-FC86B7EB7930}.Release|Any CPU.Build.0 = Release|Any CPU + {473C394B-B8D2-4758-9FDC-139B13388FB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {473C394B-B8D2-4758-9FDC-139B13388FB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {473C394B-B8D2-4758-9FDC-139B13388FB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {473C394B-B8D2-4758-9FDC-139B13388FB9}.Release|Any CPU.Build.0 = Release|Any CPU + {A3E3E598-F973-4FB3-803A-5DB121BA1141}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3E3E598-F973-4FB3-803A-5DB121BA1141}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3E3E598-F973-4FB3-803A-5DB121BA1141}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3E3E598-F973-4FB3-803A-5DB121BA1141}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE