diff --git a/BeeNet.sln b/BeeNet.sln
index 09c39e51..ac75d7bb 100644
--- a/BeeNet.sln
+++ b/BeeNet.sln
@@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.3.32811.315
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeeNet", "src\BeeNet\BeeNet.csproj", "{653BEB35-743E-4612-BEF4-7B26C6FB3D8F}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7932D52A-3D44-4723-9E77-1711F7486417}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{6EAC22F4-C9F3-4C2E-A0AC-922D4F92B8F6}"
@@ -13,9 +11,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
.gitignore = .gitignore
CODE_OF_CONDUCT.md = CODE_OF_CONDUCT.md
CONTRIBUTING.md = CONTRIBUTING.md
- COPYING = COPYING
- README.md = README.md
- COPYING-LESSER = COPYING-LESSER
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{C162BCCF-B5C8-466A-AAB7-6D85CC171434}"
@@ -39,9 +34,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{990C5C57-6E00-4E76-A23A-519F19290ACB}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeeNet.IntegrationTest", "test\BeeNet.IntegrationTest\BeeNet.IntegrationTest.csproj", "{F0C776C9-4856-4031-B4CE-18E53FEF9E55}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeeNet.Client.IntegrationTest", "test\BeeNet.Client.IntegrationTest\BeeNet.Client.IntegrationTest.csproj", "{F0C776C9-4856-4031-B4CE-18E53FEF9E55}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Core", "src\BeeNet.Core\BeeNet.Core.csproj", "{0C681EE6-7290-4548-9502-4C9B6B061F12}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Util", "src\BeeNet.Util\BeeNet.Util.csproj", "{FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Client", "src\BeeNet.Client\BeeNet.Client.csproj", "{EC667802-776E-4306-922C-AA23C7D5835B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Core.UnitTest", "test\BeeNet.Core.UnitTest\BeeNet.Core.UnitTest.csproj", "{63368E76-475A-45BE-B6DB-86402C041C39}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Util.UnitTest", "test\BeeNet.Util.UnitTest\BeeNet.Util.UnitTest.csproj", "{BBC17EDC-660C-4006-A14C-377693290D5E}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BeeNet.Tests", "test\BeeNet.Tests\BeeNet.Tests.csproj", "{549BB2F5-D48E-4785-AF14-EF116A79AD00}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BeeNet.Util.Wasm", "src\BeeNet.Util.Wasm\BeeNet.Util.Wasm.csproj", "{7257332C-5291-4814-B00B-3732BE90FB2E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -49,29 +54,49 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {653BEB35-743E-4612-BEF4-7B26C6FB3D8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {653BEB35-743E-4612-BEF4-7B26C6FB3D8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {653BEB35-743E-4612-BEF4-7B26C6FB3D8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {653BEB35-743E-4612-BEF4-7B26C6FB3D8F}.Release|Any CPU.Build.0 = Release|Any CPU
{F0C776C9-4856-4031-B4CE-18E53FEF9E55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0C776C9-4856-4031-B4CE-18E53FEF9E55}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0C776C9-4856-4031-B4CE-18E53FEF9E55}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0C776C9-4856-4031-B4CE-18E53FEF9E55}.Release|Any CPU.Build.0 = Release|Any CPU
- {549BB2F5-D48E-4785-AF14-EF116A79AD00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {549BB2F5-D48E-4785-AF14-EF116A79AD00}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {549BB2F5-D48E-4785-AF14-EF116A79AD00}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {549BB2F5-D48E-4785-AF14-EF116A79AD00}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0C681EE6-7290-4548-9502-4C9B6B061F12}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0C681EE6-7290-4548-9502-4C9B6B061F12}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0C681EE6-7290-4548-9502-4C9B6B061F12}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0C681EE6-7290-4548-9502-4C9B6B061F12}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EC667802-776E-4306-922C-AA23C7D5835B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EC667802-776E-4306-922C-AA23C7D5835B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EC667802-776E-4306-922C-AA23C7D5835B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EC667802-776E-4306-922C-AA23C7D5835B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {63368E76-475A-45BE-B6DB-86402C041C39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {63368E76-475A-45BE-B6DB-86402C041C39}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {63368E76-475A-45BE-B6DB-86402C041C39}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {63368E76-475A-45BE-B6DB-86402C041C39}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BBC17EDC-660C-4006-A14C-377693290D5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BBC17EDC-660C-4006-A14C-377693290D5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BBC17EDC-660C-4006-A14C-377693290D5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BBC17EDC-660C-4006-A14C-377693290D5E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7257332C-5291-4814-B00B-3732BE90FB2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7257332C-5291-4814-B00B-3732BE90FB2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7257332C-5291-4814-B00B-3732BE90FB2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7257332C-5291-4814-B00B-3732BE90FB2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {653BEB35-743E-4612-BEF4-7B26C6FB3D8F} = {7932D52A-3D44-4723-9E77-1711F7486417}
{C162BCCF-B5C8-466A-AAB7-6D85CC171434} = {6EAC22F4-C9F3-4C2E-A0AC-922D4F92B8F6}
{1956F8A3-25CE-42BB-8AE5-77ACC56B9B92} = {C162BCCF-B5C8-466A-AAB7-6D85CC171434}
{F6289FE6-5CC0-4225-98BC-2DCFE85C767F} = {6EAC22F4-C9F3-4C2E-A0AC-922D4F92B8F6}
{F0C776C9-4856-4031-B4CE-18E53FEF9E55} = {990C5C57-6E00-4E76-A23A-519F19290ACB}
- {549BB2F5-D48E-4785-AF14-EF116A79AD00} = {990C5C57-6E00-4E76-A23A-519F19290ACB}
+ {0C681EE6-7290-4548-9502-4C9B6B061F12} = {7932D52A-3D44-4723-9E77-1711F7486417}
+ {FDB74F14-61A0-42D9-89C1-8F8DA8A8A4C2} = {7932D52A-3D44-4723-9E77-1711F7486417}
+ {EC667802-776E-4306-922C-AA23C7D5835B} = {7932D52A-3D44-4723-9E77-1711F7486417}
+ {63368E76-475A-45BE-B6DB-86402C041C39} = {990C5C57-6E00-4E76-A23A-519F19290ACB}
+ {BBC17EDC-660C-4006-A14C-377693290D5E} = {990C5C57-6E00-4E76-A23A-519F19290ACB}
+ {7257332C-5291-4814-B00B-3732BE90FB2E} = {7932D52A-3D44-4723-9E77-1711F7486417}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BC8368EB-8E3B-4FBB-B657-D1C9375AFAFC}
diff --git a/BeeNet.sln.DotSettings b/BeeNet.sln.DotSettings
index 9bd7b53e..1e2d99e2 100644
--- a/BeeNet.sln.DotSettings
+++ b/BeeNet.sln.DotSettings
@@ -15,4 +15,5 @@ If not, see <https://www.gnu.org/licenses/>.
True
- True
\ No newline at end of file
+ True
+ True
\ No newline at end of file
diff --git a/README.md b/README.md
index 049d26f6..74408306 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,20 @@ With this client you can consume public and debug api of any Bee node exposing t
This includes also some useful to calculate data chunking, and postage batch usage.
+## Packages
+
+There are several NuGet packages available for Bee.Net. Here's a brief description of each:
+
+1. **Bee.Net.Client**: This package contains a client that is designed to connect to and work with Bee Swarm. It
+ simplifies the interaction with Bee nodes by providing high-level methods and classes.
+
+2. **Bee.Net.Core**: This package contains the base models for working with Swarm. These models represent the core
+ entities in the Swarm world and provide a foundation for interacting with the Bee Swarm.
+
+3. **Bee.Net.Util**: This package contains a series of useful tools. These tools include utilities for data chunking,
+ calculating postage batch usage, and other helpful operations that enhance your experience when working with
+ Swarm.
+
## Package repositories
You can get latest public releases from Nuget.org feed. Here you can see our [published packages](https://www.nuget.org/profiles/etherna).
diff --git a/src/BeeNet.Client/BeeClient.cs b/src/BeeNet.Client/BeeClient.cs
new file mode 100644
index 00000000..0cb7b550
--- /dev/null
+++ b/src/BeeNet.Client/BeeClient.cs
@@ -0,0 +1,1189 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Clients;
+using Etherna.BeeNet.Exceptions;
+using Etherna.BeeNet.Hashing.Store;
+using Etherna.BeeNet.Manifest;
+using Etherna.BeeNet.Models;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Net.Http;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Threading.Tasks;
+using FileResponse = Etherna.BeeNet.Models.FileResponse;
+using Loggers = Etherna.BeeNet.Models.Loggers;
+
+#if NET7_0_OR_GREATER
+using System.Formats.Tar;
+#endif
+
+namespace Etherna.BeeNet
+{
+ [SuppressMessage("Design", "CA1054:URI-like parameters should not be strings")]
+ public class BeeClient : IBeeClient, IDisposable
+ {
+ // Consts.
+ public const int DefaultPort = 1633;
+ public readonly TimeSpan DefaultTimeout = TimeSpan.FromMinutes(10);
+
+ // Fields.
+ private readonly BeeGeneratedClient generatedClient;
+ private readonly HttpClient httpClient;
+
+ private bool disposed;
+
+ // Constructors.
+ public BeeClient(
+ string baseUrl = "http://localhost/",
+ int port = DefaultPort,
+ HttpClient? httpClient = null)
+ : this(BuildBaseUrl(baseUrl, port), httpClient)
+ { }
+
+ public BeeClient(
+ Uri baseUrl,
+ HttpClient? httpClient = null)
+ {
+ this.httpClient = httpClient ?? new HttpClient { Timeout = DefaultTimeout };
+
+ BaseUrl = baseUrl;
+ generatedClient = new BeeGeneratedClient(this.httpClient) { BaseUrl = BaseUrl.ToString() };
+ }
+
+ // Dispose.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed) return;
+
+ // Dispose managed resources.
+ if (disposing)
+ httpClient.Dispose();
+
+ disposed = true;
+ }
+
+
+ // Properties.
+ public Uri BaseUrl { get; }
+
+ // Methods.
+ public async Task> AccountingAsync(
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.AccountingAsync(cancellationToken).ConfigureAwait(false)).PeerData.ToDictionary(
+ i => i.Key,
+ i => new Account(
+ balance: BzzBalance.FromPlurString(i.Value.Balance),
+ thresholdReceived: BzzBalance.FromPlurString(i.Value.ThresholdReceived),
+ thresholdGiven: BzzBalance.FromPlurString(i.Value.ThresholdGiven),
+ surplusBalance: BzzBalance.FromPlurString(i.Value.SurplusBalance),
+ reservedBalance: BzzBalance.FromPlurString(i.Value.ReservedBalance),
+ shadowReservedBalance: BzzBalance.FromPlurString(i.Value.ShadowReservedBalance),
+ ghostBalance: BzzBalance.FromPlurString(i.Value.GhostBalance)));
+
+ public async Task AuthenticateAsync(string role, int expiry) =>
+ (await generatedClient.AuthAsync(
+ new Body
+ {
+ Role = role,
+ Expiry = expiry
+ }).ConfigureAwait(false)).Key;
+
+ public async Task BuyPostageBatchAsync(
+ BzzBalance amount,
+ int depth,
+ string? label = null,
+ bool? immutable = null,
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.StampsPostAsync(
+ amount.ToPlurString(),
+ depth,
+ label,
+ immutable,
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false)).BatchID;
+
+ public async Task CashoutChequeForPeerAsync(
+ string peerId,
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChequebookCashoutPostAsync(
+ peerId,
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ public async Task CheckChunkExistsAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default)
+ {
+ try
+ {
+ await generatedClient.ChunksHeadAsync(hash.ToString(), cancellationToken).ConfigureAwait(false);
+ return true;
+ }
+ catch (BeeNetApiException)
+ {
+ return false;
+ }
+ }
+
+ public async Task CheckPinsAsync(
+ SwarmHash? hash,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.PinsCheckAsync(
+ hash?.ToString(),
+ cancellationToken).ConfigureAwait(false);
+ return new CheckPinsResult(
+ hash: response.Reference,
+ invalid: response.Invalid,
+ missing: response.Missing,
+ total: response.Total);
+ }
+
+ public async Task ConnectToPeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ConnectAsync(peerAddress, cancellationToken).ConfigureAwait(false)).Address;
+
+ public async Task CreateFeedAsync(
+ string owner,
+ string topic,
+ PostageBatchId batchId,
+ string? type = null,
+ bool? swarmPin = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.FeedsPostAsync(owner, topic, type, swarmPin, batchId.ToString(), cancellationToken).ConfigureAwait(false)).Reference;
+
+ public Task CreatePinAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.PinsPostAsync((string)hash, cancellationToken);
+
+ public async Task CreateTagAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TagsPostAsync(cancellationToken).ConfigureAwait(false);
+ return new TagInfo(
+ uid: response.Uid,
+ startedAt: response.StartedAt,
+ split: response.Split,
+ seen: response.Seen,
+ stored: response.Stored,
+ sent: response.Sent,
+ synced: response.Synced);
+ }
+
+ public Task DeletePeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.PeersDeleteAsync(peerAddress, cancellationToken);
+
+ public Task DeletePinAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.PinsDeleteAsync((string)hash, cancellationToken);
+
+ public Task DeleteTagAsync(
+ long uid,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.TagsDeleteAsync(uid, cancellationToken);
+
+ public async Task DeleteTransactionAsync(
+ string txHash,
+ XDaiBalance? gasPrice = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.TransactionsDeleteAsync(
+ txHash,
+ gasPrice?.ToWeiLong(),
+ cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ public async Task DepositIntoChequebookAsync(
+ BzzBalance amount,
+ XDaiBalance? gasPrice = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChequebookDepositAsync(
+ amount.ToPlurLong(),
+ gasPrice?.ToWeiLong(),
+ cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ public async Task DilutePostageBatchAsync(
+ PostageBatchId batchId,
+ int depth,
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.StampsDiluteAsync(
+ batchId.ToString(),
+ depth,
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false)).BatchID;
+
+ public async Task GetAddressesAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.AddressesAsync(cancellationToken).ConfigureAwait(false);
+ return new AddressDetail(
+ underlay: response.Underlay.Where(i => !string.IsNullOrWhiteSpace(i)),
+ overlay: response.Overlay,
+ ethereum: response.Ethereum,
+ publicKey: response.PublicKey,
+ pssPublicKey: response.PssPublicKey);
+ }
+
+ public async Task> GetAllBalancesAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.BalancesGetAsync(cancellationToken).ConfigureAwait(false);
+ return response.Balances.ToDictionary(
+ b => b.Peer,
+ b => BzzBalance.FromPlurString(b.Balance));
+ }
+
+ public async Task> GetAllChequebookChequesAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ChequebookChequeGetAsync(cancellationToken).ConfigureAwait(false);
+ return response.Lastcheques.Select(c =>
+ new ChequebookCheque(
+ peer: c.Peer,
+ lastReceived: c.Lastreceived is not null ? new ChequePayment(
+ beneficiary: c.Lastreceived.Beneficiary,
+ chequebook: c.Lastreceived.Chequebook,
+ payout: BzzBalance.FromPlurString(c.Lastreceived.Payout)) : null,
+ lastSent: c.Lastsent is not null ? new ChequePayment(
+ beneficiary: c.Lastsent.Beneficiary,
+ chequebook: c.Lastsent.Chequebook,
+ payout: BzzBalance.FromPlurString(c.Lastsent.Payout)) : null));
+ }
+
+ public async Task> GetAllConsumedBalancesAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ConsumedGetAsync(cancellationToken).ConfigureAwait(false);
+ return response.Balances.ToDictionary(
+ b => b.Peer,
+ b => BzzBalance.FromPlurString(b.Balance));
+ }
+
+ public async Task> GetAllPeerAddressesAsync(CancellationToken cancellationToken = default) =>
+ (await generatedClient.PeersGetAsync(cancellationToken).ConfigureAwait(false)).Peers.Select(i => i.Address);
+
+ public async Task> GetAllPinsAsync(CancellationToken cancellationToken = default) =>
+ (await generatedClient.PinsGetAsync(cancellationToken).ConfigureAwait(false)).Reference
+ .Select(h => new SwarmHash(h));
+
+ public async Task GetAllSettlementsAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.SettlementsGetAsync(cancellationToken).ConfigureAwait(false);
+ return new Settlement(
+ totalReceived: BzzBalance.FromPlurString(response.TotalReceived),
+ totalSent: BzzBalance.FromPlurString(response.TotalSent),
+ settlements: response.Settlements
+ .Select(s => new SettlementData(
+ peer: s.Peer,
+ received: BzzBalance.FromPlurString(s.Received),
+ sent: BzzBalance.FromPlurString(s.Sent))));
+ }
+
+ public async Task GetAllTimeSettlementsAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TimesettlementsAsync(cancellationToken).ConfigureAwait(false);
+ return new Settlement(
+ totalReceived: BzzBalance.FromPlurString(response.TotalReceived),
+ totalSent: BzzBalance.FromPlurString(response.TotalSent),
+ settlements: response.Settlements
+ .Select(s => new SettlementData(
+ peer: s.Peer,
+ received: BzzBalance.FromPlurString(s.Received),
+ sent: BzzBalance.FromPlurString(s.Sent))));
+ }
+
+ public async Task>> GetAllValidPostageBatchesFromAllNodesAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.BatchesAsync(cancellationToken).ConfigureAwait(false);
+ return response.Batches.GroupBy(b => b.Owner)
+ .ToDictionary(
+ g => g.Key,
+ g => g.Select(batch => new PostageBatch(
+ id: batch.BatchID,
+ amount: BzzBalance.FromPlurString(batch.Value),
+ blockNumber: batch.Start,
+ depth: batch.Depth,
+ exists: true,
+ isImmutable: batch.ImmutableFlag,
+ isUsable: true,
+ label: null,
+ storageRadius: batch.StorageRadius,
+ ttl: TimeSpan.FromSeconds(batch.BatchTTL),
+ utilization: null)));
+ }
+
+ public async Task GetBalanceWithPeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default) =>
+ BzzBalance.FromPlurString(
+ (await generatedClient.BalancesGetAsync(peerAddress, cancellationToken).ConfigureAwait(false)).Balance);
+
+ public async Task GetBytesAsync(
+ SwarmHash hash,
+ bool? swarmCache = null,
+ RedundancyStrategy? swarmRedundancyStrategy = null,
+ bool? swarmRedundancyFallbackMode = null,
+ string? swarmChunkRetrievalTimeout = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.BytesGetAsync(
+ (string)hash,
+ swarmCache,
+ (SwarmRedundancyStrategy?)swarmRedundancyStrategy,
+ swarmRedundancyFallbackMode,
+ swarmChunkRetrievalTimeout,
+ cancellationToken).ConfigureAwait(false)).Stream;
+
+ public Task GetBytesHeadAsync(SwarmHash hash, CancellationToken cancellationToken = default) =>
+ generatedClient.BytesHeadAsync(hash.ToString(), cancellationToken);
+
+ public async Task> GetBlocklistedPeerAddressesAsync(CancellationToken cancellationToken = default) =>
+ (await generatedClient.BlocklistAsync(cancellationToken).ConfigureAwait(false)).Select(i => i.Address.Address1);
+
+ public async Task GetChainStateAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ChainstateAsync(cancellationToken).ConfigureAwait(false);
+ return new ChainState(
+ block: response.Block,
+ chainTip: response.ChainTip,
+ currentPrice: BzzBalance.FromPlurString(response.CurrentPrice),
+ totalAmount: BzzBalance.FromPlurString(response.TotalAmount));
+ }
+
+ public async Task GetChequebookAddressAsync(CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChequebookAddressAsync(cancellationToken).ConfigureAwait(false)).ChequebookAddress;
+
+ public async Task GetChequebookBalanceAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ChequebookBalanceAsync(cancellationToken).ConfigureAwait(false);
+ return new ChequebookBalance(
+ totalBalance: BzzBalance.FromPlurString(response.TotalBalance),
+ availableBalance: BzzBalance.FromPlurString(response.AvailableBalance));
+ }
+
+ public async Task GetChequebookCashoutForPeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ChequebookCashoutGetAsync(
+ peerAddress,
+ cancellationToken).ConfigureAwait(false);
+ return new ChequebookCashout(
+ peer: response.Peer,
+ lastCashedCheque: response.LastCashedCheque is not null
+ ? new ChequePayment(
+ response.LastCashedCheque.Beneficiary,
+ response.LastCashedCheque.Chequebook,
+ BzzBalance.FromPlurString(response.LastCashedCheque.Payout))
+ : null,
+ transactionHash: response.TransactionHash,
+ result: new ResultChequebook(
+ recipient: response.Result.Recipient,
+ lastPayout: BzzBalance.FromPlurString(response.Result.LastPayout),
+ bounced: response.Result.Bounced),
+ uncashedAmount: BzzBalance.FromPlurString(response.UncashedAmount));
+ }
+
+ public async Task GetChequebookChequeForPeerAsync(
+ string peerId,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ChequebookChequeGetAsync(peerId, cancellationToken).ConfigureAwait(false);
+ return new ChequebookCheque(
+ peer: response.Peer,
+ lastReceived: response.Lastreceived is not null ? new ChequePayment(
+ beneficiary: response.Lastreceived.Beneficiary,
+ chequebook: response.Lastreceived.Chequebook,
+ payout: BzzBalance.FromPlurString(response.Lastreceived.Payout)) : null,
+ lastSent: response.Lastsent is not null ? new ChequePayment(
+ beneficiary: response.Lastsent.Beneficiary,
+ chequebook: response.Lastsent.Chequebook,
+ payout: BzzBalance.FromPlurString(response.Lastsent.Payout)) : null);
+ }
+
+ public async Task GetChunkAsync(
+ SwarmHash hash,
+ bool? swarmCache = null,
+ CancellationToken cancellationToken = default)
+ {
+ var chunkDto = await generatedClient.ChunksGetAsync((string)hash, swarmCache, cancellationToken).ConfigureAwait(false);
+ using var memoryStream = new MemoryStream();
+ await chunkDto.Stream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
+ var data = memoryStream.ToArray();
+ return new SwarmChunk(hash, data);
+ }
+
+ public async Task GetChunkStreamAsync(
+ SwarmHash hash,
+ bool? swarmCache = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChunksGetAsync(hash.ToString(), swarmCache, cancellationToken).ConfigureAwait(false)).Stream;
+
+ public async Task GetConsumedBalanceWithPeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default) =>
+ BzzBalance.FromPlurString(
+ (await generatedClient.ConsumedGetAsync(peerAddress, cancellationToken).ConfigureAwait(false)).Balance);
+
+ public async Task GetFeedAsync(
+ string owner,
+ string topic,
+ int? at = null,
+ int? after = null,
+ string? type = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.FeedsGetAsync(owner, topic, at, after, type, cancellationToken).ConfigureAwait(false)).Reference;
+
+ public async Task GetFileAsync(
+ SwarmAddress address,
+ bool? swarmCache = null,
+ RedundancyStrategy? swarmRedundancyStrategy = null,
+ bool? swarmRedundancyFallbackMode = null,
+ string? swarmChunkRetrievalTimeout = null,
+ CancellationToken cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(address, nameof(address));
+
+ if (address.Path is null)
+ {
+ var response = await generatedClient.BzzGetAsync(
+ address.Hash.ToString(),
+ swarmCache,
+ (SwarmRedundancyStrategy2?)swarmRedundancyStrategy,
+ swarmRedundancyFallbackMode,
+ swarmChunkRetrievalTimeout,
+ cancellationToken).ConfigureAwait(false);
+ return new FileResponse(
+ response.Headers,
+ response.Stream);
+ }
+ else
+ {
+ var response = await generatedClient.BzzGetAsync(
+ address.Hash.ToString(),
+ address.Path.ToString(),
+ (SwarmRedundancyStrategy3?)swarmRedundancyStrategy,
+ swarmRedundancyFallbackMode,
+ swarmChunkRetrievalTimeout,
+ cancellationToken).ConfigureAwait(false);
+ return new FileResponse(
+ response.Headers,
+ response.Stream);
+ }
+ }
+
+ public Task GetFileHeadAsync(SwarmHash hash, CancellationToken cancellationToken = default) =>
+ generatedClient.BzzHeadAsync((string)hash, cancellationToken);
+
+ public async Task GetHealthAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.HealthAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ isStatusOk: response.Status switch
+ {
+ Response21Status.Ok => true,
+ Response21Status.Nok => false,
+ _ => throw new InvalidOperationException()
+ },
+ version: response.Version,
+ apiVersion: response.ApiVersion,
+ debugApiVersion: response.DebugApiVersion);
+ }
+
+ public async Task GetNodeInfoAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.NodeAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ beeMode: response.BeeMode switch
+ {
+ Response31BeeMode.Dev => InfoBeeMode.Dev,
+ Response31BeeMode.Full => InfoBeeMode.Full,
+ Response31BeeMode.Light => InfoBeeMode.Light,
+ _ => throw new InvalidOperationException()
+ },
+ chequebookEnabled: response.ChequebookEnabled,
+ swapEnabled: response.SwapEnabled);
+ }
+
+ public async Task> GetOwnedPostageBatchesByNodeAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.StampsGetAsync(cancellationToken).ConfigureAwait(false);
+ return response.Stamps.Select(b =>
+ new PostageBatch(
+ amount: BzzBalance.FromPlurString(b.Amount),
+ depth: b.Depth,
+ blockNumber: b.BlockNumber,
+ exists: b.Exists,
+ id: b.BatchID,
+ isImmutable: b.ImmutableFlag,
+ label: b.Label,
+ ttl: TimeSpan.FromSeconds(b.BatchTTL),
+ isUsable: b.Usable,
+ utilization: b.Utilization,
+ storageRadius: null));
+ }
+
+ public async Task> GetPendingTransactionsAsync(
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TransactionsGetAsync(cancellationToken).ConfigureAwait(false);
+ return response.PendingTransactions.Select(tx => new TxInfo(
+ transactionHash: tx.TransactionHash,
+ to: tx.To,
+ nonce: tx.Nonce,
+ gasPrice: XDaiBalance.FromWeiString(tx.GasPrice),
+ gasLimit: tx.GasLimit,
+ data: tx.Data,
+ created: tx.Created,
+ description: tx.Description,
+ value: XDaiBalance.FromWeiString(tx.Value)));
+ }
+
+ public async Task GetPinStatusAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.PinsGetAsync((string)hash, cancellationToken).ConfigureAwait(false)).Reference;
+
+ public async Task GetPostageBatchAsync(
+ PostageBatchId batchId,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.StampsGetAsync(
+ batchId.ToString(),
+ cancellationToken).ConfigureAwait(false);
+ return new PostageBatch(
+ amount: BzzBalance.FromPlurString(response.Amount),
+ depth: response.Depth,
+ blockNumber: response.BlockNumber,
+ exists: response.Exists,
+ id: response.BatchID,
+ isImmutable: response.ImmutableFlag,
+ label: response.Label,
+ ttl: TimeSpan.FromSeconds(response.BatchTTL),
+ isUsable: response.Usable,
+ utilization: response.Utilization,
+ storageRadius: null);
+ }
+
+ public async Task GetReserveCommitmentAsync(int depth, string anchor1, string anchor2,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.RchashAsync(depth, anchor1, anchor2, cancellationToken).ConfigureAwait(false);
+ return new(
+ duration: response.Duration,
+ hash: response.Hash,
+ proof1: new ReserveCommitmentProof(
+ chunkSpan: response.Proofs.Proof1.ChunkSpan,
+ postageProof: new Models.PostageProof(
+ index: response.Proofs.Proof1.PostageProof.Index,
+ postageId: response.Proofs.Proof1.PostageProof.PostageId,
+ signature: response.Proofs.Proof1.PostageProof.Signature,
+ timeStamp: DateTimeOffset.FromUnixTimeSeconds(
+ long.Parse(response.Proofs.Proof1.PostageProof.TimeStamp, CultureInfo.InvariantCulture))),
+ proofSegments: response.Proofs.Proof1.ProofSegments ?? Array.Empty(),
+ proofSegments2: response.Proofs.Proof1.ProofSegments2 ?? Array.Empty(),
+ proofSegments3: response.Proofs.Proof1.ProofSegments3 ?? Array.Empty(),
+ proveSegment: response.Proofs.Proof1.ProveSegment,
+ proveSegment2: response.Proofs.Proof1.ProveSegment2,
+ socProof: (response.Proofs.Proof1.SocProof ?? Array.Empty()).Select(
+ p => new Models.SocProof(
+ chunkHash: p.ChunkAddr,
+ identifier: p.Identifier,
+ signature: p.Signature,
+ signer: p.Signer))),
+ proof2: new ReserveCommitmentProof(
+ chunkSpan: response.Proofs.Proof2.ChunkSpan,
+ postageProof: new Models.PostageProof(
+ index: response.Proofs.Proof2.PostageProof.Index,
+ postageId: response.Proofs.Proof2.PostageProof.PostageId,
+ signature: response.Proofs.Proof2.PostageProof.Signature,
+ timeStamp: DateTimeOffset.FromUnixTimeSeconds(
+ long.Parse(response.Proofs.Proof2.PostageProof.TimeStamp, CultureInfo.InvariantCulture))),
+ proofSegments: response.Proofs.Proof2.ProofSegments ?? Array.Empty(),
+ proofSegments2: response.Proofs.Proof2.ProofSegments2 ?? Array.Empty(),
+ proofSegments3: response.Proofs.Proof2.ProofSegments3 ?? Array.Empty(),
+ proveSegment: response.Proofs.Proof2.ProveSegment,
+ proveSegment2: response.Proofs.Proof2.ProveSegment2,
+ socProof: (response.Proofs.Proof2.SocProof ?? Array.Empty()).Select(
+ p => new Models.SocProof(
+ chunkHash: p.ChunkAddr,
+ identifier: p.Identifier,
+ signature: p.Signature,
+ signer: p.Signer))),
+ proofLast: new ReserveCommitmentProof(
+ chunkSpan: response.Proofs.ProofLast.ChunkSpan,
+ postageProof: new Models.PostageProof(
+ index: response.Proofs.ProofLast.PostageProof.Index,
+ postageId: response.Proofs.ProofLast.PostageProof.PostageId,
+ signature: response.Proofs.ProofLast.PostageProof.Signature,
+ timeStamp: DateTimeOffset.FromUnixTimeSeconds(
+ long.Parse(response.Proofs.ProofLast.PostageProof.TimeStamp, CultureInfo.InvariantCulture))),
+ proofSegments: response.Proofs.ProofLast.ProofSegments ?? Array.Empty(),
+ proofSegments2: response.Proofs.ProofLast.ProofSegments2 ?? Array.Empty(),
+ proofSegments3: response.Proofs.ProofLast.ProofSegments3 ?? Array.Empty(),
+ proveSegment: response.Proofs.ProofLast.ProveSegment,
+ proveSegment2: response.Proofs.ProofLast.ProveSegment2,
+ socProof: (response.Proofs.ProofLast.SocProof ?? Array.Empty()).Select(
+ p => new Models.SocProof(
+ chunkHash: p.ChunkAddr,
+ identifier: p.Identifier,
+ signature: p.Signature,
+ signer: p.Signer))));
+ }
+
+ public async Task GetReserveStateAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.ReservestateAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ commitment: response.Commitment,
+ radius: response.Radius,
+ storageRadius: response.StorageRadius);
+ }
+
+ public async Task GetSettlementsWithPeerAsync(
+ string peerAddress,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.SettlementsGetAsync(peerAddress, cancellationToken).ConfigureAwait(false);
+ return new SettlementData(
+ peer: response.Peer,
+ received: BzzBalance.FromPlurString(response.Received),
+ sent: BzzBalance.FromPlurString(response.Sent));
+ }
+
+ public async Task GetStampsBucketsForBatchAsync(
+ PostageBatchId batchId,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.StampsBucketsAsync(
+ batchId.ToString(),
+ cancellationToken).ConfigureAwait(false);
+ return new(
+ depth: response.Depth,
+ bucketDepth: response.BucketDepth,
+ bucketUpperBound: response.BucketUpperBound,
+ collisions: response.Buckets.Select(b => b.Collisions));
+ }
+
+ public async Task GetSwarmTopologyAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TopologyAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ baseAddr: response.BaseAddr,
+ bins: response.Bins.ToDictionary(
+ i => i.Key,
+ i => new PeersAggregate(
+ population: i.Value.Population,
+ connected: i.Value.Connected,
+ disconnectedPeers: i.Value.DisconnectedPeers.Select(
+ peer => new Peer(
+ address: peer.Address,
+ lastSeenTimestamp: peer.Metrics.LastSeenTimestamp,
+ sessionConnectionRetry: peer.Metrics.SessionConnectionRetry,
+ connectionTotalDuration: peer.Metrics.ConnectionTotalDuration,
+ sessionConnectionDuration: peer.Metrics.SessionConnectionDuration,
+ sessionConnectionDirection: peer.Metrics.SessionConnectionDirection,
+ latencyEwma: peer.Metrics.LatencyEWMA)),
+ connectedPeers: i.Value.ConnectedPeers.Select(
+ peer => new Peer(
+ address: peer.Address,
+ lastSeenTimestamp: peer.Metrics.LastSeenTimestamp,
+ sessionConnectionRetry: peer.Metrics.SessionConnectionRetry,
+ connectionTotalDuration: peer.Metrics.ConnectionTotalDuration,
+ sessionConnectionDuration: peer.Metrics.SessionConnectionDuration,
+ sessionConnectionDirection: peer.Metrics.SessionConnectionDirection,
+ latencyEwma: peer.Metrics.LatencyEWMA)))),
+ connected: response.Connected,
+ depth: response.Depth,
+ networkAvailability: response.NetworkAvailability switch
+ {
+ Response38NetworkAvailability.Unknown => NetworkAvailability.Unknown,
+ Response38NetworkAvailability.Available => NetworkAvailability.Available,
+ Response38NetworkAvailability.Unavailable => NetworkAvailability.Unavailable,
+ _ => throw new InvalidOperationException(),
+ },
+ nnLowWatermark: response.NnLowWatermark,
+ population: response.Population,
+ reachability: response.Reachability switch
+ {
+ Response38Reachability.Unknown => Reachability.Unknown,
+ Response38Reachability.Public => Reachability.Public,
+ Response38Reachability.Private => Reachability.Private,
+ _ => throw new InvalidOperationException(),
+ },
+ timestamp: DateTimeOffset.FromUnixTimeSeconds(
+ long.Parse(response.Timestamp, CultureInfo.InvariantCulture)));
+ }
+
+ public async Task GetTagInfoAsync(
+ long uid,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TagsGetAsync(uid, cancellationToken).ConfigureAwait(false);
+ return new TagInfo(
+ uid: response.Uid,
+ startedAt: response.StartedAt,
+ split: response.Split,
+ seen: response.Seen,
+ stored: response.Stored,
+ sent: response.Sent,
+ synced: response.Synced);
+ }
+
+ public async Task> GetTagsListAsync(
+ int? offset = null,
+ int? limit = null,
+ CancellationToken cancellationToken = default)
+ {
+ var tags =
+ (await generatedClient.TagsGetAsync(offset, limit, cancellationToken).ConfigureAwait(false)).Tags ??
+ Array.Empty();
+ return tags.Select(t => new TagInfo(
+ uid: t.Uid,
+ startedAt: t.StartedAt,
+ split: t.Split,
+ seen: t.Seen,
+ stored: t.Stored,
+ sent: t.Sent,
+ synced: t.Synced));
+ }
+
+ public async Task GetTransactionInfoAsync(
+ string txHash,
+ CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.TransactionsGetAsync(txHash, cancellationToken).ConfigureAwait(false);
+ return new TxInfo(
+ transactionHash: response.TransactionHash,
+ to: response.To,
+ nonce: response.Nonce,
+ gasPrice: XDaiBalance.FromWeiString(response.GasPrice),
+ gasLimit: response.GasLimit,
+ data: response.Data,
+ created: response.Created,
+ description: response.Description,
+ value: XDaiBalance.FromWeiString(response.Value));
+ }
+
+ public async Task GetWalletBalance(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.WalletAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ bzzBalance: BzzBalance.FromPlurString(response.BzzBalance),
+ xDaiBalance: XDaiBalance.FromWeiString(response.NativeTokenBalance));
+ }
+
+ public async Task GetWelcomeMessageAsync(CancellationToken cancellationToken = default) =>
+ (await generatedClient.WelcomeMessageGetAsync(cancellationToken).ConfigureAwait(false)).WelcomeMessage;
+
+ public async Task IsContentRetrievableAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.StewardshipGetAsync((string)hash, cancellationToken).ConfigureAwait(false))
+ .IsRetrievable;
+
+ public async Task LoggersGetAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.LoggersGetAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ loggers: response.Loggers.Select(
+ i => new Loggers(
+ id: i.Id,
+ logger: i.Logger,
+ subsystem: i.Subsystem,
+ verbosity: i.Verbosity)).ToList(),
+ tree: response.Tree.ToDictionary(i => i.Key, i => i.Value?.Plus.ToList() ?? new List()));
+ }
+
+ public async Task LoggersGetAsync(string exp, CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.LoggersGetAsync(exp, cancellationToken).ConfigureAwait(false);
+ return new(
+ loggers: response.Loggers.Select(
+ i => new Loggers(
+ id: i.Id,
+ logger: i.Logger,
+ subsystem: i.Subsystem,
+ verbosity: i.Verbosity)).ToList(),
+ tree: response.Tree.ToDictionary(i => i.Key, i => i.Value?.Plus.ToList() ?? new List()));
+ }
+
+ public async Task LoggersPutAsync(string exp, CancellationToken cancellationToken = default) =>
+ await generatedClient.LoggersPutAsync(exp, cancellationToken).ConfigureAwait(false);
+
+ public async Task RebroadcastTransactionAsync(
+ string txHash,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.TransactionsPostAsync(txHash, cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ public async Task RedistributionStateAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.RedistributionstateAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ isFrozen: response.IsFrozen,
+ isFullySynced: response.IsFullySynced,
+ isHealthy: response.IsHealthy,
+ round: response.Round,
+ lastWonRound: response.LastWonRound,
+ lastPlayedRound: response.LastPlayedRound,
+ lastFrozenRound: response.LastFrozenRound,
+ block: response.Block,
+ reward: BzzBalance.FromPlurString(response.Reward),
+ fees: XDaiBalance.FromWeiString(response.Fees));
+ }
+
+ public async Task RefreshAuthAsync(
+ string role,
+ int expiry,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.RefreshAsync(
+ new Body2
+ {
+ Role = role,
+ Expiry = expiry
+ },
+ cancellationToken).ConfigureAwait(false)).Key;
+
+ public async Task ResolveAddressToChunkReferenceAsync(SwarmAddress address)
+ {
+ var chunkStore = new BeeClientChunkStore(this);
+
+ var rootManifest = new ReferencedMantarayManifest(
+ chunkStore,
+ address.Hash);
+
+ return await rootManifest.ResolveAddressToChunkReferenceAsync(address).ConfigureAwait(false);
+ }
+
+ public Task ReuploadContentAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.StewardshipPutAsync((string)hash, cancellationToken: cancellationToken);
+
+ public Task SendPssAsync(
+ string topic,
+ string targets,
+ PostageBatchId batchId,
+ string? recipient = null,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.PssSendAsync(topic, targets, batchId.ToString(), recipient, cancellationToken);
+
+ public Task SetWelcomeMessageAsync(
+ string welcomeMessage,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.WelcomeMessagePostAsync(
+ new Body4
+ {
+ WelcomeMessage = welcomeMessage
+ },
+ cancellationToken);
+
+ public async Task StakeDeleteAsync(
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ await generatedClient.StakeDeleteAsync(
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false);
+
+ public async Task StakeGetAsync(CancellationToken cancellationToken = default) =>
+ await generatedClient.StakeGetAsync(cancellationToken).ConfigureAwait(false);
+
+ public async Task StakePostAsync(
+ BzzBalance amount,
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ await generatedClient.StakePostAsync(
+ amount.ToPlurString(),
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false);
+
+ public async Task StatusNodeAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.StatusAsync(cancellationToken).ConfigureAwait(false);
+ return new(
+ beeMode: response.BeeMode switch
+ {
+ Response65BeeMode.Light => StatusBeeMode.Light,
+ Response65BeeMode.Full => StatusBeeMode.Full,
+ Response65BeeMode.UltraLight => StatusBeeMode.UltraLight,
+ Response65BeeMode.Unknown => StatusBeeMode.Unknown,
+ _ => throw new InvalidOperationException()
+ },
+ batchCommitment: response.BatchCommitment,
+ connectedPeers: response.ConnectedPeers,
+ neighborhoodSize: response.NeighborhoodSize,
+ peer: response.Peer,
+ proximity: response.Proximity,
+ pullsyncRate: response.PullsyncRate,
+ reserveSize: response.ReserveSize,
+ reserveSizeWithinRadius: (int)response.ReserveSizeWithinRadius,
+ requestFailed: response.RequestFailed,
+ storageRadius: response.StorageRadius);
+ }
+
+ public async Task> StatusPeersAsync(CancellationToken cancellationToken = default)
+ {
+ var response = await generatedClient.StatusPeersAsync(cancellationToken).ConfigureAwait(false);
+ return response.Stamps.Select(
+ s => new StatusNode(
+ beeMode: s.BeeMode switch
+ {
+ StampsBeeMode.Light => StatusBeeMode.Light,
+ StampsBeeMode.Full => StatusBeeMode.Full,
+ StampsBeeMode.UltraLight => StatusBeeMode.UltraLight,
+ StampsBeeMode.Unknown => StatusBeeMode.Unknown,
+ _ => throw new InvalidOperationException()
+ },
+ batchCommitment: s.BatchCommitment,
+ connectedPeers: s.ConnectedPeers,
+ neighborhoodSize: s.NeighborhoodSize,
+ peer: s.Peer,
+ proximity: s.Proximity,
+ pullsyncRate: s.PullsyncRate,
+ reserveSize: s.ReserveSize,
+ reserveSizeWithinRadius: (int)s.ReserveSizeWithinRadius,
+ requestFailed: s.RequestFailed,
+ storageRadius: s.StorageRadius));
+ }
+
+ public Task SubscribeToPssAsync(
+ string topic,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.PssSubscribeAsync(topic, cancellationToken);
+
+ public async Task TopUpPostageBatchAsync(
+ PostageBatchId batchId,
+ BzzBalance amount,
+ XDaiBalance? gasPrice = null,
+ long? gasLimit = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.StampsTopupAsync(
+ batchId.ToString(),
+ amount.ToPlurLong(),
+ gasPrice?.ToWeiLong(),
+ gasLimit,
+ cancellationToken).ConfigureAwait(false)).BatchID;
+
+ public async Task TryConnectToPeerAsync(
+ string peerId,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.PingpongAsync(peerId, cancellationToken).ConfigureAwait(false)).Rtt;
+
+ public Task UpdateTagAsync(
+ long uid,
+ SwarmHash? hash = null,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.TagsPatchAsync(
+ uid,
+ hash.HasValue ?
+ new Body3 { Address = hash.Value.ToString() } :
+ null,
+ cancellationToken);
+
+ public async Task UploadChunkAsync(PostageBatchId batchId,
+ Stream chunkData,
+ bool swarmPin = false,
+ bool swarmDeferredUpload = true,
+ long? swarmTag = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChunksPostAsync(
+ swarmTag,
+ batchId.ToString(),
+ chunkData,
+ cancellationToken).ConfigureAwait(false)).Reference;
+
+ public Task UploadChunksStreamAsync(
+ PostageBatchId batchId,
+ int? swarmTag = null,
+ bool? swarmPin = null,
+ CancellationToken cancellationToken = default) =>
+ generatedClient.ChunksStreamAsync(swarmTag, batchId.ToString(), cancellationToken);
+
+ public async Task UploadBytesAsync(
+ PostageBatchId batchId,
+ Stream body,
+ int? swarmTag = null,
+ bool? swarmPin = null,
+ bool? swarmEncrypt = null,
+ bool? swarmDeferredUpload = null,
+ RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.BytesPostAsync(
+ swarm_postage_batch_id: batchId.ToString(),
+ swarm_tag: swarmTag,
+ swarm_pin: swarmPin,
+ swarm_deferred_upload: swarmDeferredUpload,
+ swarm_encrypt: swarmEncrypt,
+ swarm_redundancy_level: (int)swarmRedundancyLevel,
+ body: body,
+ cancellationToken).ConfigureAwait(false)).Reference;
+
+#if NET7_0_OR_GREATER
+ public async Task UploadDirectoryAsync(
+ PostageBatchId batchId,
+ string directoryPath,
+ int? swarmTag = null,
+ bool? swarmPin = null,
+ bool? swarmEncrypt = null,
+ string? swarmIndexDocument = null,
+ string? swarmErrorDocument = null,
+ bool? swarmDeferredUpload = null,
+ RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
+ CancellationToken cancellationToken = default)
+ {
+ // Create tar file.
+ using var memoryStream = new MemoryStream();
+ await TarFile.CreateFromDirectoryAsync(directoryPath, memoryStream, false, cancellationToken).ConfigureAwait(false);
+ memoryStream.Position = 0;
+
+ // Try set index document.
+ if (swarmIndexDocument is null &&
+ File.Exists(Path.Combine(directoryPath, "index.html")))
+ swarmIndexDocument = "index.html";
+
+ // Upload directory.
+ return (await generatedClient.BzzPostAsync(
+ new FileParameter(memoryStream, null, "application/x-tar"),
+ swarm_tag: swarmTag,
+ swarm_pin: swarmPin,
+ swarm_encrypt: swarmEncrypt,
+ swarm_collection: true,
+ swarm_index_document: swarmIndexDocument,
+ swarm_error_document: swarmErrorDocument,
+ swarm_postage_batch_id: batchId.ToString(),
+ swarm_deferred_upload: swarmDeferredUpload,
+ swarm_redundancy_level: (SwarmRedundancyLevel)swarmRedundancyLevel,
+ cancellationToken: cancellationToken).ConfigureAwait(false)).Reference;
+ }
+#endif
+
+ public async Task UploadFileAsync(
+ PostageBatchId batchId,
+ Stream content,
+ string? name = null,
+ string? contentType = null,
+ bool isFileCollection = false,
+ int? swarmTag = null,
+ bool? swarmPin = null,
+ bool? swarmEncrypt = null,
+ string? swarmIndexDocument = null,
+ string? swarmErrorDocument = null,
+ bool? swarmDeferredUpload = null,
+ RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
+ CancellationToken cancellationToken = default)
+ {
+ return (await generatedClient.BzzPostAsync(
+ new FileParameter(content, name, contentType),
+ swarm_tag: swarmTag,
+ swarm_pin: swarmPin,
+ swarm_encrypt: swarmEncrypt,
+ swarm_collection: isFileCollection,
+ swarm_index_document: swarmIndexDocument,
+ swarm_error_document: swarmErrorDocument,
+ swarm_postage_batch_id: batchId.ToString(),
+ swarm_deferred_upload: swarmDeferredUpload,
+ swarm_redundancy_level: (SwarmRedundancyLevel)swarmRedundancyLevel,
+ cancellationToken: cancellationToken).ConfigureAwait(false)).Reference;
+ }
+
+ public async Task UploadSocAsync(
+ string owner,
+ string id,
+ string sig,
+ PostageBatchId batchId,
+ Stream body,
+ bool? swarmPin = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.SocAsync(
+ owner,
+ id,
+ sig,
+ batchId.ToString(),
+ body,
+ swarmPin,
+ cancellationToken).ConfigureAwait(false)).Reference;
+
+ public async Task WalletWithdrawAsync(
+ BzzBalance amount,
+ string address,
+ XDaiBalance coin,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.WalletWithdrawAsync(
+ amount.ToPlurString(),
+ address,
+ coin.ToWeiString(),
+ cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ public async Task WithdrawFromChequebookAsync(
+ BzzBalance amount,
+ XDaiBalance? gasPrice = null,
+ CancellationToken cancellationToken = default) =>
+ (await generatedClient.ChequebookWithdrawAsync(
+ amount.ToPlurLong(),
+ gasPrice?.ToWeiLong(),
+ cancellationToken).ConfigureAwait(false)).TransactionHash;
+
+ // Helpers.
+ private static Uri BuildBaseUrl(string url, int port)
+ {
+ var normalizedUrl = url;
+ if (normalizedUrl.Last() != '/')
+ normalizedUrl += '/';
+
+ var baseUrl = "";
+
+ var urlRegex = new Regex(@"^((?\w+)://)?(?[^/:]+)",
+ RegexOptions.None, TimeSpan.FromMilliseconds(150));
+ var urlMatch = urlRegex.Match(normalizedUrl);
+
+ if (!urlMatch.Success)
+ throw new ArgumentException("Url is not valid", nameof(url));
+
+ if (!string.IsNullOrEmpty(urlMatch.Groups["proto"].Value))
+ baseUrl += urlMatch.Groups["proto"].Value + "://";
+
+ baseUrl += $"{urlMatch.Groups["host"].Value}:{port}";
+
+ return new Uri(baseUrl);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Client/BeeNet.Client.csproj b/src/BeeNet.Client/BeeNet.Client.csproj
new file mode 100644
index 00000000..e1692bf9
--- /dev/null
+++ b/src/BeeNet.Client/BeeNet.Client.csproj
@@ -0,0 +1,51 @@
+
+
+
+ net6.0;net7.0;net8.0
+ true
+ Etherna.BeeNet
+
+ Etherna SA
+ A .Net client to connect with Ethereum Swarm Bee
+
+ 12
+ enable
+ true
+ true
+ AllEnabledByDefault
+
+ Bee.Net.Client
+ https://github.com/Etherna/bee-net
+ git
+ true
+ true
+ snupkg
+ COPYING
+ COPYING-LESSER
+ README.md
+ true
+ true
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BeeNet/Clients/BeeGeneratedClient.cs b/src/BeeNet.Client/Clients/BeeGeneratedClient.cs
similarity index 100%
rename from src/BeeNet/Clients/BeeGeneratedClient.cs
rename to src/BeeNet.Client/Clients/BeeGeneratedClient.cs
diff --git a/src/BeeNet/Clients/Fixer/PostageBatchDto.cs b/src/BeeNet.Client/Clients/Fixer/PostageBatchDto.cs
similarity index 100%
rename from src/BeeNet/Clients/Fixer/PostageBatchDto.cs
rename to src/BeeNet.Client/Clients/Fixer/PostageBatchDto.cs
diff --git a/src/BeeNet/BeeNet.csproj b/src/BeeNet.Core/BeeNet.Core.csproj
similarity index 77%
rename from src/BeeNet/BeeNet.csproj
rename to src/BeeNet.Core/BeeNet.Core.csproj
index 4976d563..00be88a7 100644
--- a/src/BeeNet/BeeNet.csproj
+++ b/src/BeeNet.Core/BeeNet.Core.csproj
@@ -4,16 +4,17 @@
net6.0;net7.0;net8.0
true
Etherna.BeeNet
-
- Etherna Sagl
- A .Net client for Swarm Bee
-
+
+ Etherna SA
+ Core models to work with Ethereum Swarm in .Net
+
12
enable
+ true
true
AllEnabledByDefault
- Bee.Net
+ Bee.Net.Core
https://github.com/Etherna/bee-net
git
true
@@ -31,15 +32,11 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
-
+
diff --git a/src/BeeNet/Exceptions/BeeNetApiException.cs b/src/BeeNet.Core/Exceptions/BeeNetApiException.cs
similarity index 92%
rename from src/BeeNet/Exceptions/BeeNetApiException.cs
rename to src/BeeNet.Core/Exceptions/BeeNetApiException.cs
index f5b5aa6c..92e5a303 100644
--- a/src/BeeNet/Exceptions/BeeNetApiException.cs
+++ b/src/BeeNet.Core/Exceptions/BeeNetApiException.cs
@@ -20,10 +20,10 @@
namespace Etherna.BeeNet.Exceptions
{
[SuppressMessage("Design", "CA1032:Implement standard exception constructors")]
- public partial class BeeNetApiException : Exception
+ public class BeeNetApiException : Exception
{
// Constructor.
- internal BeeNetApiException(
+ public BeeNetApiException(
string message,
int statusCode,
string? response,
@@ -55,10 +55,10 @@ public override string ToString()
}
[SuppressMessage("Design", "CA1032:Implement standard exception constructors")]
- public partial class BeeNetApiException : BeeNetApiException
+ public class BeeNetApiException : BeeNetApiException
{
// Constructor.
- internal BeeNetApiException(
+ public BeeNetApiException(
string message,
int statusCode,
string? response,
diff --git a/src/BeeNet/Extensions/ArrayExtensions.cs b/src/BeeNet.Core/Extensions/ArrayExtensions.cs
similarity index 100%
rename from src/BeeNet/Extensions/ArrayExtensions.cs
rename to src/BeeNet.Core/Extensions/ArrayExtensions.cs
diff --git a/src/BeeNet/Extensions/LongExtensions.cs b/src/BeeNet.Core/Extensions/LongExtensions.cs
similarity index 100%
rename from src/BeeNet/Extensions/LongExtensions.cs
rename to src/BeeNet.Core/Extensions/LongExtensions.cs
diff --git a/src/BeeNet/JsonConverters/BzzBalanceJsonConverter.cs b/src/BeeNet.Core/JsonConverters/BzzBalanceJsonConverter.cs
similarity index 100%
rename from src/BeeNet/JsonConverters/BzzBalanceJsonConverter.cs
rename to src/BeeNet.Core/JsonConverters/BzzBalanceJsonConverter.cs
diff --git a/src/BeeNet/JsonConverters/PostageBatchIdJsonConverter.cs b/src/BeeNet.Core/JsonConverters/PostageBatchIdJsonConverter.cs
similarity index 100%
rename from src/BeeNet/JsonConverters/PostageBatchIdJsonConverter.cs
rename to src/BeeNet.Core/JsonConverters/PostageBatchIdJsonConverter.cs
diff --git a/src/BeeNet/JsonConverters/XDaiBalanceJsonConverter.cs b/src/BeeNet.Core/JsonConverters/XDaiBalanceJsonConverter.cs
similarity index 100%
rename from src/BeeNet/JsonConverters/XDaiBalanceJsonConverter.cs
rename to src/BeeNet.Core/JsonConverters/XDaiBalanceJsonConverter.cs
diff --git a/src/BeeNet/Models/ChainState.cs b/src/BeeNet.Core/Models/Account.cs
similarity index 51%
rename from src/BeeNet/Models/ChainState.cs
rename to src/BeeNet.Core/Models/Account.cs
index cee96af4..68490db0 100644
--- a/src/BeeNet/Models/ChainState.cs
+++ b/src/BeeNet.Core/Models/Account.cs
@@ -12,28 +12,24 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
-using System.Globalization;
-
namespace Etherna.BeeNet.Models
{
- public sealed class ChainState
+ public sealed class Account(
+ BzzBalance balance,
+ BzzBalance thresholdReceived,
+ BzzBalance thresholdGiven,
+ BzzBalance surplusBalance,
+ BzzBalance reservedBalance,
+ BzzBalance shadowReservedBalance,
+ BzzBalance ghostBalance)
{
- // Constructors.
- internal ChainState(Clients.Response30 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Block = response.Block;
- ChainTip = response.ChainTip;
- CurrentPrice = BzzBalance.FromPlurString(response.CurrentPrice);
- TotalAmount = BzzBalance.FromPlurString(response.TotalAmount);
- }
-
// Properties.
- public long Block { get; }
- public int ChainTip { get; }
- public BzzBalance CurrentPrice { get; }
- public BzzBalance TotalAmount { get; }
+ public BzzBalance Balance { get; } = balance;
+ public BzzBalance ThresholdReceived { get; } = thresholdReceived;
+ public BzzBalance ThresholdGiven { get; } = thresholdGiven;
+ public BzzBalance SurplusBalance { get; } = surplusBalance;
+ public BzzBalance ReservedBalance { get; } = reservedBalance;
+ public BzzBalance ShadowReservedBalance { get; } = shadowReservedBalance;
+ public BzzBalance GhostBalance { get; } = ghostBalance;
}
}
diff --git a/src/BeeNet.Core/Models/AddressDetail.cs b/src/BeeNet.Core/Models/AddressDetail.cs
new file mode 100644
index 00000000..3c24964f
--- /dev/null
+++ b/src/BeeNet.Core/Models/AddressDetail.cs
@@ -0,0 +1,33 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class AddressDetail(
+ string overlay,
+ IEnumerable underlay,
+ string ethereum,
+ string publicKey,
+ string pssPublicKey)
+ {
+ // Properties.
+ public string Overlay { get; } = overlay;
+ public IEnumerable Underlay { get; } = underlay;
+ public string Ethereum { get; } = ethereum;
+ public string PublicKey { get; } = publicKey;
+ public string PssPublicKey { get; } = pssPublicKey;
+ }
+}
diff --git a/src/BeeNet/Models/BzzBalance.cs b/src/BeeNet.Core/Models/BzzBalance.cs
similarity index 100%
rename from src/BeeNet/Models/BzzBalance.cs
rename to src/BeeNet.Core/Models/BzzBalance.cs
diff --git a/src/BeeNet.Core/Models/ChainState.cs b/src/BeeNet.Core/Models/ChainState.cs
new file mode 100644
index 00000000..b8a45372
--- /dev/null
+++ b/src/BeeNet.Core/Models/ChainState.cs
@@ -0,0 +1,29 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ChainState(
+ long block,
+ int chainTip,
+ BzzBalance currentPrice,
+ BzzBalance totalAmount)
+ {
+ // Properties.
+ public long Block { get; } = block;
+ public int ChainTip { get; } = chainTip;
+ public BzzBalance CurrentPrice { get; } = currentPrice;
+ public BzzBalance TotalAmount { get; } = totalAmount;
+ }
+}
diff --git a/src/BeeNet.Core/Models/CheckPinsResult.cs b/src/BeeNet.Core/Models/CheckPinsResult.cs
new file mode 100644
index 00000000..4af7a112
--- /dev/null
+++ b/src/BeeNet.Core/Models/CheckPinsResult.cs
@@ -0,0 +1,28 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class CheckPinsResult(
+ SwarmHash hash,
+ int invalid,
+ int missing,
+ int total)
+ {
+ public SwarmHash Hash { get; } = hash;
+ public int Invalid { get; } = invalid;
+ public int Missing { get; } = missing;
+ public int Total { get; } = total;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Core/Models/ChequePayment.cs b/src/BeeNet.Core/Models/ChequePayment.cs
new file mode 100644
index 00000000..6dd15f09
--- /dev/null
+++ b/src/BeeNet.Core/Models/ChequePayment.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ChequePayment(
+ string beneficiary,
+ string chequebook,
+ BzzBalance payout)
+ {
+ // Properties.
+ public string Beneficiary { get; } = beneficiary;
+ public string Chequebook { get; } = chequebook;
+ public BzzBalance Payout { get; } = payout;
+ }
+}
diff --git a/src/BeeNet/Models/Auth.cs b/src/BeeNet.Core/Models/ChequebookBalance.cs
similarity index 73%
rename from src/BeeNet/Models/Auth.cs
rename to src/BeeNet.Core/Models/ChequebookBalance.cs
index 7f0800e7..2ceb6e00 100644
--- a/src/BeeNet/Models/Auth.cs
+++ b/src/BeeNet.Core/Models/ChequebookBalance.cs
@@ -12,21 +12,14 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
-
namespace Etherna.BeeNet.Models
{
- public sealed class Auth
+ public sealed class ChequebookBalance(
+ BzzBalance availableBalance,
+ BzzBalance totalBalance)
{
- // Constructors.
- internal Auth(Clients.Response response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Key = response.Key;
- }
-
// Properties.
- public string Key { get; }
+ public BzzBalance AvailableBalance { get; } = availableBalance;
+ public BzzBalance TotalBalance { get; } = totalBalance;
}
}
diff --git a/src/BeeNet/Models/Wallet.cs b/src/BeeNet.Core/Models/ChequebookCashout.cs
similarity index 60%
rename from src/BeeNet/Models/Wallet.cs
rename to src/BeeNet.Core/Models/ChequebookCashout.cs
index edf2e05c..41dca128 100644
--- a/src/BeeNet/Models/Wallet.cs
+++ b/src/BeeNet.Core/Models/ChequebookCashout.cs
@@ -12,23 +12,20 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
-
namespace Etherna.BeeNet.Models
{
- public sealed class Wallet
+ public sealed class ChequebookCashout(
+ string peer,
+ ChequePayment? lastCashedCheque,
+ string transactionHash,
+ ResultChequebook result,
+ BzzBalance uncashedAmount)
{
- // Constructors.
- internal Wallet(Clients.Response61 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Bzz = BzzBalance.FromPlurString(response.BzzBalance);
- NativeTokenBalance = XDaiBalance.FromWeiString(response.NativeTokenBalance);
- }
-
// Properties.
- public BzzBalance Bzz { get; }
- public XDaiBalance NativeTokenBalance { get; }
+ public string Peer { get; } = peer;
+ public ChequePayment? LastCashedCheque { get; } = lastCashedCheque;
+ public string TransactionHash { get; } = transactionHash;
+ public ResultChequebook Result { get; } = result;
+ public BzzBalance UncashedAmount { get; } = uncashedAmount;
}
}
diff --git a/src/BeeNet.Core/Models/ChequebookCheque.cs b/src/BeeNet.Core/Models/ChequebookCheque.cs
new file mode 100644
index 00000000..edcd472b
--- /dev/null
+++ b/src/BeeNet.Core/Models/ChequebookCheque.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ChequebookCheque(
+ string peer,
+ ChequePayment? lastReceived,
+ ChequePayment? lastSent)
+ {
+ // Properties.
+ public string Peer { get; } = peer;
+ public ChequePayment? LastReceived { get; } = lastReceived;
+ public ChequePayment? LastSent { get; } = lastSent;
+ }
+}
diff --git a/src/BeeNet/Feeds/EpochFeedIndex.cs b/src/BeeNet.Core/Models/Feeds/EpochFeedIndex.cs
similarity index 90%
rename from src/BeeNet/Feeds/EpochFeedIndex.cs
rename to src/BeeNet.Core/Models/Feeds/EpochFeedIndex.cs
index 8ca01a62..6d4632c9 100644
--- a/src/BeeNet/Feeds/EpochFeedIndex.cs
+++ b/src/BeeNet.Core/Models/Feeds/EpochFeedIndex.cs
@@ -12,12 +12,11 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Epoche;
using Etherna.BeeNet.Extensions;
+using Nethereum.Util.HashProviders;
using System;
-using System.Collections.ObjectModel;
-namespace Etherna.BeeNet.Feeds
+namespace Etherna.BeeNet.Models.Feeds
{
public sealed class EpochFeedIndex : FeedIndexBase
{
@@ -81,22 +80,6 @@ public EpochFeedIndex Parent
///
public byte Level { get; }
- ///
- /// Index represenentation as keccak256 hash
- ///
- public override ReadOnlyCollection MarshalBinary
- {
- get
- {
- var epochBytes = Start.UnixDateTimeToByteArray();
- var newArray = new byte[epochBytes.Length + 1];
- epochBytes.CopyTo(newArray, 0);
- newArray[epochBytes.Length] = Level;
-
- return new ReadOnlyCollection(Keccak256.ComputeHash(newArray));
- }
- }
-
///
/// Epoch start in seconds
///
@@ -138,6 +121,19 @@ public EpochFeedIndex GetChildAt(ulong at)
public override int GetHashCode() =>
Level.GetHashCode() ^ Start.GetHashCode();
+ ///
+ /// Index representation as keccak256 hash
+ ///
+ public override Memory GetMarshalBinaryHash(IHashProvider hashProvider)
+ {
+ var epochBytes = Start.UnixDateTimeToByteArray();
+ var newArray = new byte[epochBytes.Length + 1];
+ epochBytes.CopyTo(newArray, 0);
+ newArray[epochBytes.Length] = Level;
+
+ return hashProvider.ComputeHash(newArray);
+ }
+
public override FeedIndexBase GetNext(ulong at)
{
#if NET8_0_OR_GREATER
diff --git a/src/BeeNet/Feeds/FeedIndexBase.cs b/src/BeeNet.Core/Models/Feeds/FeedIndexBase.cs
similarity index 86%
rename from src/BeeNet/Feeds/FeedIndexBase.cs
rename to src/BeeNet.Core/Models/Feeds/FeedIndexBase.cs
index 95d9d18f..4e213714 100644
--- a/src/BeeNet/Feeds/FeedIndexBase.cs
+++ b/src/BeeNet.Core/Models/Feeds/FeedIndexBase.cs
@@ -12,15 +12,15 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
+using Nethereum.Util.HashProviders;
using System;
-using System.Collections.ObjectModel;
-namespace Etherna.BeeNet.Feeds
+namespace Etherna.BeeNet.Models.Feeds
{
public abstract class FeedIndexBase
{
// Properties.
- public abstract ReadOnlyCollection MarshalBinary { get; }
+ public abstract Memory GetMarshalBinaryHash(IHashProvider hashProvider);
// Methods.
public FeedIndexBase GetNext(DateTimeOffset at) =>
diff --git a/src/BeeNet/Models/FileResponse.cs b/src/BeeNet.Core/Models/FileResponse.cs
similarity index 69%
rename from src/BeeNet/Models/FileResponse.cs
rename to src/BeeNet.Core/Models/FileResponse.cs
index a8977985..0e13deba 100644
--- a/src/BeeNet/Models/FileResponse.cs
+++ b/src/BeeNet.Core/Models/FileResponse.cs
@@ -13,29 +13,24 @@
// If not, see .
using System;
+using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
namespace Etherna.BeeNet.Models
{
- public sealed class FileResponse : IDisposable, IAsyncDisposable
+ public sealed class FileResponse(
+ IReadOnlyDictionary> headers,
+ Stream stream)
+ : IDisposable, IAsyncDisposable
{
- // Constructors.
- internal FileResponse(Clients.FileResponse response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Stream = response.Stream;
- IsFeed = response.Headers.ContainsKey("Swarm-Feed-Index");
- }
-
// Dispose.
public void Dispose() => Stream.Dispose();
public ValueTask DisposeAsync() => Stream.DisposeAsync();
// Properties.
- public bool IsFeed { get; }
- public Stream Stream { get; }
-
+ public bool IsFeed => Headers.ContainsKey("Swarm-Feed-Index");
+ public IReadOnlyDictionary> Headers { get; } = headers;
+ public Stream Stream { get; } = stream;
}
}
diff --git a/src/BeeNet/Models/GnosisChain.cs b/src/BeeNet.Core/Models/GnosisChain.cs
similarity index 100%
rename from src/BeeNet/Models/GnosisChain.cs
rename to src/BeeNet.Core/Models/GnosisChain.cs
diff --git a/src/BeeNet/Models/Bucket.cs b/src/BeeNet.Core/Models/Health.cs
similarity index 68%
rename from src/BeeNet/Models/Bucket.cs
rename to src/BeeNet.Core/Models/Health.cs
index dbd817e9..d26e532b 100644
--- a/src/BeeNet/Models/Bucket.cs
+++ b/src/BeeNet.Core/Models/Health.cs
@@ -16,19 +16,16 @@
namespace Etherna.BeeNet.Models
{
- public sealed class Bucket
+ public sealed class Health(
+ bool isStatusOk,
+ string version,
+ string apiVersion,
+ string debugApiVersion)
{
- // Constructors.
- internal Bucket(Clients.Buckets bucket)
- {
- ArgumentNullException.ThrowIfNull(bucket, nameof(bucket));
-
- BucketId = bucket.BucketID;
- Collisions = bucket.Collisions;
- }
-
// Properties.
- public int BucketId { get; }
- public int Collisions { get; }
+ public bool IsStatusOk { get; } = isStatusOk;
+ public string Version { get; } = version;
+ public string ApiVersion { get; } = apiVersion;
+ public string DebugApiVersion { get; } = debugApiVersion;
}
}
diff --git a/src/BeeNet.Core/Models/IReadOnlyPostageBuckets.cs b/src/BeeNet.Core/Models/IReadOnlyPostageBuckets.cs
new file mode 100644
index 00000000..054f6670
--- /dev/null
+++ b/src/BeeNet.Core/Models/IReadOnlyPostageBuckets.cs
@@ -0,0 +1,59 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public interface IReadOnlyPostageBuckets
+ {
+ // Properties.
+ ///
+ /// The higher level of collisions for a bucket
+ ///
+ uint MaxBucketCollisions { get; }
+
+ ///
+ /// The lower level of collisions for a bucket
+ ///
+ uint MinBucketCollisions { get; }
+
+ ///
+ /// Minimum required postage batch depth
+ ///
+ int RequiredPostageBatchDepth { get; }
+
+ ///
+ /// Total added chunks in buckets
+ ///
+ long TotalChunks { get; }
+
+ // Methods.
+ ///
+ /// Amount of buckets, grouped by collisions
+ ///
+ /// Array with collisions as index, and buckets amount as values
+ int[] CountBucketsByCollisions();
+
+ ///
+ /// Get a copy of all buckets
+ ///
+ /// All the buckets
+ uint[] GetBuckets();
+
+ IEnumerable GetBucketsByCollisions(uint collisions);
+
+ uint GetCollisions(uint bucketId);
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Core/Models/InfoBeeMode.cs b/src/BeeNet.Core/Models/InfoBeeMode.cs
new file mode 100644
index 00000000..dae66e1a
--- /dev/null
+++ b/src/BeeNet.Core/Models/InfoBeeMode.cs
@@ -0,0 +1,34 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public enum InfoBeeMode
+ {
+ ///
+ /// Light node; does not participate in forwarding or storing chunks
+ ///
+ Light,
+
+ ///
+ /// Full node
+ ///
+ Full,
+
+ ///
+ /// Development mode; Bee client for development purposes, blockchain operations are mocked
+ ///
+ Dev,
+ }
+}
diff --git a/src/BeeNet/Models/StewardshipGet.cs b/src/BeeNet.Core/Models/LogData.cs
similarity index 70%
rename from src/BeeNet/Models/StewardshipGet.cs
rename to src/BeeNet.Core/Models/LogData.cs
index 6536a297..6a657061 100644
--- a/src/BeeNet/Models/StewardshipGet.cs
+++ b/src/BeeNet.Core/Models/LogData.cs
@@ -12,21 +12,16 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
+using System.Collections.Generic;
namespace Etherna.BeeNet.Models
{
- public sealed class StewardshipGet
+ public sealed class LogData(
+ ICollection loggers,
+ IDictionary> tree)
{
- // Constructors.
- internal StewardshipGet(Clients.Response19 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- IsRetrievable = response.IsRetrievable;
- }
-
// Properties.
- public bool IsRetrievable { get; }
+ public ICollection Loggers { get; } = loggers;
+ public IDictionary> Tree { get; } = tree;
}
}
diff --git a/src/BeeNet.Core/Models/Loggers.cs b/src/BeeNet.Core/Models/Loggers.cs
new file mode 100644
index 00000000..deac777e
--- /dev/null
+++ b/src/BeeNet.Core/Models/Loggers.cs
@@ -0,0 +1,29 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class Loggers(
+ string id,
+ string logger,
+ string subsystem,
+ string verbosity)
+ {
+ // Properties.
+ public string Id { get; } = id;
+ public string Logger { get; } = logger;
+ public string Subsystem { get; } = subsystem;
+ public string Verbosity { get; } = verbosity;
+ }
+}
diff --git a/src/BeeNet/Models/NetworkAvailability.cs b/src/BeeNet.Core/Models/NetworkAvailability.cs
similarity index 100%
rename from src/BeeNet/Models/NetworkAvailability.cs
rename to src/BeeNet.Core/Models/NetworkAvailability.cs
diff --git a/src/BeeNet.Core/Models/NodeInfo.cs b/src/BeeNet.Core/Models/NodeInfo.cs
new file mode 100644
index 00000000..9d46c39e
--- /dev/null
+++ b/src/BeeNet.Core/Models/NodeInfo.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class NodeInfo(
+ InfoBeeMode beeMode,
+ bool chequebookEnabled,
+ bool swapEnabled)
+ {
+ // Properties.
+ public InfoBeeMode BeeMode { get; } = beeMode;
+ public bool ChequebookEnabled { get; } = chequebookEnabled;
+ public bool SwapEnabled { get; } = swapEnabled;
+ }
+}
diff --git a/src/BeeNet/Models/AddressDetail.cs b/src/BeeNet.Core/Models/Peer.cs
similarity index 50%
rename from src/BeeNet/Models/AddressDetail.cs
rename to src/BeeNet.Core/Models/Peer.cs
index b8e9963f..c8935300 100644
--- a/src/BeeNet/Models/AddressDetail.cs
+++ b/src/BeeNet.Core/Models/Peer.cs
@@ -12,31 +12,25 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
namespace Etherna.BeeNet.Models
{
- public sealed class AddressDetail
+ public sealed class Peer(
+ string address,
+ int lastSeenTimestamp,
+ int sessionConnectionRetry,
+ double connectionTotalDuration,
+ double sessionConnectionDuration,
+ string sessionConnectionDirection,
+ int latencyEwma)
{
- // Constructors.
- internal AddressDetail(Clients.Response20 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Underlay = response.Underlay.Where(i => !string.IsNullOrWhiteSpace(i));
- Overlay = response.Overlay;
- Ethereum = response.Ethereum;
- PublicKey = response.PublicKey;
- PssPublicKey = response.PssPublicKey;
- }
-
// Properties.
- public string Overlay { get; }
- public IEnumerable Underlay { get; }
- public string Ethereum { get; }
- public string PublicKey { get; }
- public string PssPublicKey { get; }
+ public string Address { get; } = address;
+ public int LastSeenTimestamp { get; } = lastSeenTimestamp;
+ public int SessionConnectionRetry { get; } = sessionConnectionRetry;
+ public double ConnectionTotalDuration { get; } = connectionTotalDuration;
+ public double SessionConnectionDuration { get; } = sessionConnectionDuration;
+ public string SessionConnectionDirection { get; } = sessionConnectionDirection;
+ public int LatencyEwma { get; } = latencyEwma;
}
+
}
diff --git a/src/BeeNet.Core/Models/PeersAggregate.cs b/src/BeeNet.Core/Models/PeersAggregate.cs
new file mode 100644
index 00000000..3b95dccd
--- /dev/null
+++ b/src/BeeNet.Core/Models/PeersAggregate.cs
@@ -0,0 +1,31 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class PeersAggregate(
+ int population,
+ int connected,
+ IEnumerable disconnectedPeers,
+ IEnumerable connectedPeers)
+ {
+ // Properties.
+ public int Population { get; } = population;
+ public int Connected { get; } = connected;
+ public IEnumerable DisconnectedPeers { get; } = disconnectedPeers;
+ public IEnumerable ConnectedPeers { get; } = connectedPeers;
+ }
+}
diff --git a/src/BeeNet/Models/PostageBatch.cs b/src/BeeNet.Core/Models/PostageBatch.cs
similarity index 70%
rename from src/BeeNet/Models/PostageBatch.cs
rename to src/BeeNet.Core/Models/PostageBatch.cs
index 85da91c8..4de63942 100644
--- a/src/BeeNet/Models/PostageBatch.cs
+++ b/src/BeeNet.Core/Models/PostageBatch.cs
@@ -12,7 +12,6 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Clients;
using System;
namespace Etherna.BeeNet.Models
@@ -34,8 +33,9 @@ public PostageBatch(
bool isImmutable,
bool isUsable,
string? label,
+ int? storageRadius,
TimeSpan ttl,
- uint utilization)
+ uint? utilization)
{
if (depth is < MinDepth or > MaxDepth)
throw new ArgumentOutOfRangeException(nameof(depth), "Batch depth out of range");
@@ -48,47 +48,11 @@ public PostageBatch(
IsImmutable = isImmutable;
IsUsable = isUsable;
Label = label;
+ StorageRadius = storageRadius;
Ttl = ttl;
Utilization = utilization;
}
- // Internal constructors.
- internal PostageBatch(Stamps batch)
- {
- ArgumentNullException.ThrowIfNull(batch, nameof(batch));
- if (batch.Depth is < MinDepth or > MaxDepth)
- throw new ArgumentOutOfRangeException(nameof(batch), "Batch depth out of range");
-
- Amount = BzzBalance.FromPlurString(batch.Amount);
- Depth = batch.Depth;
- BlockNumber = batch.BlockNumber;
- Exists = batch.Exists;
- Id = batch.BatchID;
- IsImmutable = batch.ImmutableFlag;
- Label = batch.Label;
- Ttl = TimeSpan.FromSeconds(batch.BatchTTL);
- IsUsable = batch.Usable;
- Utilization = batch.Utilization;
- }
-
- internal PostageBatch(Response52 batch)
- {
- ArgumentNullException.ThrowIfNull(batch, nameof(batch));
- if (batch.Depth is < MinDepth or > MaxDepth)
- throw new ArgumentOutOfRangeException(nameof(batch), "Batch depth out of range");
-
- Amount = BzzBalance.FromPlurString(batch.Amount);
- Depth = batch.Depth;
- BlockNumber = batch.BlockNumber;
- Exists = batch.Exists;
- Id = batch.BatchID;
- IsImmutable = batch.ImmutableFlag;
- Label = batch.Label;
- Ttl = TimeSpan.FromSeconds(batch.BatchTTL);
- IsUsable = batch.Usable;
- Utilization = batch.Utilization;
- }
-
// Static properties.
public static PostageBatch MaxDepthInstance { get; } = new(
PostageBatchId.Zero,
@@ -99,6 +63,7 @@ internal PostageBatch(Response52 batch)
false,
true,
null,
+ null,
TimeSpan.FromDays(3650),
0);
@@ -136,7 +101,9 @@ internal PostageBatch(Response52 batch)
/// Label to identify the batch
///
public string? Label { get; }
-
+
+ public int? StorageRadius { get; }
+
///
/// Time to live before expiration
///
@@ -145,7 +112,7 @@ internal PostageBatch(Response52 batch)
///
/// The count of the fullest bucket
///
- public uint Utilization { get; }
+ public uint? Utilization { get; }
// Static methods.
public static BzzBalance CalculateAmount(BzzBalance chainPrice, TimeSpan ttl) =>
diff --git a/src/BeeNet/Models/PostageBatchId.cs b/src/BeeNet.Core/Models/PostageBatchId.cs
similarity index 100%
rename from src/BeeNet/Models/PostageBatchId.cs
rename to src/BeeNet.Core/Models/PostageBatchId.cs
diff --git a/src/BeeNet.Core/Models/PostageBuckets.cs b/src/BeeNet.Core/Models/PostageBuckets.cs
new file mode 100644
index 00000000..19b29dab
--- /dev/null
+++ b/src/BeeNet.Core/Models/PostageBuckets.cs
@@ -0,0 +1,216 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Threading;
+
+namespace Etherna.BeeNet.Models
+{
+ ///
+ /// A thread safe implementation of postage buckets array
+ ///
+ [SuppressMessage("Reliability", "CA2002:Do not lock on objects with weak identity")]
+ public class PostageBuckets : IReadOnlyPostageBuckets, IDisposable
+ {
+ // Consts.
+ public const int BucketsSize = 1 << PostageBatch.BucketDepth;
+
+ // Fields.
+ private readonly uint[] _buckets;
+ private readonly Dictionary> bucketsByCollisions; //
+ private readonly ReaderWriterLockSlim bucketsLock = new(LockRecursionPolicy.NoRecursion);
+ private bool disposed;
+
+ // Constructor.
+ public PostageBuckets(
+ uint[]? initialBuckets = null)
+ {
+ if (initialBuckets is not null &&
+ initialBuckets.Length != BucketsSize)
+ throw new ArgumentOutOfRangeException(nameof(initialBuckets),
+ $"Initial buckets must have length {BucketsSize}, or be null");
+
+ //init "buckets" and reverse index "bucketsByCollisions"
+ _buckets = initialBuckets ?? new uint[BucketsSize];
+ bucketsByCollisions = new Dictionary> { [0] = [] };
+ for (uint i = 0; i < BucketsSize; i++)
+ bucketsByCollisions[0].Add(i);
+
+ //init counters
+ MaxBucketCollisions = 0;
+ MinBucketCollisions = 0;
+ TotalChunks = 0;
+ }
+
+ // Dispose.
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposed) return;
+
+ // Dispose managed resources.
+ if (disposing)
+ bucketsLock.Dispose();
+
+ disposed = true;
+ }
+
+ // Properties.
+ public uint MaxBucketCollisions { get; private set; }
+ public uint MinBucketCollisions { get; private set; }
+ public int RequiredPostageBatchDepth => CollisionsToRequiredPostageBatchDepth(MaxBucketCollisions);
+ public long TotalChunks { get; private set; }
+
+ // Methods.
+ public int[] CountBucketsByCollisions()
+ {
+ bucketsLock.EnterReadLock();
+ try
+ {
+ return bucketsByCollisions.Select(pair => pair.Value.Count).ToArray();
+ }
+ finally
+ {
+ bucketsLock.ExitReadLock();
+ }
+ }
+
+ public uint[] GetBuckets()
+ {
+ bucketsLock.EnterReadLock();
+ try
+ {
+ return _buckets.ToArray();
+ }
+ finally
+ {
+ bucketsLock.ExitReadLock();
+ }
+ }
+
+ public IEnumerable GetBucketsByCollisions(uint collisions)
+ {
+ bucketsLock.EnterReadLock();
+ try
+ {
+ return bucketsByCollisions.TryGetValue(collisions, out var bucketsSet)
+ ? bucketsSet
+ : Array.Empty();
+ }
+ finally
+ {
+ bucketsLock.ExitReadLock();
+ }
+ }
+
+ public uint GetCollisions(uint bucketId)
+ {
+ bucketsLock.EnterReadLock();
+ try
+ {
+ return _buckets[bucketId];
+ }
+ finally
+ {
+ bucketsLock.ExitReadLock();
+ }
+ }
+
+ public void IncrementCollisions(uint bucketId)
+ {
+ /*
+ * We have to lock on _buckets because we need atomic operations also with bucketsByCollisions
+ * and counters. ConcurrentDictionary would have better locking on single values, but doesn't
+ * support atomic operations involving third objects, like counters and "bucketsByCollisions".
+ */
+ bucketsLock.EnterWriteLock();
+ try
+ {
+ // Update collections.
+ _buckets[bucketId]++;
+
+ bucketsByCollisions.TryAdd(_buckets[bucketId], []);
+ bucketsByCollisions[_buckets[bucketId] - 1].Remove(bucketId);
+ bucketsByCollisions[_buckets[bucketId]].Add(bucketId);
+
+ // Update counters.
+ if (_buckets[bucketId] > MaxBucketCollisions)
+ MaxBucketCollisions = _buckets[bucketId];
+
+ MinBucketCollisions = bucketsByCollisions.OrderBy(p => p.Key)
+ .First(p => p.Value.Count > 0)
+ .Key;
+
+ TotalChunks++;
+ }
+ finally
+ {
+ bucketsLock.ExitWriteLock();
+ }
+ }
+
+ public void ResetBucketCollisions(uint bucketId)
+ {
+ bucketsLock.EnterWriteLock();
+ try
+ {
+ // Update collections.
+ var oldCollisions = _buckets[bucketId];
+ _buckets[bucketId] = 0;
+
+ bucketsByCollisions[oldCollisions].Remove(bucketId);
+ bucketsByCollisions[0].Add(bucketId);
+
+ // Update counters.
+ MaxBucketCollisions = bucketsByCollisions.OrderByDescending(p => p.Key)
+ .First(p => p.Value.Count > 0)
+ .Key;
+
+ MinBucketCollisions = 0;
+ }
+ finally
+ {
+ bucketsLock.ExitWriteLock();
+ }
+ }
+
+ // Static methods.
+ public static int CollisionsToRequiredPostageBatchDepth(uint collisions)
+ {
+ if (collisions == 0)
+ return PostageBatch.MinDepth;
+ return Math.Max(
+ (int)Math.Ceiling(Math.Log2(collisions)) + PostageBatch.BucketDepth,
+ PostageBatch.MinDepth);
+ }
+
+ public static uint PostageBatchDepthToMaxCollisions(int postageBatchDepth)
+ {
+#pragma warning disable CA1512 //only supported from .net 8
+ if (postageBatchDepth < PostageBatch.MinDepth)
+ throw new ArgumentOutOfRangeException(nameof(postageBatchDepth));
+#pragma warning restore CA1512
+
+ return (uint)Math.Pow(2, postageBatchDepth - PostageBatch.BucketDepth);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Core/Models/PostageProof.cs b/src/BeeNet.Core/Models/PostageProof.cs
new file mode 100644
index 00000000..a1ca83cd
--- /dev/null
+++ b/src/BeeNet.Core/Models/PostageProof.cs
@@ -0,0 +1,31 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class PostageProof(
+ string index,
+ PostageBatchId postageId,
+ string signature,
+ DateTimeOffset timeStamp)
+ {
+ // Properties.
+ public string Index { get; } = index;
+ public PostageBatchId PostageId { get; } = postageId;
+ public string Signature { get; } = signature;
+ public DateTimeOffset TimeStamp { get; } = timeStamp;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Postage/PostageStamp.cs b/src/BeeNet.Core/Models/PostageStamp.cs
similarity index 96%
rename from src/BeeNet/Hasher/Postage/PostageStamp.cs
rename to src/BeeNet.Core/Models/PostageStamp.cs
index e43d5832..a5185929 100644
--- a/src/BeeNet/Hasher/Postage/PostageStamp.cs
+++ b/src/BeeNet.Core/Models/PostageStamp.cs
@@ -12,10 +12,9 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Models;
using System;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Models
{
public class PostageStamp
{
diff --git a/src/BeeNet/Models/Reachability.cs b/src/BeeNet.Core/Models/Reachability.cs
similarity index 100%
rename from src/BeeNet/Models/Reachability.cs
rename to src/BeeNet.Core/Models/Reachability.cs
diff --git a/src/BeeNet.Core/Models/RedistributionState.cs b/src/BeeNet.Core/Models/RedistributionState.cs
new file mode 100644
index 00000000..eb072e73
--- /dev/null
+++ b/src/BeeNet.Core/Models/RedistributionState.cs
@@ -0,0 +1,43 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class RedistributionState(
+ bool isFrozen,
+ bool isFullySynced,
+ bool isHealthy,
+ int round,
+ int lastWonRound,
+ int lastPlayedRound,
+ int lastFrozenRound,
+ int block,
+ BzzBalance reward,
+ XDaiBalance fees)
+ {
+ // Properties.
+ public bool IsFrozen { get; } = isFrozen;
+ public bool IsFullySynced { get; } = isFullySynced;
+ public bool IsHealthy { get; } = isHealthy;
+ public int Round { get; } = round;
+ public int LastWonRound { get; } = lastWonRound;
+ public int LastPlayedRound { get; } = lastPlayedRound;
+ public int LastFrozenRound { get; } = lastFrozenRound;
+ public int Block { get; } = block;
+ public BzzBalance Reward { get; } = reward;
+ public XDaiBalance Fees { get; } = fees;
+ }
+}
diff --git a/src/BeeNet/Models/RedundancyLevel.cs b/src/BeeNet.Core/Models/RedundancyLevel.cs
similarity index 100%
rename from src/BeeNet/Models/RedundancyLevel.cs
rename to src/BeeNet.Core/Models/RedundancyLevel.cs
diff --git a/src/BeeNet/Models/RedundancyStrategy.cs b/src/BeeNet.Core/Models/RedundancyStrategy.cs
similarity index 100%
rename from src/BeeNet/Models/RedundancyStrategy.cs
rename to src/BeeNet.Core/Models/RedundancyStrategy.cs
diff --git a/src/BeeNet/Models/CheckPinsResult.cs b/src/BeeNet.Core/Models/ReserveCommitment.cs
similarity index 58%
rename from src/BeeNet/Models/CheckPinsResult.cs
rename to src/BeeNet.Core/Models/ReserveCommitment.cs
index bca7b88d..da5f2605 100644
--- a/src/BeeNet/Models/CheckPinsResult.cs
+++ b/src/BeeNet.Core/Models/ReserveCommitment.cs
@@ -12,26 +12,20 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Clients;
-using System;
-
namespace Etherna.BeeNet.Models
{
- public sealed class CheckPinsResult
+ public sealed class ReserveCommitment(
+ int duration,
+ SwarmHash hash,
+ ReserveCommitmentProof proof1,
+ ReserveCommitmentProof proof2,
+ ReserveCommitmentProof proofLast)
{
- internal CheckPinsResult(Response15 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Hash = response.Reference;
- Invalid = response.Invalid;
- Missing = response.Missing;
- Total = response.Total;
- }
-
- public SwarmHash Hash { get; }
- public int Invalid { get; }
- public int Missing { get; }
- public int Total { get; }
+ // Properties.
+ public int Duration { get; } = duration;
+ public SwarmHash Hash { get; } = hash;
+ public ReserveCommitmentProof Proof1 { get; } = proof1;
+ public ReserveCommitmentProof Proof2 { get; } = proof2;
+ public ReserveCommitmentProof ProofLast { get; } = proofLast;
}
}
\ No newline at end of file
diff --git a/src/BeeNet.Core/Models/ReserveCommitmentProof.cs b/src/BeeNet.Core/Models/ReserveCommitmentProof.cs
new file mode 100644
index 00000000..8b6b6100
--- /dev/null
+++ b/src/BeeNet.Core/Models/ReserveCommitmentProof.cs
@@ -0,0 +1,39 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ReserveCommitmentProof(
+ int chunkSpan,
+ PostageProof postageProof,
+ IEnumerable proofSegments,
+ IEnumerable proofSegments2,
+ IEnumerable proofSegments3,
+ string proveSegment,
+ string proveSegment2,
+ IEnumerable socProof)
+ {
+ // Properties.
+ public int ChunkSpan { get; } = chunkSpan;
+ public PostageProof PostageProof { get; } = postageProof;
+ public IEnumerable ProofSegments { get; } = proofSegments;
+ public IEnumerable ProofSegments2 { get; } = proofSegments2;
+ public IEnumerable ProofSegments3 { get; } = proofSegments3;
+ public string ProveSegment { get; } = proveSegment;
+ public string ProveSegment2 { get; } = proveSegment2;
+ public IEnumerable SocProof { get; } = socProof;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Core/Models/ReserveState.cs b/src/BeeNet.Core/Models/ReserveState.cs
new file mode 100644
index 00000000..aca04f7f
--- /dev/null
+++ b/src/BeeNet.Core/Models/ReserveState.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ReserveState(
+ long commitment,
+ int radius,
+ int storageRadius)
+ {
+ // Properties.
+ public long Commitment { get; } = commitment;
+ public int Radius { get; } = radius;
+ public int StorageRadius { get; } = storageRadius;
+ }
+}
diff --git a/src/BeeNet.Core/Models/ResultChequebook.cs b/src/BeeNet.Core/Models/ResultChequebook.cs
new file mode 100644
index 00000000..53dc4de5
--- /dev/null
+++ b/src/BeeNet.Core/Models/ResultChequebook.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class ResultChequebook(
+ bool bounced,
+ BzzBalance lastPayout,
+ string recipient)
+ {
+ // Properties.
+ public bool Bounced { get; } = bounced;
+ public BzzBalance LastPayout { get; } = lastPayout;
+ public string Recipient { get; } = recipient;
+ }
+}
diff --git a/src/BeeNet.Core/Models/Settlement.cs b/src/BeeNet.Core/Models/Settlement.cs
new file mode 100644
index 00000000..16d1aa1e
--- /dev/null
+++ b/src/BeeNet.Core/Models/Settlement.cs
@@ -0,0 +1,29 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class Settlement(
+ BzzBalance totalReceived,
+ BzzBalance totalSent,
+ IEnumerable settlements)
+ {
+ // Properties.
+ public BzzBalance TotalReceived { get; } = totalReceived;
+ public BzzBalance TotalSent { get; } = totalSent;
+ public IEnumerable Settlements { get; } = settlements;
+ }
+}
diff --git a/src/BeeNet.Core/Models/SettlementData.cs b/src/BeeNet.Core/Models/SettlementData.cs
new file mode 100644
index 00000000..2f0bf487
--- /dev/null
+++ b/src/BeeNet.Core/Models/SettlementData.cs
@@ -0,0 +1,27 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class SettlementData(
+ string peer,
+ BzzBalance received,
+ BzzBalance sent)
+ {
+ // Properties.
+ public string Peer { get; } = peer;
+ public BzzBalance Received { get; } = received;
+ public BzzBalance Sent { get; } = sent;
+ }
+}
diff --git a/src/BeeNet.Core/Models/SocProof.cs b/src/BeeNet.Core/Models/SocProof.cs
new file mode 100644
index 00000000..2f502cba
--- /dev/null
+++ b/src/BeeNet.Core/Models/SocProof.cs
@@ -0,0 +1,29 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class SocProof(
+ SwarmHash chunkHash,
+ string identifier,
+ string signature,
+ string signer)
+ {
+ // Properties.
+ public SwarmHash ChunkHash { get; } = chunkHash;
+ public string Identifier { get; } = identifier;
+ public string Signature { get; } = signature;
+ public string Signer { get; } = signer;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Postage/StampBucketIndex.cs b/src/BeeNet.Core/Models/StampBucketIndex.cs
similarity index 97%
rename from src/BeeNet/Hasher/Postage/StampBucketIndex.cs
rename to src/BeeNet.Core/Models/StampBucketIndex.cs
index 2972a419..c697d154 100644
--- a/src/BeeNet/Hasher/Postage/StampBucketIndex.cs
+++ b/src/BeeNet.Core/Models/StampBucketIndex.cs
@@ -15,7 +15,7 @@
using System;
using System.Buffers.Binary;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Models
{
public class StampBucketIndex(uint bucketId, uint bucketCounter)
{
diff --git a/src/BeeNet.Core/Models/StampsBuckets.cs b/src/BeeNet.Core/Models/StampsBuckets.cs
new file mode 100644
index 00000000..355e55fa
--- /dev/null
+++ b/src/BeeNet.Core/Models/StampsBuckets.cs
@@ -0,0 +1,31 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class StampsBuckets(
+ int depth,
+ int bucketDepth,
+ int bucketUpperBound,
+ IEnumerable collisions)
+ {
+ // Properties.
+ public int Depth { get; } = depth;
+ public int BucketDepth { get; } = bucketDepth;
+ public int BucketUpperBound { get; } = bucketUpperBound;
+ public IEnumerable Collisions { get; } = collisions;
+ }
+}
diff --git a/src/BeeNet/Models/StatusBeeMode.cs b/src/BeeNet.Core/Models/StatusBeeMode.cs
similarity index 100%
rename from src/BeeNet/Models/StatusBeeMode.cs
rename to src/BeeNet.Core/Models/StatusBeeMode.cs
diff --git a/src/BeeNet.Core/Models/StatusNode.cs b/src/BeeNet.Core/Models/StatusNode.cs
new file mode 100644
index 00000000..ac0633bb
--- /dev/null
+++ b/src/BeeNet.Core/Models/StatusNode.cs
@@ -0,0 +1,43 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class StatusNode(
+ StatusBeeMode beeMode,
+ int batchCommitment,
+ int connectedPeers,
+ int neighborhoodSize,
+ string peer,
+ int proximity,
+ double pullsyncRate,
+ int reserveSize,
+ int reserveSizeWithinRadius,
+ bool? requestFailed,
+ int storageRadius)
+ {
+ // Properties.
+ public StatusBeeMode BeeMode { get; } = beeMode;
+ public int BatchCommitment { get; } = batchCommitment;
+ public int ConnectedPeers { get; } = connectedPeers;
+ public int NeighborhoodSize { get; } = neighborhoodSize;
+ public string Peer { get; } = peer;
+ public int Proximity { get; } = proximity;
+ public double PullsyncRate { get; } = pullsyncRate;
+ public int ReserveSize { get; } = reserveSize;
+ public int ReserveSizeWithinRadius { get; } = reserveSizeWithinRadius;
+ public bool? RequestFailed { get; } = requestFailed;
+ public int StorageRadius { get; } = storageRadius;
+ }
+}
diff --git a/src/BeeNet/Models/SwarmAddress.cs b/src/BeeNet.Core/Models/SwarmAddress.cs
similarity index 63%
rename from src/BeeNet/Models/SwarmAddress.cs
rename to src/BeeNet.Core/Models/SwarmAddress.cs
index eac9d419..f1b12aae 100644
--- a/src/BeeNet/Models/SwarmAddress.cs
+++ b/src/BeeNet.Core/Models/SwarmAddress.cs
@@ -14,76 +14,67 @@
using System;
using System.Collections.Generic;
-using System.IO;
namespace Etherna.BeeNet.Models
{
public readonly struct SwarmAddress : IEquatable
{
+ // Consts.
+ public const char Separator = '/';
+
// Constructor.
- public SwarmAddress(SwarmHash hash, Uri? relativePath = null)
+ public SwarmAddress(SwarmHash hash, string? path = null)
{
- if (relativePath is not null &&
- relativePath.IsAbsoluteUri)
- throw new ArgumentException("Path needs to be relative", nameof(relativePath));
-
Hash = hash;
- RelativePath = relativePath;
+ Path = NormalizePath(path);
}
public SwarmAddress(string address)
{
ArgumentNullException.ThrowIfNull(address, nameof(address));
- // Trim initial and final slash.
- address = address.Trim('/');
+ // Trim initial slash.
+ address = address.TrimStart(Separator);
// Extract hash root.
- var slashIndex = address.IndexOf('/', StringComparison.InvariantCulture);
- var root = slashIndex > 0 ? address[..slashIndex] : address;
- var path = slashIndex > 0 ? address[(slashIndex + 1)..] : null;
+ var slashIndex = address.IndexOf(Separator, StringComparison.InvariantCulture);
+ var hash = slashIndex > 0 ? address[..slashIndex] : address;
+ var path = slashIndex > 0 ? address[slashIndex..] : Separator.ToString();
// Set hash and path.
- Hash = new SwarmHash(root);
- if (!string.IsNullOrEmpty(path))
- RelativePath = new Uri(path, UriKind.Relative);
+ Hash = new SwarmHash(hash);
+ Path = NormalizePath(path);
}
// Properties.
public SwarmHash Hash { get; }
- public Uri? RelativePath { get; }
+ public string Path { get; }
// Methods.
public bool Equals(SwarmAddress other) =>
Hash.Equals(other.Hash) &&
- EqualityComparer.Default.Equals(RelativePath, other.RelativePath);
+ EqualityComparer.Default.Equals(Path, other.Path);
public override bool Equals(object? obj) => obj is SwarmAddress other && Equals(other);
public override int GetHashCode() => Hash.GetHashCode() ^
- (RelativePath?.GetHashCode() ?? 0);
- public override string ToString()
- {
- if (RelativePath is null)
- return Hash + "/";
-
- var pathString = RelativePath.ToString();
- if (Path.IsPathRooted(pathString))
- return Hash + pathString;
-
- return Hash + "/" + pathString;
- }
+ (Path?.GetHashCode(StringComparison.InvariantCulture) ?? 0);
+ public override string ToString() => Hash + Path;
// Static methods.
- public static SwarmAddress FromSwarmHash(SwarmHash value) => new(value);
public static SwarmAddress FromString(string value) => new(value);
+ public static SwarmAddress FromSwarmHash(SwarmHash value) => new(value);
// Operator methods.
public static bool operator ==(SwarmAddress left, SwarmAddress right) => left.Equals(right);
public static bool operator !=(SwarmAddress left, SwarmAddress right) => !(left == right);
// Implicit conversion operator methods.
- public static implicit operator SwarmAddress(SwarmHash value) => new(value);
public static implicit operator SwarmAddress(string value) => new(value);
+ public static implicit operator SwarmAddress(SwarmHash value) => new(value);
// Explicit conversion operator methods.
public static explicit operator string(SwarmAddress value) => value.ToString();
+
+ // Helpers.
+ internal static string NormalizePath(string? path) =>
+ Separator + (path ?? "").TrimStart(Separator);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Models/SwarmChunk.cs b/src/BeeNet.Core/Models/SwarmChunk.cs
similarity index 95%
rename from src/BeeNet/Models/SwarmChunk.cs
rename to src/BeeNet.Core/Models/SwarmChunk.cs
index e45d1a96..b3ff467a 100644
--- a/src/BeeNet/Models/SwarmChunk.cs
+++ b/src/BeeNet.Core/Models/SwarmChunk.cs
@@ -12,8 +12,6 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Bmt;
-using Etherna.BeeNet.Hasher.Postage;
using System;
using System.Buffers.Binary;
@@ -26,7 +24,7 @@ public class SwarmChunk
protected readonly byte[] _span;
// Consts.
- public const int DataSize = SwarmChunkBmt.SegmentSize * SwarmChunkBmt.SegmentsCount;
+ public const int DataSize = 4096;
public const int SpanAndDataSize = SpanSize + DataSize;
public const int SpanSize = 8;
diff --git a/src/BeeNet.Core/Models/SwarmChunkReference.cs b/src/BeeNet.Core/Models/SwarmChunkReference.cs
new file mode 100644
index 00000000..e746b175
--- /dev/null
+++ b/src/BeeNet.Core/Models/SwarmChunkReference.cs
@@ -0,0 +1,9 @@
+namespace Etherna.BeeNet.Models
+{
+ public class SwarmChunkReference(SwarmHash hash, XorEncryptKey? encryptionKey, bool useRecursiveEncryption)
+ {
+ public XorEncryptKey? EncryptionKey { get; } = encryptionKey;
+ public SwarmHash Hash { get; } = hash;
+ public bool UseRecursiveEncryption { get; } = useRecursiveEncryption;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Models/SwarmFeedChunk.cs b/src/BeeNet.Core/Models/SwarmFeedChunk.cs
similarity index 84%
rename from src/BeeNet/Models/SwarmFeedChunk.cs
rename to src/BeeNet.Core/Models/SwarmFeedChunk.cs
index 641d1d86..e524c22e 100644
--- a/src/BeeNet/Models/SwarmFeedChunk.cs
+++ b/src/BeeNet.Core/Models/SwarmFeedChunk.cs
@@ -12,11 +12,11 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Epoche;
using Etherna.BeeNet.Extensions;
-using Etherna.BeeNet.Feeds;
+using Etherna.BeeNet.Models.Feeds;
using Nethereum.Hex.HexConvertors.Extensions;
using Nethereum.Util;
+using Nethereum.Util.HashProviders;
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
@@ -95,46 +95,48 @@ public static byte[] BuildChunkPayload(byte[] payload, ulong? timestamp = null)
return chunkData;
}
- public static SwarmHash BuildHash(string account, byte[] topic, FeedIndexBase index) =>
- BuildHash(account, BuildIdentifier(topic, index));
+ public static SwarmHash BuildHash(string account, byte[] topic, FeedIndexBase index, IHashProvider hashProvider) =>
+ BuildHash(account, BuildIdentifier(topic, index, hashProvider), hashProvider);
- public static SwarmHash BuildHash(byte[] account, byte[] topic, FeedIndexBase index) =>
- BuildHash(account, BuildIdentifier(topic, index));
+ public static SwarmHash BuildHash(byte[] account, byte[] topic, FeedIndexBase index, IHashProvider hashProvider) =>
+ BuildHash(account, BuildIdentifier(topic, index, hashProvider), hashProvider);
- public static SwarmHash BuildHash(string account, byte[] identifier)
+ public static SwarmHash BuildHash(string account, byte[] identifier, IHashProvider hashProvider)
{
if (!account.IsValidEthereumAddressHexFormat())
throw new ArgumentException("Value is not a valid ethereum account", nameof(account));
- return BuildHash(account.HexToByteArray(), identifier);
+ return BuildHash(account.HexToByteArray(), identifier, hashProvider);
}
- public static SwarmHash BuildHash(byte[] account, byte[] identifier)
+ public static SwarmHash BuildHash(byte[] account, byte[] identifier, IHashProvider hashProvider)
{
ArgumentNullException.ThrowIfNull(account, nameof(account));
+ ArgumentNullException.ThrowIfNull(hashProvider, nameof(hashProvider));
ArgumentNullException.ThrowIfNull(identifier, nameof(identifier));
if (account.Length != AccountSize)
throw new ArgumentOutOfRangeException(nameof(account), "Invalid account length");
if (identifier.Length != IdentifierSize)
throw new ArgumentOutOfRangeException(nameof(identifier), "Invalid identifier length");
-
- return Keccak256.ComputeHash(identifier.Concat(account).ToArray());
+
+ return hashProvider.ComputeHash(identifier.Concat(account).ToArray());
}
- public static byte[] BuildIdentifier(byte[] topic, FeedIndexBase index)
+ public static byte[] BuildIdentifier(byte[] topic, FeedIndexBase index, IHashProvider hashProvider)
{
- ArgumentNullException.ThrowIfNull(topic, nameof(topic));
+ ArgumentNullException.ThrowIfNull(hashProvider, nameof(hashProvider));
ArgumentNullException.ThrowIfNull(index, nameof(index));
+ ArgumentNullException.ThrowIfNull(topic, nameof(topic));
if (topic.Length != TopicSize)
throw new ArgumentOutOfRangeException(nameof(topic), "Invalid topic length");
var newArray = new byte[TopicSize + IndexSize];
topic.CopyTo(newArray, 0);
- index.MarshalBinary.CopyTo(newArray, topic.Length);
+ index.GetMarshalBinaryHash(hashProvider).CopyTo(newArray.AsMemory()[topic.Length..]);
- return Keccak256.ComputeHash(newArray);
+ return hashProvider.ComputeHash(newArray);
}
}
}
diff --git a/src/BeeNet/Models/SwarmHash.cs b/src/BeeNet.Core/Models/SwarmHash.cs
similarity index 81%
rename from src/BeeNet/Models/SwarmHash.cs
rename to src/BeeNet.Core/Models/SwarmHash.cs
index 5c7fee99..38392fae 100644
--- a/src/BeeNet/Models/SwarmHash.cs
+++ b/src/BeeNet.Core/Models/SwarmHash.cs
@@ -31,7 +31,7 @@ namespace Etherna.BeeNet.Models
public SwarmHash(byte[] hash)
{
ArgumentNullException.ThrowIfNull(hash, nameof(hash));
- if (hash.Length != HashSize)
+ if (!IsValidHash(hash))
throw new ArgumentOutOfRangeException(nameof(hash));
byteHash = hash;
@@ -41,9 +41,16 @@ public SwarmHash(string hash)
{
ArgumentNullException.ThrowIfNull(hash, nameof(hash));
- byteHash = hash.HexToByteArray();
+ try
+ {
+ byteHash = hash.HexToByteArray();
+ }
+ catch (FormatException)
+ {
+ throw new ArgumentException("Invalid hash", nameof(hash));
+ }
- if (byteHash.Length != HashSize)
+ if (!IsValidHash(byteHash))
throw new ArgumentOutOfRangeException(nameof(hash));
}
@@ -63,6 +70,22 @@ public uint ToBucketId() =>
// Static methods.
public static SwarmHash FromByteArray(byte[] value) => new(value);
public static SwarmHash FromString(string value) => new(value);
+ public static bool IsValidHash(byte[] value)
+ {
+ ArgumentNullException.ThrowIfNull(value, nameof(value));
+ return value.Length == HashSize;
+ }
+ public static bool IsValidHash(string value)
+ {
+ try
+ {
+ return IsValidHash(value.HexToByteArray());
+ }
+ catch (FormatException)
+ {
+ return false;
+ }
+ }
// Operator methods.
public static bool operator ==(SwarmHash left, SwarmHash right) => left.Equals(right);
diff --git a/src/BeeNet.Core/Models/SwarmUri.cs b/src/BeeNet.Core/Models/SwarmUri.cs
new file mode 100644
index 00000000..da256a2f
--- /dev/null
+++ b/src/BeeNet.Core/Models/SwarmUri.cs
@@ -0,0 +1,149 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace Etherna.BeeNet.Models
+{
+ [SuppressMessage("Design", "CA1054:URI-like parameters should not be strings")]
+ public readonly struct SwarmUri : IEquatable
+ {
+ // Constructor.
+ public SwarmUri(SwarmHash? hash, string? path)
+ {
+ if (hash is null && path is null)
+ throw new ArgumentException("Hash and path can't be both null");
+
+ Hash = hash;
+ Path = hash != null ? SwarmAddress.NormalizePath(path) : path!;
+ }
+ public SwarmUri(string uri, UriKind uriKind)
+ {
+ ArgumentNullException.ThrowIfNull(uri, nameof(uri));
+
+ // Determine uri kind.
+ if (uriKind == UriKind.RelativeOrAbsolute)
+ uriKind = SwarmHash.IsValidHash(uri.Split(SwarmAddress.Separator)[0])
+ ? UriKind.Absolute
+ : UriKind.Relative;
+
+ if (uriKind == UriKind.Absolute)
+ {
+ var address = new SwarmAddress(uri);
+ Hash = address.Hash;
+ Path = address.Path;
+ }
+ else
+ {
+ Path = uri;
+ }
+ }
+
+ // Properties.
+ public SwarmHash? Hash { get; }
+ public bool IsRooted => UriKind == UriKind.Absolute || System.IO.Path.IsPathRooted(Path);
+ public string Path { get; }
+ public UriKind UriKind => Hash.HasValue ? UriKind.Absolute : UriKind.Relative;
+
+ // Methods.
+ public bool Equals(SwarmUri other) =>
+ Hash.Equals(other.Hash) &&
+ EqualityComparer.Default.Equals(Path, other.Path);
+
+ public override bool Equals(object? obj) => obj is SwarmUri other && Equals(other);
+
+ public override int GetHashCode() => Hash.GetHashCode() ^
+ (Path?.GetHashCode(StringComparison.InvariantCulture) ?? 0);
+
+ public override string ToString() =>
+ UriKind == UriKind.Absolute ? new SwarmAddress(Hash!.Value, Path).ToString() : Path!;
+
+ ///
+ /// Convert a URI to an Address. If URI is relative, a prefix Address must be provided
+ ///
+ /// Optional prefix address
+ /// The absolute URI as an Address
+ public SwarmAddress ToSwarmAddress(SwarmAddress? prefix = null)
+ {
+ if (prefix is null)
+ {
+ if (UriKind != UriKind.Absolute)
+ throw new InvalidOperationException("Url is not absolute, and a prefix address is required");
+
+ return new SwarmAddress(Hash!.Value, Path);
+ }
+
+ var combined = Combine(prefix.Value, this);
+ return new(combined.Hash!.Value, combined.Path);
+ }
+
+ public bool TryGetRelativeTo(SwarmUri relativeTo, out SwarmUri output)
+ {
+ output = default;
+
+ if (relativeTo.Hash != Hash)
+ return false;
+
+ var dirs = Path.Split(SwarmAddress.Separator);
+ var relativeToDirs = relativeTo.Path.TrimEnd(SwarmAddress.Separator).Split(SwarmAddress.Separator);
+ if (dirs.Length < relativeToDirs.Length ||
+ !dirs[..relativeToDirs.Length].SequenceEqual(relativeToDirs))
+ return false;
+
+ output = new SwarmUri(null, string.Join(SwarmAddress.Separator, dirs[relativeToDirs.Length..]));
+ return true;
+ }
+
+ // Static methods.
+ public static SwarmUri Combine(params SwarmUri[] uris)
+ {
+ ArgumentNullException.ThrowIfNull(uris, nameof(uris));
+ if (uris.Length == 0)
+ throw new ArgumentOutOfRangeException(nameof(uris), "Empty uri list");
+
+ var combined = uris[0];
+ foreach (var uri in uris.Skip(1))
+ {
+ if (uri.UriKind == UriKind.Absolute)
+ combined = uri;
+ else if (uri.IsRooted)
+ combined = new SwarmUri(combined.Hash, uri.Path);
+ else
+ combined = new SwarmUri(
+ combined.Hash,
+ (combined.Path ?? "").TrimEnd(SwarmAddress.Separator) + SwarmAddress.Separator + uri.Path);
+ }
+
+ return combined;
+ }
+ public static SwarmUri FromString(string value) => new(value, UriKind.RelativeOrAbsolute);
+ public static SwarmUri FromSwarmAddress(SwarmAddress value) => new(value.Hash, value.Path);
+ public static SwarmUri FromSwarmHash(SwarmHash value) => new(value, null);
+
+ // Operator methods.
+ public static bool operator ==(SwarmUri left, SwarmUri right) => left.Equals(right);
+ public static bool operator !=(SwarmUri left, SwarmUri right) => !(left == right);
+
+ // Implicit conversion operator methods.
+ public static implicit operator SwarmUri(string value) => new(value, UriKind.RelativeOrAbsolute);
+ public static implicit operator SwarmUri(SwarmAddress value) => new(value.Hash, value.Path);
+ public static implicit operator SwarmUri(SwarmHash value) => new(value, null);
+
+ // Explicit conversion operator methods.
+ public static explicit operator string(SwarmUri value) => value.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Models/DisconnectedPeers.cs b/src/BeeNet.Core/Models/TagInfo.cs
similarity index 62%
rename from src/BeeNet/Models/DisconnectedPeers.cs
rename to src/BeeNet.Core/Models/TagInfo.cs
index 246f96ae..b6801e20 100644
--- a/src/BeeNet/Models/DisconnectedPeers.cs
+++ b/src/BeeNet.Core/Models/TagInfo.cs
@@ -16,19 +16,22 @@
namespace Etherna.BeeNet.Models
{
- public sealed class DisconnectedPeers
+ public sealed class TagInfo(
+ long uid,
+ DateTimeOffset startedAt,
+ int split,
+ int seen,
+ int stored,
+ int sent,
+ int synced)
{
- // Constructors.
- internal DisconnectedPeers(Clients.DisconnectedPeers disconnectedPeers)
- {
- ArgumentNullException.ThrowIfNull(disconnectedPeers, nameof(disconnectedPeers));
-
- Address = disconnectedPeers.Address;
- Metrics = new PeerMetrics(disconnectedPeers.Metrics);
- }
-
// Properties.
- public string Address { get; }
- public PeerMetrics Metrics { get; }
+ public long Uid { get; } = uid;
+ public DateTimeOffset StartedAt { get; } = startedAt;
+ public int Split { get; } = split;
+ public int Seen { get; } = seen;
+ public int Stored { get; } = stored;
+ public int Sent { get; } = sent;
+ public int Synced { get; } = synced;
}
}
diff --git a/src/BeeNet.Core/Models/Topology.cs b/src/BeeNet.Core/Models/Topology.cs
new file mode 100644
index 00000000..2621ec6a
--- /dev/null
+++ b/src/BeeNet.Core/Models/Topology.cs
@@ -0,0 +1,42 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+using System.Collections.Generic;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class Topology(
+ string baseAddr,
+ IDictionary bins,
+ int connected,
+ int depth,
+ NetworkAvailability networkAvailability,
+ int nnLowWatermark,
+ int population,
+ Reachability reachability,
+ DateTimeOffset timestamp)
+ {
+ // Properties.
+ public string BaseAddr { get; } = baseAddr;
+ public IDictionary Bins { get; } = bins;
+ public int Connected { get; } = connected;
+ public int Depth { get; } = depth;
+ public NetworkAvailability NetworkAvailability { get; } = networkAvailability;
+ public int NnLowWatermark { get; } = nnLowWatermark;
+ public int Population { get; } = population;
+ public Reachability Reachability { get; } = reachability;
+ public DateTimeOffset Timestamp { get; } = timestamp;
+ }
+}
diff --git a/src/BeeNet.Core/Models/TxInfo.cs b/src/BeeNet.Core/Models/TxInfo.cs
new file mode 100644
index 00000000..7fecb204
--- /dev/null
+++ b/src/BeeNet.Core/Models/TxInfo.cs
@@ -0,0 +1,41 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+
+namespace Etherna.BeeNet.Models
+{
+ public sealed class TxInfo(
+ string transactionHash,
+ string to,
+ int nonce,
+ XDaiBalance gasPrice,
+ long gasLimit,
+ string data,
+ DateTimeOffset created,
+ string description,
+ XDaiBalance value)
+ {
+ // Properties.
+ public string TransactionHash { get; } = transactionHash;
+ public string To { get; } = to;
+ public int Nonce { get; } = nonce;
+ public XDaiBalance GasPrice { get; } = gasPrice;
+ public long GasLimit { get; } = gasLimit;
+ public string Data { get; } = data;
+ public DateTimeOffset Created { get; } = created;
+ public string Description { get; } = description;
+ public XDaiBalance Value { get; } = value;
+ }
+}
diff --git a/src/BeeNet/Models/InfoBeeMode.cs b/src/BeeNet.Core/Models/WalletBalances.cs
similarity index 75%
rename from src/BeeNet/Models/InfoBeeMode.cs
rename to src/BeeNet.Core/Models/WalletBalances.cs
index a7831929..8d281c85 100644
--- a/src/BeeNet/Models/InfoBeeMode.cs
+++ b/src/BeeNet.Core/Models/WalletBalances.cs
@@ -12,16 +12,14 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
-using System.Collections.Generic;
-using System.Text;
-
namespace Etherna.BeeNet.Models
{
- public enum InfoBeeMode
+ public sealed class WalletBalances(
+ BzzBalance bzzBalance,
+ XDaiBalance xDaiBalance)
{
- Light,
- Full,
- Dev,
+ // Properties.
+ public BzzBalance BzzBalance { get; } = bzzBalance;
+ public XDaiBalance XDaiBalance { get; } = xDaiBalance;
}
}
diff --git a/src/BeeNet/Models/XDaiBalance.cs b/src/BeeNet.Core/Models/XDaiBalance.cs
similarity index 100%
rename from src/BeeNet/Models/XDaiBalance.cs
rename to src/BeeNet.Core/Models/XDaiBalance.cs
diff --git a/src/BeeNet/Manifest/XorEncryptKey.cs b/src/BeeNet.Core/Models/XorEncryptKey.cs
similarity index 72%
rename from src/BeeNet/Manifest/XorEncryptKey.cs
rename to src/BeeNet.Core/Models/XorEncryptKey.cs
index b1c88f0a..5ef20990 100644
--- a/src/BeeNet/Manifest/XorEncryptKey.cs
+++ b/src/BeeNet.Core/Models/XorEncryptKey.cs
@@ -12,10 +12,11 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
+using Nethereum.Hex.HexConvertors.Extensions;
using System;
using System.Security.Cryptography;
-namespace Etherna.BeeNet.Manifest
+namespace Etherna.BeeNet.Models
{
public class XorEncryptKey
{
@@ -34,6 +35,23 @@ public XorEncryptKey(byte[] bytes)
this.bytes = bytes;
}
+
+ public XorEncryptKey(string key)
+ {
+ ArgumentNullException.ThrowIfNull(key, nameof(key));
+
+ try
+ {
+ bytes = key.HexToByteArray();
+ }
+ catch (FormatException)
+ {
+ throw new ArgumentException("Invalid hash", nameof(key));
+ }
+
+ if (!IsValidKey(bytes))
+ throw new ArgumentOutOfRangeException(nameof(key));
+ }
// Builders.
public static XorEncryptKey BuildNewRandom()
@@ -61,5 +79,14 @@ public void EncryptDecrypt(Span data)
for (var i = 0; i < data.Length; i++)
data[i] = (byte)(data[i] ^ bytes[i % bytes.Length]);
}
+
+ public override string ToString() => bytes.ToHex();
+
+ // Static methods.
+ public static bool IsValidKey(byte[] value)
+ {
+ ArgumentNullException.ThrowIfNull(value, nameof(value));
+ return value.Length == KeySize;
+ }
}
}
\ No newline at end of file
diff --git a/src/BeeNet.Util.Wasm/BeeNet.Util.Wasm.csproj b/src/BeeNet.Util.Wasm/BeeNet.Util.Wasm.csproj
new file mode 100644
index 00000000..68146d5b
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/BeeNet.Util.Wasm.csproj
@@ -0,0 +1,30 @@
+
+
+ net8.0
+ true
+ Etherna.BeeNet.Wasm
+
+ Etherna SA
+ Utility services to work with Ethereum Swarm with WASM
+
+ false
+ true
+ AllEnabledByDefault
+
+ https://github.com/Etherna/bee-net
+ git
+ COPYING
+ COPYING-LESSER
+ README.md
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BeeNet.Util.Wasm/Program.cs b/src/BeeNet.Util.Wasm/Program.cs
new file mode 100644
index 00000000..a1c6435d
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/Program.cs
@@ -0,0 +1,29 @@
+using Etherna.BeeNet.Services;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.InteropServices.JavaScript;
+using System.Threading.Tasks;
+
+#pragma warning disable CA1303
+Console.WriteLine("Main, don't remove!");
+#pragma warning restore CA1303
+
+[SuppressMessage("Design", "CA1052:Static holder types should be Static or NotInheritable")]
+[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
+[SuppressMessage("Design", "CA1050:Declare types in namespaces")]
+public partial class BeeNetWasmUtil
+{
+ [JSExport]
+ internal static async Task GetHashStringAsync(
+ byte[] data,
+ string fileContentType,
+ string fileName)
+ {
+ var calculatorService = new CalculatorService();
+ var result = await calculatorService.EvaluateFileUploadAsync(
+ data,
+ fileContentType,
+ fileName).ConfigureAwait(false);
+ return result.Hash.ToString();
+ }
+}
diff --git a/src/BeeNet.Util.Wasm/Properties/AssemblyInfo.cs b/src/BeeNet.Util.Wasm/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000..2b51b753
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/Properties/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+[assembly: System.Runtime.Versioning.SupportedOSPlatform("browser")]
\ No newline at end of file
diff --git a/src/BeeNet.Util.Wasm/Properties/launchSettings.json b/src/BeeNet.Util.Wasm/Properties/launchSettings.json
new file mode 100644
index 00000000..bed8bdce
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/Properties/launchSettings.json
@@ -0,0 +1,13 @@
+{
+ "profiles": {
+ "BeeNet.Util.Wasm": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:7080;http://localhost:5094",
+ "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
+ }
+ }
+}
diff --git a/src/BeeNet.Util.Wasm/runtimeconfig.template.json b/src/BeeNet.Util.Wasm/runtimeconfig.template.json
new file mode 100644
index 00000000..b96a9432
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/runtimeconfig.template.json
@@ -0,0 +1,10 @@
+{
+ "wasmHostProperties": {
+ "perHostConfig": [
+ {
+ "name": "browser",
+ "host": "browser"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Util.Wasm/wwwroot/index.html b/src/BeeNet.Util.Wasm/wwwroot/index.html
new file mode 100644
index 00000000..04ac67cb
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/wwwroot/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+ BeeNet.Util.Wasm
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BeeNet.Util.Wasm/wwwroot/main.js b/src/BeeNet.Util.Wasm/wwwroot/main.js
new file mode 100644
index 00000000..e45548a0
--- /dev/null
+++ b/src/BeeNet.Util.Wasm/wwwroot/main.js
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+import { dotnet } from './_framework/dotnet.js'
+
+const { setModuleImports, getAssemblyExports, getConfig } = await dotnet
+ .withDiagnosticTracing(false)
+ .withApplicationArgumentsFromQuery()
+ .create();
+
+setModuleImports('main.js', {
+ window: {
+ location: {
+ href: () => globalThis.window.location.href
+ }
+ }
+});
+
+const config = getConfig();
+const exports = await getAssemblyExports(config.mainAssemblyName);
+
+let utf8Encode = new TextEncoder();
+let array = utf8Encode.encode("Bzz over the world!");
+
+const hash = await exports.BeeNetWasmUtil.GetHashStringAsync(
+ array,
+ "text/plain",
+ "hello.txt"
+);
+console.log(hash);
+
+document.getElementById('out').innerHTML = hash;
+await dotnet.run();
\ No newline at end of file
diff --git a/src/BeeNet.Util/BeeNet.Util.csproj b/src/BeeNet.Util/BeeNet.Util.csproj
new file mode 100644
index 00000000..32a92dcb
--- /dev/null
+++ b/src/BeeNet.Util/BeeNet.Util.csproj
@@ -0,0 +1,53 @@
+
+
+
+ net6.0;net7.0;net8.0
+ true
+ Etherna.BeeNet
+
+ Etherna SA
+ Utility services to work with Ethereum Swarm in .Net
+
+ 12
+ enable
+ true
+ true
+ AllEnabledByDefault
+
+ Bee.Net.Util
+ https://github.com/Etherna/bee-net
+ git
+ true
+ true
+ snupkg
+ COPYING
+ COPYING-LESSER
+ README.md
+ true
+ true
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/BeeNet/Hasher/Bmt/SwarmChunkBmt.cs b/src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmt.cs
similarity index 73%
rename from src/BeeNet/Hasher/Bmt/SwarmChunkBmt.cs
rename to src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmt.cs
index 82a57e1e..7a2f5a7c 100644
--- a/src/BeeNet/Hasher/Bmt/SwarmChunkBmt.cs
+++ b/src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmt.cs
@@ -12,21 +12,23 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Epoche;
using Etherna.BeeNet.Models;
using Nethereum.Merkle;
using Nethereum.Merkle.StrategyOptions.PairingConcat;
using Nethereum.Util.ByteArrayConvertors;
-using Nethereum.Util.HashProviders;
using System;
using System.Collections.Generic;
-namespace Etherna.BeeNet.Hasher.Bmt
+namespace Etherna.BeeNet.Hashing.Bmt
{
- internal class SwarmChunkBmt : MerkleTree
+ internal sealed class SwarmChunkBmt(IHasher hasher)
+ : MerkleTree(
+ hasher,
+ byteArrayConvertor,
+ PairingConcatType.Normal)
{
// Classes.
- private class ChunkBmtByteArrayConvertor : IByteArrayConvertor
+ private sealed class ChunkBmtByteArrayConvertor : IByteArrayConvertor
{
///
/// Verify that chunk segment data has right size
@@ -46,27 +48,13 @@ public byte[] ConvertToByteArray(byte[] data)
return data;
}
}
- private class HashProvider : IHashProvider
- {
- public byte[] ComputeHash(byte[] data) => Keccak256.ComputeHash(data);
- }
// Consts.
- public const int MaxDataSize = SegmentsCount * SegmentSize;
- public const int SegmentsCount = 128;
- public const int SegmentSize = 32; //Keccak hash size
+ public const int SegmentsCount = SwarmChunk.DataSize / SegmentSize;
+ public const int SegmentSize = SwarmHash.HashSize;
// Static fields.
private static readonly ChunkBmtByteArrayConvertor byteArrayConvertor = new();
- private static readonly HashProvider hashProvider = new();
-
- // Constructor.
- public SwarmChunkBmt()
- : base(hashProvider, byteArrayConvertor, PairingConcatType.Normal)
- { }
-
- // Static methods.
- public static SwarmHash ComputeHash(byte[] data) => hashProvider.ComputeHash(data);
// Protected override methods.
protected override MerkleTreeNode CreateMerkleTreeNode(byte[] item) =>
diff --git a/src/BeeNet/Hasher/Bmt/SwarmChunkBmtHasher.cs b/src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmtHasher.cs
similarity index 80%
rename from src/BeeNet/Hasher/Bmt/SwarmChunkBmtHasher.cs
rename to src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmtHasher.cs
index 88f42bb0..cec1ece2 100644
--- a/src/BeeNet/Hasher/Bmt/SwarmChunkBmtHasher.cs
+++ b/src/BeeNet.Util/Hashing/Bmt/SwarmChunkBmtHasher.cs
@@ -17,18 +17,18 @@
using System.Collections.Generic;
using System.Linq;
-namespace Etherna.BeeNet.Hasher.Bmt
+namespace Etherna.BeeNet.Hashing.Bmt
{
internal static class SwarmChunkBmtHasher
{
// Static methods.
- public static SwarmHash Hash(byte[] span, byte[] data)
+ public static SwarmHash Hash(byte[] span, byte[] data, IHasher? hasher = null)
{
ArgumentNullException.ThrowIfNull(span, nameof(span));
ArgumentNullException.ThrowIfNull(data, nameof(data));
- if (data.Length > SwarmChunkBmt.MaxDataSize)
- throw new ArgumentOutOfRangeException(nameof(data), $"Max writable data is {SwarmChunkBmt.MaxDataSize} bytes");
+ if (data.Length > SwarmChunk.DataSize)
+ throw new ArgumentOutOfRangeException(nameof(data), $"Max writable data is {SwarmChunk.DataSize} bytes");
// Split input data into leaf segments.
var segments = new List();
@@ -39,11 +39,12 @@ public static SwarmHash Hash(byte[] span, byte[] data)
}
// Build the merkle tree.
- var bmt = new SwarmChunkBmt();
+ hasher ??= new Hasher();
+ var bmt = new SwarmChunkBmt(hasher);
bmt.BuildTree(segments);
var result = bmt.Root.Hash;
- return SwarmChunkBmt.ComputeHash(span.Concat(result).ToArray());
+ return hasher.ComputeHash(span.Concat(result).ToArray());
}
}
}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/Hasher.cs b/src/BeeNet.Util/Hashing/Hasher.cs
new file mode 100644
index 00000000..c3ce9a65
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Hasher.cs
@@ -0,0 +1,47 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Models;
+using Org.BouncyCastle.Crypto.Digests;
+using System;
+using System.Text;
+
+namespace Etherna.BeeNet.Hashing
+{
+ ///
+ /// Hasher service, not thread safe
+ ///
+ public class Hasher : IHasher
+ {
+ // Fields.
+ private readonly KeccakDigest hasher = new(256);
+
+ // Methods.
+ public void ComputeHash(byte[] data, Span output)
+ {
+ hasher.BlockUpdate(data);
+ hasher.DoFinal(output);
+ }
+
+ public byte[] ComputeHash(byte[] data)
+ {
+ var result = new byte[SwarmHash.HashSize];
+ ComputeHash(data, result);
+ return result;
+ }
+
+ public byte[] ComputeHash(string data) =>
+ ComputeHash(Encoding.UTF8.GetBytes(data));
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/IHasher.cs b/src/BeeNet.Util/Hashing/IHasher.cs
new file mode 100644
index 00000000..02be670c
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/IHasher.cs
@@ -0,0 +1,25 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using System;
+
+namespace Etherna.BeeNet.Hashing
+{
+ public interface IHasher :
+ Nethereum.Util.HashProviders.IHashProvider
+ {
+ void ComputeHash(byte[] data, Span output);
+ byte[] ComputeHash(string data);
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/ChunkAggregatorPipelineStage.cs b/src/BeeNet.Util/Hashing/Pipeline/ChunkAggregatorPipelineStage.cs
similarity index 73%
rename from src/BeeNet/Hasher/Pipeline/ChunkAggregatorPipelineStage.cs
rename to src/BeeNet.Util/Hashing/Pipeline/ChunkAggregatorPipelineStage.cs
index cf78ec97..9f73724d 100644
--- a/src/BeeNet/Hasher/Pipeline/ChunkAggregatorPipelineStage.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/ChunkAggregatorPipelineStage.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Bmt;
+using Etherna.BeeNet.Hashing.Bmt;
using Etherna.BeeNet.Models;
using System;
using System.Collections.Generic;
@@ -20,15 +20,18 @@
using System.Threading;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
- internal delegate Task HashChunkDelegateAsync(byte[] span, byte[] data);
-
internal sealed class ChunkAggregatorPipelineStage : IHasherPipelineStage
{
// Private classes.
- private class ChunkHeader(SwarmHash hash, ReadOnlyMemory span, bool isParityChunk)
+ private sealed class ChunkHeader(
+ SwarmHash hash,
+ ReadOnlyMemory span,
+ XorEncryptKey? chunkKey,
+ bool isParityChunk)
{
+ public XorEncryptKey? ChunkKey { get; } = chunkKey;
public SwarmHash Hash { get; } = hash;
public ReadOnlyMemory Span { get; } = span;
public bool IsParityChunk { get; } = isParityChunk;
@@ -38,18 +41,23 @@ private class ChunkHeader(SwarmHash hash, ReadOnlyMemory span, bool isPari
private readonly SemaphoreSlim feedChunkMutex = new(1, 1);
private readonly Dictionary feedingBuffer = new();
private readonly List> chunkLevels; //[level][chunk]
- private readonly HashChunkDelegateAsync hashChunkDelegate;
private readonly byte maxChildrenChunks;
+ private readonly ChunkBmtPipelineStage shortBmtPipelineStage;
+ private readonly bool useRecursiveEncryption;
private long feededChunkNumberId;
// Constructor.
public ChunkAggregatorPipelineStage(
- HashChunkDelegateAsync hashChunkDelegate)
+ ChunkBmtPipelineStage shortBmtPipelineStage,
+ bool useRecursiveEncryption)
{
chunkLevels = [];
- this.hashChunkDelegate = hashChunkDelegate;
- maxChildrenChunks = SwarmChunkBmt.SegmentsCount;
+ maxChildrenChunks = (byte)(useRecursiveEncryption
+ ? SwarmChunkBmt.SegmentsCount / 2 //write chunk key after chunk hash
+ : SwarmChunkBmt.SegmentsCount);
+ this.shortBmtPipelineStage = shortBmtPipelineStage;
+ this.useRecursiveEncryption = useRecursiveEncryption;
}
// Dispose.
@@ -58,6 +66,9 @@ public void Dispose()
feedChunkMutex.Dispose();
}
+ // Properties.
+ public long MissedOptimisticHashing => shortBmtPipelineStage.MissedOptimisticHashing;
+
// Methods.
public async Task FeedAsync(HasherPipelineFeedArgs args)
{
@@ -83,6 +94,7 @@ await AddChunkToLevelAsync(
new ChunkHeader(
processingChunk.Hash!.Value,
processingChunk.Span,
+ processingChunk.ChunkKey,
false)).ConfigureAwait(false);
}
}
@@ -92,7 +104,7 @@ await AddChunkToLevelAsync(
}
}
- public async Task SumAsync()
+ public async Task SumAsync()
{
bool rootChunkFound = false;
for (int i = 0; !rootChunkFound; i++)
@@ -118,7 +130,7 @@ public async Task SumAsync()
var rootChunk = chunkLevels.Last()[0];
- return rootChunk.Hash;
+ return new(rootChunk.Hash, rootChunk.ChunkKey, useRecursiveEncryption);
}
// Helpers.
@@ -151,19 +163,32 @@ private async Task WrapFullLevelAsync(int level)
.Aggregate((a,c) => a + c)); //sum of ulongs. Linq doesn't have it
// Build total data from total span, and all the hashes in level.
+ // If chunks are compacted, append the encryption key after the chunk hash.
var totalData = totalSpan.Concat(
- levelChunks.SelectMany(c => c.Hash.ToByteArray()))
+ levelChunks.SelectMany(c => useRecursiveEncryption
+ ? c.Hash.ToByteArray().Concat(c.ChunkKey!.Bytes.ToArray())
+ : c.Hash.ToByteArray()))
.ToArray();
// Run hashing on the new chunk, and add it to next level.
+ var hashingResult = await HashIntermediateChunkAsync(totalSpan, totalData).ConfigureAwait(false);
await AddChunkToLevelAsync(
level + 1,
new ChunkHeader(
- await hashChunkDelegate(totalSpan, totalData).ConfigureAwait(false),
+ hashingResult.Hash,
totalSpan,
+ hashingResult.EncryptionKey,
false)).ConfigureAwait(false);
levelChunks.Clear();
}
+
+ // Helpers.
+ private async Task HashIntermediateChunkAsync(byte[] span, byte[] data)
+ {
+ var args = new HasherPipelineFeedArgs(span: span, data: data);
+ await shortBmtPipelineStage.FeedAsync(args).ConfigureAwait(false);
+ return new(args.Hash!.Value, args.ChunkKey, useRecursiveEncryption);
+ }
}
}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/Pipeline/ChunkBmtPipelineStage.cs b/src/BeeNet.Util/Hashing/Pipeline/ChunkBmtPipelineStage.cs
new file mode 100644
index 00000000..f85897be
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Pipeline/ChunkBmtPipelineStage.cs
@@ -0,0 +1,227 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Hashing.Bmt;
+using Etherna.BeeNet.Hashing.Postage;
+using Etherna.BeeNet.Models;
+using System;
+using System.Buffers.Binary;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Etherna.BeeNet.Hashing.Pipeline
+{
+ ///
+ /// Calculate hash of each chunk
+ ///
+ internal sealed class ChunkBmtPipelineStage : IHasherPipelineStage
+ {
+ // Fields.
+ private readonly ushort compactLevel;
+ private readonly IHasherPipelineStage nextStage;
+ private readonly IPostageStampIssuer stampIssuer;
+
+ private long _missedOptimisticHashing;
+
+ // Constructor.
+ ///
+ /// Calculate hash of each chunk
+ ///
+ public ChunkBmtPipelineStage(
+ ushort compactLevel,
+ IHasherPipelineStage nextStage,
+ IPostageStampIssuer stampIssuer)
+ {
+ this.compactLevel = compactLevel;
+ this.nextStage = nextStage;
+ this.stampIssuer = stampIssuer;
+ }
+
+ // Dispose.
+ public void Dispose()
+ {
+ nextStage.Dispose();
+ }
+
+ // Properties.
+ public long MissedOptimisticHashing =>
+ _missedOptimisticHashing + nextStage.MissedOptimisticHashing;
+
+ // Methods.
+ public async Task FeedAsync(HasherPipelineFeedArgs args)
+ {
+ if (args.Data.Length < SwarmChunk.SpanSize)
+ throw new InvalidOperationException("Data can't be shorter than span size here");
+ if (args.Data.Length > SwarmChunk.SpanAndDataSize)
+ throw new InvalidOperationException("Data can't be longer than chunk + span size here");
+
+ // Create an instance for this specific task. Hasher is not thread safe.
+ var hasher = new Hasher();
+
+ var plainChunkHash = SwarmChunkBmtHasher.Hash(
+ args.Data[..SwarmChunk.SpanSize].ToArray(),
+ args.Data[SwarmChunk.SpanSize..].ToArray(),
+ hasher);
+ if (compactLevel == 0)
+ {
+ /* If no chunk compaction is involved, simply calculate the chunk hash and proceed. */
+ args.Hash = plainChunkHash;
+ }
+ else
+ {
+ // Search best chunk key.
+ var bestChunkResult = await GetBestChunkAsync(args, plainChunkHash, hasher).ConfigureAwait(false);
+
+ args.ChunkKey = bestChunkResult.ChunkKey;
+ args.Data = bestChunkResult.EncryptedData;
+ args.Hash = bestChunkResult.Hash;
+ }
+
+ await nextStage.FeedAsync(args).ConfigureAwait(false);
+ }
+
+ public Task SumAsync() => nextStage.SumAsync();
+
+ // Helpers.
+ private static void EncryptDecryptChunkData(XorEncryptKey chunkKey, byte[] data)
+ {
+ // Don't encrypt span, otherwise knowing the chunk length, we could reconstruct the key.
+ chunkKey.EncryptDecrypt(data.AsSpan()[SwarmChunk.SpanSize..]);
+ }
+
+ private async Task GetBestChunkAsync(
+ HasherPipelineFeedArgs args,
+ SwarmHash plainChunkHash,
+ Hasher hasher)
+ {
+ /*
+ * If chunk compaction is involved, use optimistic calculation.
+ *
+ * Calculate an encryption key, and try to find a bucket with optimal collisions.
+ * Before to proceed with the chunk and its key, wait optimistically until
+ * the previous chunk has been completed. Then verify if the same bucket has received
+ * new collisions, or not. If not, proceed, otherwise try again to search the best chunk key.
+ *
+ * The chunk key is calculate from the plain chunk hash, replacing the last 4 bytes
+ * with the attempt counter (int), and then hashing again.
+ *
+ * chunkKey = Keccack(plainChunkHash[^2..] + attempt)
+ *
+ * The encrypted chunk is calculated encrypting data with the chunk key.
+ *
+ * The optimistic algorithm will search the first best chunk available, trying a max of
+ * incremental attempts with max at the "compactionLevel" parameter.
+ *
+ * Best chunk is a chunk that fits in a bucket with the lowest possible number of collisions.
+ *
+ * Use a cache on generated chunkKey and relative bucketId for each attempt. This permits to not
+ * repeat the hash calculation in case that we need to repeat the search.
+ */
+
+ // Run optimistically before prev chunk completion.
+ var encryptionCache = new Dictionary();
+ var (bestKeyAttempt, expectedCollisions) = SearchFirstBestChunkKey(args, encryptionCache, plainChunkHash, hasher);
+
+ // If there isn't any prev chunk to wait, proceed with result.
+ if (args.PrevChunkSemaphore == null)
+ return encryptionCache[bestKeyAttempt];
+
+ try
+ {
+ // Otherwise wait until prev chunk has been processed.
+ await args.PrevChunkSemaphore.WaitAsync().ConfigureAwait(false);
+
+ // ** Here chunks can enter only once per time, and in order. **
+
+ // Check the optimistic result, and keep if valid.
+ var bestBucketId = encryptionCache[bestKeyAttempt].Hash.ToBucketId();
+ var actualCollisions = stampIssuer.Buckets.GetCollisions(bestBucketId);
+
+ if (actualCollisions == expectedCollisions)
+ return encryptionCache[bestKeyAttempt];
+
+ // If it has been invalidated, do it again.
+ _missedOptimisticHashing++;
+ var (newBestKeyAttempt, _) = SearchFirstBestChunkKey(args, encryptionCache, plainChunkHash, hasher);
+ return encryptionCache[newBestKeyAttempt];
+ }
+ finally
+ {
+ //release prev chunk semaphore to reuse it
+ args.PrevChunkSemaphore.Release();
+ }
+ }
+
+ private (ushort BestKeyAttempt, uint ExpectedCollisions) SearchFirstBestChunkKey(
+ HasherPipelineFeedArgs args,
+ Dictionary optimisticCache,
+ SwarmHash plainChunkHash,
+ Hasher hasher)
+ {
+ // Init.
+ ushort bestAttempt = 0;
+ uint bestCollisions = 0;
+
+ var plainChunkHashArray = plainChunkHash.ToByteArray();
+
+ // Search best chunk key.
+ for (ushort i = 0; i < compactLevel; i++)
+ {
+ uint collisions;
+
+ if (optimisticCache.TryGetValue(i, out var cachedValues))
+ {
+ collisions = stampIssuer.Buckets.GetCollisions(cachedValues.Hash.ToBucketId());
+ }
+ else
+ {
+ // Create key.
+ BinaryPrimitives.WriteUInt16BigEndian(plainChunkHashArray.AsSpan()[^2..], i);
+ var chunkKey = new XorEncryptKey(hasher.ComputeHash(plainChunkHashArray));
+
+ // Encrypt data.
+ var encryptedData = args.Data.ToArray();
+ EncryptDecryptChunkData(chunkKey, encryptedData);
+
+ // Calculate hash, bucket id, and save in cache.
+ var encryptedHash = SwarmChunkBmtHasher.Hash(
+ encryptedData[..SwarmChunk.SpanSize],
+ encryptedData[SwarmChunk.SpanSize..],
+ hasher);
+ optimisticCache[i] = new(chunkKey, encryptedData, encryptedHash);
+
+ // Check key collisions.
+ collisions = stampIssuer.Buckets.GetCollisions(encryptedHash.ToBucketId());
+ }
+
+ // First attempt is always the best one.
+ if (i == 0)
+ bestCollisions = collisions;
+
+ // Check if collisions are optimal.
+ if (collisions == stampIssuer.Buckets.MinBucketCollisions)
+ return (i, collisions);
+
+ // Else, if this reach better collisions, but not the best.
+ if (collisions < bestCollisions)
+ {
+ bestAttempt = i;
+ bestCollisions = collisions;
+ }
+ }
+
+ return (bestAttempt, bestCollisions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/Pipeline/ChunkFeederPipelineStage.cs b/src/BeeNet.Util/Hashing/Pipeline/ChunkFeederPipelineStage.cs
new file mode 100644
index 00000000..c498ab7e
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Pipeline/ChunkFeederPipelineStage.cs
@@ -0,0 +1,179 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Models;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Etherna.BeeNet.Hashing.Pipeline
+{
+ ///
+ /// Produce chunked data with span prefix for successive stages.
+ /// Also controls the parallelism on chunk elaboration
+ ///
+ internal sealed class ChunkFeederPipelineStage : IHasherPipeline
+ {
+ // Fields.
+ private readonly SemaphoreSlim chunkConcurrencySemaphore;
+ private readonly ConcurrentQueue chunkSemaphorePool;
+ private readonly IHasherPipelineStage nextStage;
+ private readonly List nextStageTasks = new();
+
+ private long passedBytes;
+
+ // Constructors.
+ [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
+ public ChunkFeederPipelineStage(
+ IHasherPipelineStage nextStage,
+ int? chunkConcurrency = default)
+ {
+ chunkConcurrency ??= Environment.ProcessorCount;
+
+ this.nextStage = nextStage;
+ chunkConcurrencySemaphore = new(chunkConcurrency.Value, chunkConcurrency.Value);
+ chunkSemaphorePool = new ConcurrentQueue();
+
+ //init semaphore pool
+ /*
+ * Double semaphores compared to current chunk concurrency.
+ * This avoids the race condition when: a chunk complete its hashing, it's semaphore is assigned and
+ * locked by another one, and only after this the direct child of the first one tries to wait its parent.
+ *
+ * This is possible because the returning order of semaphores in queue is not guaranteed.
+ *
+ * Explanation:
+ * While the task of chunk A is still waiting to lock on its prev A-1, all the prev chunks have ended tasks.
+ * Anyway, prevs didn't end in order, and for some reason semaphore that was of chunk A-1 comes in order
+ * before than next "Concurrency -1" (only active task is with A). Because of this, it can be allocated
+ * with any next task from A+1. If this happens before A locks on semaphore of A-1, we are in deadlock.
+ *
+ * Instead, doubling semaphores we guarantee that queue never goes under level of concurrency
+ * with contained elements, so a prev chunk's semaphore can't be reused until it's direct next
+ * has completed and released concurrency.
+ */
+ for (int i = 0; i < chunkConcurrency * 2; i++)
+ chunkSemaphorePool.Enqueue(new SemaphoreSlim(1, 1));
+ }
+
+ // Dispose.
+ public void Dispose()
+ {
+ nextStage.Dispose();
+ chunkConcurrencySemaphore.Dispose();
+ while (chunkSemaphorePool.TryDequeue(out var semaphore))
+ semaphore.Dispose();
+ }
+
+ // Properties.
+ public bool IsUsable { get; private set; } = true;
+
+ public long MissedOptimisticHashing => nextStage.MissedOptimisticHashing;
+
+ // Methods.
+ public async Task HashDataAsync(byte[] data)
+ {
+ ArgumentNullException.ThrowIfNull(data, nameof(data));
+
+ using var memoryStream = new MemoryStream(data);
+ return await HashDataAsync(memoryStream).ConfigureAwait(false);
+ }
+
+ public async Task HashDataAsync(Stream dataStream)
+ {
+ ArgumentNullException.ThrowIfNull(dataStream, nameof(dataStream));
+
+ if (!IsUsable)
+ throw new InvalidOperationException("Pipeline has already been used");
+
+ // Make it no more usable.
+ IsUsable = false;
+
+ // Slicing the stream permits to avoid to load all the stream in memory at the same time.
+ var chunkBuffer = new byte[SwarmChunk.DataSize];
+ int chunkReadSize;
+ SemaphoreSlim? prevChunkSemaphore = null;
+ do
+ {
+ chunkReadSize = await dataStream.ReadAsync(chunkBuffer).ConfigureAwait(false);
+
+ if (chunkReadSize > 0 || //write only chunks with data
+ passedBytes == 0) //or if the first and only one is empty
+ {
+ var chunkNumberId = passedBytes / SwarmChunk.DataSize;
+
+ // Copy read data from buffer to a new chunk data byte[]. Include also span
+ var chunkData = new byte[SwarmChunk.SpanSize + chunkReadSize];
+ chunkBuffer.AsSpan(0, chunkReadSize).CopyTo(chunkData.AsSpan(SwarmChunk.SpanSize));
+
+ // Write chunk span.
+ SwarmChunk.WriteSpan(
+ chunkData.AsSpan(0, SwarmChunk.SpanSize),
+ (ulong)chunkReadSize);
+
+ // Invoke next stage with parallelism on chunks.
+ //control concurrency
+ await chunkConcurrencySemaphore.WaitAsync().ConfigureAwait(false);
+
+ //initialize chunk semaphore, receiving from semaphore pool
+#pragma warning disable CA2000
+ if (!chunkSemaphorePool.TryDequeue(out var chunkSemaphore))
+ throw new InvalidOperationException("Semaphore pool exhausted");
+#pragma warning restore CA2000
+ await chunkSemaphore.WaitAsync().ConfigureAwait(false);
+
+ //build args
+ var feedArgs = new HasherPipelineFeedArgs(
+ span: chunkData[..SwarmChunk.SpanSize],
+ data: chunkData,
+ numberId: chunkNumberId,
+ prevChunkSemaphore: prevChunkSemaphore);
+
+ //run task
+ nextStageTasks.Add(
+ Task.Run(async () =>
+ {
+ try
+ {
+ await nextStage.FeedAsync(feedArgs).ConfigureAwait(false);
+ }
+ finally
+ {
+ //release and restore chunk semaphore in pool
+ chunkSemaphore.Release();
+ chunkSemaphorePool.Enqueue(chunkSemaphore);
+
+ //release task for next chunk
+ chunkConcurrencySemaphore.Release();
+ }
+ }));
+
+ //set current chunk semaphore as prev for next chunk
+ prevChunkSemaphore = chunkSemaphore;
+
+ passedBytes += chunkReadSize;
+ }
+ } while (chunkReadSize == SwarmChunk.DataSize);
+
+ // Wait the end of all chunk computation.
+ await Task.WhenAll(nextStageTasks).ConfigureAwait(false);
+
+ return await nextStage.SumAsync().ConfigureAwait(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/ChunkStoreWriterPipelineStage.cs b/src/BeeNet.Util/Hashing/Pipeline/ChunkStoreWriterPipelineStage.cs
similarity index 69%
rename from src/BeeNet/Hasher/Pipeline/ChunkStoreWriterPipelineStage.cs
rename to src/BeeNet.Util/Hashing/Pipeline/ChunkStoreWriterPipelineStage.cs
index 1286da82..edeadb8c 100644
--- a/src/BeeNet/Hasher/Pipeline/ChunkStoreWriterPipelineStage.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/ChunkStoreWriterPipelineStage.cs
@@ -12,37 +12,28 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Postage;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Postage;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using System;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
- internal sealed class ChunkStoreWriterPipelineStage : IHasherPipelineStage
+ internal sealed class ChunkStoreWriterPipelineStage(
+ IChunkStore chunkStore,
+ IPostageStamper postageStamper,
+ IHasherPipelineStage? nextStage)
+ : IHasherPipelineStage
{
- // Fields.
- private readonly IChunkStore chunkStore;
- private readonly IHasherPipelineStage? nextStage;
- private readonly IPostageStamper postageStamper;
-
- // Constructor.
- public ChunkStoreWriterPipelineStage(
- IChunkStore chunkStore,
- IPostageStamper postageStamper,
- IHasherPipelineStage? nextStage)
- {
- this.chunkStore = chunkStore;
- this.nextStage = nextStage;
- this.postageStamper = postageStamper;
- }
-
// Dispose.
public void Dispose()
{
nextStage?.Dispose();
}
+
+ // Properties.
+ public long MissedOptimisticHashing => nextStage?.MissedOptimisticHashing ?? 0;
// Methods.
public async Task FeedAsync(HasherPipelineFeedArgs args)
@@ -62,7 +53,7 @@ public async Task FeedAsync(HasherPipelineFeedArgs args)
await nextStage.FeedAsync(args).ConfigureAwait(false);
}
- public Task SumAsync() =>
+ public Task SumAsync() =>
nextStage?.SumAsync() ?? throw new InvalidOperationException();
}
}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/Pipeline/CompactedChunkAttemptResult.cs b/src/BeeNet.Util/Hashing/Pipeline/CompactedChunkAttemptResult.cs
new file mode 100644
index 00000000..df4ed468
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Pipeline/CompactedChunkAttemptResult.cs
@@ -0,0 +1,17 @@
+using Etherna.BeeNet.Manifest;
+using Etherna.BeeNet.Models;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Etherna.BeeNet.Hashing.Pipeline
+{
+ [SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
+ public class CompactedChunkAttemptResult(
+ XorEncryptKey chunkKey,
+ byte[] encryptedData,
+ SwarmHash hash)
+ {
+ public XorEncryptKey ChunkKey { get; } = chunkKey;
+ public byte[] EncryptedData { get; } = encryptedData;
+ public SwarmHash Hash { get; } = hash;
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/HasherPipelineBuilder.cs b/src/BeeNet.Util/Hashing/Pipeline/HasherPipelineBuilder.cs
similarity index 64%
rename from src/BeeNet/Hasher/Pipeline/HasherPipelineBuilder.cs
rename to src/BeeNet.Util/Hashing/Pipeline/HasherPipelineBuilder.cs
index 6d060ac2..73e4a490 100644
--- a/src/BeeNet/Hasher/Pipeline/HasherPipelineBuilder.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/HasherPipelineBuilder.cs
@@ -12,35 +12,43 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Postage;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Postage;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using System;
using System.Diagnostics.CodeAnalysis;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope")]
- internal static class HasherPipelineBuilder
+ public static class HasherPipelineBuilder
{
// Static builders.
public static IHasherPipeline BuildNewHasherPipeline(
IPostageStamper postageStamper,
RedundancyLevel redundancyLevel,
bool isEncrypted,
- string? chunkStoreDirectory) =>
+ string? chunkStoreDirectory,
+ ushort compactLevel,
+ int? chunkConcurrency) =>
BuildNewHasherPipeline(
chunkStoreDirectory is null ? new FakeChunkStore() : new LocalDirectoryChunkStore(chunkStoreDirectory),
postageStamper,
redundancyLevel,
- isEncrypted);
+ isEncrypted,
+ compactLevel,
+ chunkConcurrency);
public static IHasherPipeline BuildNewHasherPipeline(
IChunkStore chunkStore,
IPostageStamper postageStamper,
RedundancyLevel redundancyLevel,
- bool isEncrypted)
+ bool isEncrypted,
+ ushort compactLevel,
+ int? chunkConcurrency)
{
+ ArgumentNullException.ThrowIfNull(postageStamper, nameof(postageStamper));
+
if (redundancyLevel != RedundancyLevel.None)
throw new NotImplementedException();
@@ -52,29 +60,19 @@ public static IHasherPipeline BuildNewHasherPipeline(
else
{
//build stages
- var shortPipelineStage = BuildNewShortHasherPipeline(chunkStore, postageStamper);
-
var chunkAggregatorStage = new ChunkAggregatorPipelineStage(
- async (span, data) =>
- {
- var args = new HasherPipelineFeedArgs(span: span, data: data);
- await shortPipelineStage.FeedAsync(args).ConfigureAwait(false);
- return args.Hash!.Value;
- }
- );
+ new ChunkBmtPipelineStage(
+ compactLevel,
+ new ChunkStoreWriterPipelineStage(chunkStore, postageStamper, null),
+ postageStamper.StampIssuer),
+ compactLevel > 0);
+
var storeWriterStage = new ChunkStoreWriterPipelineStage(chunkStore, postageStamper, chunkAggregatorStage);
- bmtStage = new ChunkBmtPipelineStage(storeWriterStage);
+
+ bmtStage = new ChunkBmtPipelineStage(compactLevel, storeWriterStage, postageStamper.StampIssuer);
}
- return new ChunkFeederPipelineStage(bmtStage);
- }
-
- public static IHasherPipelineStage BuildNewShortHasherPipeline(
- IChunkStore chunkStore,
- IPostageStamper postageStamper)
- {
- var storeWriter = new ChunkStoreWriterPipelineStage(chunkStore, postageStamper, null);
- return new ChunkBmtPipelineStage(storeWriter);
+ return new ChunkFeederPipelineStage(bmtStage, chunkConcurrency);
}
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/HasherPipelineFeedArgs.cs b/src/BeeNet.Util/Hashing/Pipeline/HasherPipelineFeedArgs.cs
similarity index 69%
rename from src/BeeNet/Hasher/Pipeline/HasherPipelineFeedArgs.cs
rename to src/BeeNet.Util/Hashing/Pipeline/HasherPipelineFeedArgs.cs
index a712e9cd..dae12f22 100644
--- a/src/BeeNet/Hasher/Pipeline/HasherPipelineFeedArgs.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/HasherPipelineFeedArgs.cs
@@ -14,21 +14,25 @@
using Etherna.BeeNet.Models;
using System;
+using System.Threading;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
- internal class HasherPipelineFeedArgs
+ public sealed class HasherPipelineFeedArgs
{
// Fields.
- private readonly byte[] _data;
private readonly byte[]? _span;
+ private byte[] _data;
// Constructor.
public HasherPipelineFeedArgs(
byte[] data,
byte[]? span = null,
- long numberId = 0)
+ long numberId = 0,
+ SemaphoreSlim? prevChunkSemaphore = null)
{
+ ArgumentNullException.ThrowIfNull(data, nameof(data));
+
if (span is not null)
{
if (data.Length < SwarmChunk.SpanSize)
@@ -40,13 +44,23 @@ public HasherPipelineFeedArgs(
_data = data;
_span = span;
NumberId = numberId;
+ PrevChunkSemaphore = prevChunkSemaphore;
}
// Properties.
+ ///
+ /// The optional chunk encryption key
+ ///
+ public XorEncryptKey? ChunkKey { get; internal set; }
+
///
/// Data can include the span too, but it may be encrypted if the pipeline is encrypted
///
- public ReadOnlyMemory Data => _data;
+ public ReadOnlyMemory Data
+ {
+ get => _data;
+ internal set => _data = value.ToArray();
+ }
///
/// Hash generated by BMT
@@ -59,8 +73,13 @@ public HasherPipelineFeedArgs(
public ReadOnlyMemory Span => _span;
///
- /// Ordered Id, from 0 to n with the last chunk
+ /// Ordered id, from 0 to n with the last chunk
///
public long NumberId { get; }
+
+ ///
+ /// Previous chunk semaphore. Occuped resource until chunk is processing.
+ ///
+ public SemaphoreSlim? PrevChunkSemaphore { get; }
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/IHasherPipeline.cs b/src/BeeNet.Util/Hashing/Pipeline/IHasherPipeline.cs
similarity index 83%
rename from src/BeeNet/Hasher/Pipeline/IHasherPipeline.cs
rename to src/BeeNet.Util/Hashing/Pipeline/IHasherPipeline.cs
index 1da6b28a..40cf2a6e 100644
--- a/src/BeeNet/Hasher/Pipeline/IHasherPipeline.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/IHasherPipeline.cs
@@ -17,24 +17,28 @@
using System.IO;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
public interface IHasherPipeline : IDisposable
{
+ // Properties.
bool IsUsable { get; }
+ long MissedOptimisticHashing { get; }
+
+ // Methods.
///
/// Consume a byte array and returns a Swarm hash as result
///
/// Input data
/// Resulting swarm hash
- Task HashDataAsync(byte[] data);
+ Task HashDataAsync(byte[] data);
///
/// Consume a stream slicing it in chunk size parts, and returns a Swarm hash as result
///
/// Input data stream
/// Resulting swarm hash
- Task HashDataAsync(Stream dataStream);
+ Task HashDataAsync(Stream dataStream);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/IHasherPipelineStage.cs b/src/BeeNet.Util/Hashing/Pipeline/IHasherPipelineStage.cs
similarity index 78%
rename from src/BeeNet/Hasher/Pipeline/IHasherPipelineStage.cs
rename to src/BeeNet.Util/Hashing/Pipeline/IHasherPipelineStage.cs
index b03b11ca..d25e0385 100644
--- a/src/BeeNet/Hasher/Pipeline/IHasherPipelineStage.cs
+++ b/src/BeeNet.Util/Hashing/Pipeline/IHasherPipelineStage.cs
@@ -16,11 +16,15 @@
using System;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Pipeline
+namespace Etherna.BeeNet.Hashing.Pipeline
{
- internal interface IHasherPipelineStage : IDisposable
+ public interface IHasherPipelineStage : IDisposable
{
+ // Properties.
+ long MissedOptimisticHashing { get; }
+
+ // Methods.
Task FeedAsync(HasherPipelineFeedArgs args);
- Task SumAsync();
+ Task SumAsync();
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Postage/FakePostageStampIssuer.cs b/src/BeeNet.Util/Hashing/Postage/FakePostageStampIssuer.cs
similarity index 80%
rename from src/BeeNet/Hasher/Postage/FakePostageStampIssuer.cs
rename to src/BeeNet.Util/Hashing/Postage/FakePostageStampIssuer.cs
index bae9ab98..b50a2ed1 100644
--- a/src/BeeNet/Hasher/Postage/FakePostageStampIssuer.cs
+++ b/src/BeeNet.Util/Hashing/Postage/FakePostageStampIssuer.cs
@@ -13,22 +13,18 @@
// If not, see .
using Etherna.BeeNet.Models;
-using System;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
public class FakePostageStampIssuer : IPostageStampIssuer
{
- public ReadOnlySpan Buckets => Array.Empty();
+ public IReadOnlyPostageBuckets Buckets { get; } = new PostageBuckets();
public uint BucketUpperBound { get; }
public bool HasSaturated { get; }
public PostageBatch PostageBatch => PostageBatch.MaxDepthInstance;
- public uint MaxBucketCount { get; }
+ public uint MaxBucketCollisions { get; }
public long TotalChunks { get; }
- public StampBucketIndex IncrementBucketCount(SwarmHash hash) =>
- new StampBucketIndex(0, 0);
-
- public ulong GetCollisions(uint bucketId) => 0;
+ public StampBucketIndex IncrementBucketCount(SwarmHash hash) => new(0, 0);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Postage/FakePostageStamper.cs b/src/BeeNet.Util/Hashing/Postage/FakePostageStamper.cs
similarity index 91%
rename from src/BeeNet/Hasher/Postage/FakePostageStamper.cs
rename to src/BeeNet.Util/Hashing/Postage/FakePostageStamper.cs
index 8529c55f..bab0d284 100644
--- a/src/BeeNet/Hasher/Postage/FakePostageStamper.cs
+++ b/src/BeeNet.Util/Hashing/Postage/FakePostageStamper.cs
@@ -12,12 +12,12 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Signer;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Signer;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using System;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
public class FakePostageStamper : IPostageStamper
{
diff --git a/src/BeeNet/Hasher/Postage/IPostageStampIssuer.cs b/src/BeeNet.Util/Hashing/Postage/IPostageStampIssuer.cs
similarity index 66%
rename from src/BeeNet/Hasher/Postage/IPostageStampIssuer.cs
rename to src/BeeNet.Util/Hashing/Postage/IPostageStampIssuer.cs
index 4753f62b..fec10061 100644
--- a/src/BeeNet/Hasher/Postage/IPostageStampIssuer.cs
+++ b/src/BeeNet.Util/Hashing/Postage/IPostageStampIssuer.cs
@@ -13,40 +13,27 @@
// If not, see .
using Etherna.BeeNet.Models;
-using System;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
public interface IPostageStampIssuer
{
// Properties.
- ///
- /// Collision Buckets: counts per neighbourhoods
- ///
- public ReadOnlySpan Buckets { get; }
-
- public uint BucketUpperBound { get; }
+ IReadOnlyPostageBuckets Buckets { get; }
+
+ uint BucketUpperBound { get; }
///
/// True if batch is mutable and BucketUpperBound has been it
///
- public bool HasSaturated { get; }
+ bool HasSaturated { get; }
///
/// The batch stamps are issued from
///
- public PostageBatch PostageBatch { get; }
-
- ///
- /// The count of the fullest bucket
- ///
- public uint MaxBucketCount { get; }
-
- long TotalChunks { get; }
+ PostageBatch PostageBatch { get; }
// Methods.
StampBucketIndex IncrementBucketCount(SwarmHash hash);
-
- ulong GetCollisions(uint bucketId);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Postage/IPostageStamper.cs b/src/BeeNet.Util/Hashing/Postage/IPostageStamper.cs
similarity index 86%
rename from src/BeeNet/Hasher/Postage/IPostageStamper.cs
rename to src/BeeNet.Util/Hashing/Postage/IPostageStamper.cs
index 6f2fd454..dffdc200 100644
--- a/src/BeeNet/Hasher/Postage/IPostageStamper.cs
+++ b/src/BeeNet.Util/Hashing/Postage/IPostageStamper.cs
@@ -12,13 +12,13 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Signer;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Signer;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
- internal interface IPostageStamper
+ public interface IPostageStamper
{
// Properties.
ISigner Signer { get; }
diff --git a/src/BeeNet/Hasher/Postage/PostageStampIssuer.cs b/src/BeeNet.Util/Hashing/Postage/PostageStampIssuer.cs
similarity index 83%
rename from src/BeeNet/Hasher/Postage/PostageStampIssuer.cs
rename to src/BeeNet.Util/Hashing/Postage/PostageStampIssuer.cs
index b1ec918e..dd55036e 100644
--- a/src/BeeNet/Hasher/Postage/PostageStampIssuer.cs
+++ b/src/BeeNet.Util/Hashing/Postage/PostageStampIssuer.cs
@@ -15,7 +15,7 @@
using Etherna.BeeNet.Models;
using System;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
public class PostageStampIssuer : IPostageStampIssuer
{
@@ -25,26 +25,22 @@ public class PostageStampIssuer : IPostageStampIssuer
// Constructor.
public PostageStampIssuer(
PostageBatch postageBatch,
- uint[]? initialBuckets = null)
+ PostageBuckets? buckets = null)
{
ArgumentNullException.ThrowIfNull(postageBatch, nameof(postageBatch));
- _buckets = new PostageBuckets(initialBuckets);
+ _buckets = buckets ?? new PostageBuckets();
BucketUpperBound = (uint)1 << (postageBatch.Depth - PostageBatch.BucketDepth);
PostageBatch = postageBatch;
}
// Properties.
- public ReadOnlySpan Buckets => _buckets.Buckets;
+ public IReadOnlyPostageBuckets Buckets => _buckets;
public uint BucketUpperBound { get; }
public bool HasSaturated { get; private set; }
public PostageBatch PostageBatch { get; }
- public uint MaxBucketCount => _buckets.MaxBucketCount;
- public long TotalChunks => _buckets.TotalChunks;
// Methods.
- public ulong GetCollisions(uint bucketId) => _buckets.GetCollisions(bucketId);
-
public StampBucketIndex IncrementBucketCount(SwarmHash hash)
{
var bucketId = hash.ToBucketId();
diff --git a/src/BeeNet/Hasher/Postage/PostageStamper.cs b/src/BeeNet.Util/Hashing/Postage/PostageStamper.cs
similarity index 73%
rename from src/BeeNet/Hasher/Postage/PostageStamper.cs
rename to src/BeeNet.Util/Hashing/Postage/PostageStamper.cs
index 142bf7ed..ec877977 100644
--- a/src/BeeNet/Hasher/Postage/PostageStamper.cs
+++ b/src/BeeNet.Util/Hashing/Postage/PostageStamper.cs
@@ -12,22 +12,24 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Epoche;
using Etherna.BeeNet.Extensions;
-using Etherna.BeeNet.Hasher.Signer;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Signer;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
+using Org.BouncyCastle.Crypto.Digests;
using System;
-using System.Linq;
-namespace Etherna.BeeNet.Hasher.Postage
+namespace Etherna.BeeNet.Hashing.Postage
{
- internal class PostageStamper(
+ internal sealed class PostageStamper(
ISigner signer,
IPostageStampIssuer stampIssuer,
IStampStore stampStore)
: IPostageStamper
{
+ // Fields.
+ private readonly KeccakDigest hasher = new(256);
+
// Properties.
public ISigner Signer { get; } = signer;
public IPostageStampIssuer StampIssuer { get; } = stampIssuer;
@@ -76,11 +78,24 @@ public PostageStamp Stamp(SwarmHash hash)
///
///
///
- private static byte[] ToSignDigest(SwarmHash hash, PostageBatchId batchId, StampBucketIndex stampBucketIndex, DateTimeOffset timeStamp) =>
- Keccak256.ComputeHash(
- hash.ToByteArray()
- .Concat(batchId.ToByteArray())
- .Concat(stampBucketIndex.ToByteArray())
- .Concat(timeStamp.ToUnixTimeMilliseconds().UnixDateTimeToByteArray()).ToArray());
+ private byte[] ToSignDigest(
+ SwarmHash hash,
+ PostageBatchId batchId,
+ StampBucketIndex stampBucketIndex,
+ DateTimeOffset timeStamp)
+ {
+ var result = new byte[SwarmHash.HashSize];
+
+ lock (hasher)
+ {
+ hasher.BlockUpdate(hash.ToByteArray());
+ hasher.BlockUpdate(batchId.ToByteArray());
+ hasher.BlockUpdate(stampBucketIndex.ToByteArray());
+ hasher.BlockUpdate(timeStamp.ToUnixTimeMilliseconds().UnixDateTimeToByteArray());
+ hasher.DoFinal(result);
+ }
+
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Signer/FakeSigner.cs b/src/BeeNet.Util/Hashing/Signer/FakeSigner.cs
similarity index 95%
rename from src/BeeNet/Hasher/Signer/FakeSigner.cs
rename to src/BeeNet.Util/Hashing/Signer/FakeSigner.cs
index cc6f4746..d143a215 100644
--- a/src/BeeNet/Hasher/Signer/FakeSigner.cs
+++ b/src/BeeNet.Util/Hashing/Signer/FakeSigner.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-namespace Etherna.BeeNet.Hasher.Signer
+namespace Etherna.BeeNet.Hashing.Signer
{
public class FakeSigner : ISigner
{
diff --git a/src/BeeNet/Hasher/Signer/ISigner.cs b/src/BeeNet.Util/Hashing/Signer/ISigner.cs
similarity index 95%
rename from src/BeeNet/Hasher/Signer/ISigner.cs
rename to src/BeeNet.Util/Hashing/Signer/ISigner.cs
index 4c75c283..6c5672b4 100644
--- a/src/BeeNet/Hasher/Signer/ISigner.cs
+++ b/src/BeeNet.Util/Hashing/Signer/ISigner.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-namespace Etherna.BeeNet.Hasher.Signer
+namespace Etherna.BeeNet.Hashing.Signer
{
public interface ISigner
{
diff --git a/src/BeeNet/Models/ChequebookBalance.cs b/src/BeeNet.Util/Hashing/Store/BeeClientChunkStore.cs
similarity index 52%
rename from src/BeeNet/Models/ChequebookBalance.cs
rename to src/BeeNet.Util/Hashing/Store/BeeClientChunkStore.cs
index fa25e916..4b882d49 100644
--- a/src/BeeNet/Models/ChequebookBalance.cs
+++ b/src/BeeNet.Util/Hashing/Store/BeeClientChunkStore.cs
@@ -1,4 +1,4 @@
-// Copyright 2021-present Etherna SA
+// Copyright 2021-present Etherna SA
// This file is part of Bee.Net.
//
// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
@@ -12,24 +12,28 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Clients;
-using System;
+using Etherna.BeeNet.Exceptions;
+using Etherna.BeeNet.Models;
+using System.Threading.Tasks;
-namespace Etherna.BeeNet.Models
+namespace Etherna.BeeNet.Hashing.Store
{
- public sealed class ChequebookBalance
+ public class BeeClientChunkStore(IBeeClient beeClient)
+ : IReadOnlyChunkStore
{
- // Constructors.
- internal ChequebookBalance(Response27 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
+ public Task GetAsync(SwarmHash hash) =>
+ beeClient.GetChunkAsync(hash);
- TotalBalance = BzzBalance.FromPlurString(response.TotalBalance);
- AvailableBalance = BzzBalance.FromPlurString(response.AvailableBalance);
+ public async Task TryGetAsync(SwarmHash hash)
+ {
+ try
+ {
+ return await beeClient.GetChunkAsync(hash).ConfigureAwait(false);
+ }
+ catch (BeeNetApiException)
+ {
+ return null;
+ }
}
-
- // Properties.
- public BzzBalance TotalBalance { get; }
- public BzzBalance AvailableBalance { get; }
}
-}
+}
\ No newline at end of file
diff --git a/src/BeeNet.Util/Hashing/Store/ChunkJoiner.cs b/src/BeeNet.Util/Hashing/Store/ChunkJoiner.cs
new file mode 100644
index 00000000..82ddcfba
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Store/ChunkJoiner.cs
@@ -0,0 +1,116 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Models;
+using System;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Etherna.BeeNet.Hashing.Store
+{
+ public class ChunkJoiner(
+ IReadOnlyChunkStore chunkStore)
+ {
+ // Methods.
+ ///
+ /// Get data stream from chunks
+ ///
+ /// The root chunk reference
+ /// Optional file where store read data. Necessary if data is >2GB
+ /// Optional cancellation token
+ /// The data stream
+ public async Task GetJoinedChunkDataAsync(
+ SwarmChunkReference rootChunkReference,
+ string? fileCachePath = null,
+ CancellationToken? cancellationToken = default)
+ {
+ ArgumentNullException.ThrowIfNull(rootChunkReference, nameof(rootChunkReference));
+
+ //in memory
+ if (fileCachePath is null)
+ {
+ var dataStream = new MemoryStream();
+
+ await GetJoinedChunkDataHelperAsync(
+ rootChunkReference,
+ dataStream,
+ cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
+
+ dataStream.Position = 0;
+ return dataStream;
+ }
+
+ //file cached
+ using (var writeDataStream = File.OpenWrite(fileCachePath))
+ {
+ await GetJoinedChunkDataHelperAsync(
+ rootChunkReference,
+ writeDataStream,
+ cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
+
+ await writeDataStream.FlushAsync().ConfigureAwait(false);
+ }
+
+ return File.OpenRead(fileCachePath);
+ }
+
+ // Helpers.
+ private async Task GetJoinedChunkDataHelperAsync(
+ SwarmChunkReference chunkReference,
+ Stream dataStream,
+ CancellationToken cancellationToken)
+ {
+ // Read and decrypt chunk data.
+ var chunk = await chunkStore.GetAsync(chunkReference.Hash).ConfigureAwait(false);
+ var dataArray = chunk.Data.ToArray();
+ chunkReference.EncryptionKey?.EncryptDecrypt(dataArray);
+
+ // Determine if is a data chunk, or an intermediate chunk.
+ var totalDataLength = SwarmChunk.SpanToLength(chunk.Span.Span);
+
+ //if is data chunk
+ if (totalDataLength <= SwarmChunk.DataSize)
+ {
+ await dataStream.WriteAsync(dataArray, cancellationToken).ConfigureAwait(false);
+ return;
+ }
+
+ //else, is intermediate chunk
+ for (int i = 0; i < dataArray.Length;)
+ {
+ //read hash
+ var childHash = new SwarmHash(dataArray[i..(i + SwarmHash.HashSize)]);
+ i += SwarmHash.HashSize;
+
+ //read encryption key
+ XorEncryptKey? childEncryptionKey = null;
+ if (chunkReference.UseRecursiveEncryption)
+ {
+ childEncryptionKey = new XorEncryptKey(dataArray[i..(i + XorEncryptKey.KeySize)]);
+ i += XorEncryptKey.KeySize;
+ }
+
+ //add joined data recursively
+ await GetJoinedChunkDataHelperAsync(
+ new SwarmChunkReference(
+ childHash,
+ childEncryptionKey,
+ chunkReference.UseRecursiveEncryption),
+ dataStream,
+ cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Store/FakeChunkStore.cs b/src/BeeNet.Util/Hashing/Store/FakeChunkStore.cs
similarity index 85%
rename from src/BeeNet/Hasher/Store/FakeChunkStore.cs
rename to src/BeeNet.Util/Hashing/Store/FakeChunkStore.cs
index c2fc5325..5ee901c1 100644
--- a/src/BeeNet/Hasher/Store/FakeChunkStore.cs
+++ b/src/BeeNet.Util/Hashing/Store/FakeChunkStore.cs
@@ -13,17 +13,13 @@
// If not, see .
using Etherna.BeeNet.Models;
-using System;
using System.Collections.Generic;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
public class FakeChunkStore : IChunkStore
{
- public Task> GetAllHashesAsync() =>
- Task.FromResult>(Array.Empty());
-
public Task GetAsync(SwarmHash hash) =>
throw new KeyNotFoundException("Chunk get on a fake chunk store");
diff --git a/src/BeeNet/Hasher/Store/IChunkStore.cs b/src/BeeNet.Util/Hashing/Store/IChunkStore.cs
similarity index 77%
rename from src/BeeNet/Hasher/Store/IChunkStore.cs
rename to src/BeeNet.Util/Hashing/Store/IChunkStore.cs
index b071c4f0..05262da2 100644
--- a/src/BeeNet/Hasher/Store/IChunkStore.cs
+++ b/src/BeeNet.Util/Hashing/Store/IChunkStore.cs
@@ -13,19 +13,12 @@
// If not, see .
using Etherna.BeeNet.Models;
-using System.Collections.Generic;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
- public interface IChunkStore
+ public interface IChunkStore : IReadOnlyChunkStore
{
- public Task> GetAllHashesAsync();
-
- public Task GetAsync(SwarmHash hash);
-
- public Task TryGetAsync(SwarmHash hash);
-
///
/// Add a chunk in the store
///
diff --git a/src/BeeNet.Util/Hashing/Store/IReadOnlyChunkStore.cs b/src/BeeNet.Util/Hashing/Store/IReadOnlyChunkStore.cs
new file mode 100644
index 00000000..30761fa2
--- /dev/null
+++ b/src/BeeNet.Util/Hashing/Store/IReadOnlyChunkStore.cs
@@ -0,0 +1,26 @@
+// Copyright 2021-present Etherna SA
+// This file is part of Bee.Net.
+//
+// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
+// GNU Lesser General Public License as published by the Free Software Foundation,
+// either version 3 of the License, or (at your option) any later version.
+//
+// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+// See the GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
+// If not, see .
+
+using Etherna.BeeNet.Models;
+using System.Threading.Tasks;
+
+namespace Etherna.BeeNet.Hashing.Store
+{
+ public interface IReadOnlyChunkStore
+ {
+ public Task GetAsync(SwarmHash hash);
+
+ public Task TryGetAsync(SwarmHash hash);
+ }
+}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Store/IStampStore.cs b/src/BeeNet.Util/Hashing/Store/IStampStore.cs
similarity index 95%
rename from src/BeeNet/Hasher/Store/IStampStore.cs
rename to src/BeeNet.Util/Hashing/Store/IStampStore.cs
index 14d2ca32..2a515b27 100644
--- a/src/BeeNet/Hasher/Store/IStampStore.cs
+++ b/src/BeeNet.Util/Hashing/Store/IStampStore.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
public interface IStampStore
{
diff --git a/src/BeeNet/Hasher/Store/LocalDirectoryChunkStore.cs b/src/BeeNet.Util/Hashing/Store/LocalDirectoryChunkStore.cs
similarity index 99%
rename from src/BeeNet/Hasher/Store/LocalDirectoryChunkStore.cs
rename to src/BeeNet.Util/Hashing/Store/LocalDirectoryChunkStore.cs
index 3b709571..5a1b0cfb 100644
--- a/src/BeeNet/Hasher/Store/LocalDirectoryChunkStore.cs
+++ b/src/BeeNet.Util/Hashing/Store/LocalDirectoryChunkStore.cs
@@ -19,7 +19,7 @@
using System.IO;
using System.Threading.Tasks;
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
///
/// Store chunks in a local directory
diff --git a/src/BeeNet/Hasher/Store/MemoryStampStore.cs b/src/BeeNet.Util/Hashing/Store/MemoryStampStore.cs
similarity index 97%
rename from src/BeeNet/Hasher/Store/MemoryStampStore.cs
rename to src/BeeNet.Util/Hashing/Store/MemoryStampStore.cs
index d7fda209..e560fc66 100644
--- a/src/BeeNet/Hasher/Store/MemoryStampStore.cs
+++ b/src/BeeNet.Util/Hashing/Store/MemoryStampStore.cs
@@ -15,7 +15,7 @@
using System;
using System.Collections.Concurrent;
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
public class MemoryStampStore : IStampStore
{
diff --git a/src/BeeNet/Hasher/Store/StampStoreItem.cs b/src/BeeNet.Util/Hashing/Store/StampStoreItem.cs
similarity index 94%
rename from src/BeeNet/Hasher/Store/StampStoreItem.cs
rename to src/BeeNet.Util/Hashing/Store/StampStoreItem.cs
index 42d7575a..e864e6eb 100644
--- a/src/BeeNet/Hasher/Store/StampStoreItem.cs
+++ b/src/BeeNet.Util/Hashing/Store/StampStoreItem.cs
@@ -12,11 +12,10 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Postage;
using Etherna.BeeNet.Models;
using System;
-namespace Etherna.BeeNet.Hasher.Store
+namespace Etherna.BeeNet.Hashing.Store
{
public class StampStoreItem(
PostageBatchId batchId,
diff --git a/src/BeeNet/IBeeClient.cs b/src/BeeNet.Util/IBeeClient.cs
similarity index 96%
rename from src/BeeNet/IBeeClient.cs
rename to src/BeeNet.Util/IBeeClient.cs
index 5e3cf65a..df2fd1b3 100644
--- a/src/BeeNet/IBeeClient.cs
+++ b/src/BeeNet.Util/IBeeClient.cs
@@ -36,9 +36,9 @@ public interface IBeeClient
Task> AccountingAsync(CancellationToken cancellationToken = default);
/// Authenticate - This endpoint is experimental
- /// Ok
+ /// Auth key
/// A server side error occurred.
- Task AuthenticateAsync(string role, int expiry);
+ Task AuthenticateAsync(string role, int expiry);
/// Buy a new postage batch.
/// Amount of BZZ added that the postage batch will have.
@@ -79,14 +79,6 @@ Task CheckChunkExistsAsync(
SwarmHash hash,
CancellationToken cancellationToken = default);
- /// Check if content is available
- /// Root hash of content (can be of any type: collection, file, chunk)
- /// Returns if the content is retrievable
- /// A server side error occurred.
- Task CheckIsContentAvailableAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default);
-
///
/// Validate pinned chunks integerity
///
@@ -123,9 +115,8 @@ Task CreateFeedAsync(
/// Pin the root hash with the given reference
/// Swarm reference of the root hash
- /// Pin already exists, so no operation
/// A server side error occurred.
- Task CreatePinAsync(
+ Task CreatePinAsync(
SwarmHash hash,
CancellationToken cancellationToken = default);
@@ -137,17 +128,15 @@ Task CreateTagAsync(
/// Remove peer
/// Swarm address of peer
- /// Disconnected peer
/// A server side error occurred.
- Task DeletePeerAsync(
+ Task DeletePeerAsync(
string peerAddress,
CancellationToken cancellationToken = default);
/// Unpin the root hash with the given reference
/// Swarm reference of the root hash
- /// Unpinning root hash with reference
/// A server side error occurred.
- Task DeletePinAsync(
+ Task DeletePinAsync(
SwarmHash hash,
CancellationToken cancellationToken = default);
@@ -174,7 +163,7 @@ Task DeleteTransactionAsync(
/// Gas price for transaction
/// Transaction hash of the deposit transaction
/// A server side error occurred.
- Task DepositIntoChequeBookAsync(
+ Task DepositIntoChequebookAsync(
BzzBalance amount,
XDaiBalance? gasPrice = null,
CancellationToken cancellationToken = default);
@@ -199,17 +188,17 @@ Task DilutePostageBatchAsync(
/// Get the balances with all known peers including prepaid services
/// Own balances with all known peers
/// A server side error occurred.
- Task> GetAllBalancesAsync(CancellationToken cancellationToken = default);
+ Task> GetAllBalancesAsync(CancellationToken cancellationToken = default);
/// Get last cheques for all peers
/// Last cheques
/// A server side error occurred.
- Task> GetAllChequeBookChequesAsync(CancellationToken cancellationToken = default);
+ Task> GetAllChequebookChequesAsync(CancellationToken cancellationToken = default);
/// Get the past due consumption balances with all known peers
/// Own past due consumption balances with all known peers
/// A server side error occurred.
- Task> GetAllConsumedBalancesAsync(CancellationToken cancellationToken = default);
+ Task> GetAllConsumedBalancesAsync(CancellationToken cancellationToken = default);
/// Get a list of peers
/// Returns overlay addresses of connected peers
@@ -235,15 +224,15 @@ Task DilutePostageBatchAsync(
/// Get all globally available batches that were purchased by all nodes.
///
///
- /// Returns an array of all available and currently valid postage batches.
+ /// Returns a dictionary with owner as keys, and enumerable of currently valid owned postage batches as values.
/// A server side error occurred.
- Task> GetAllValidPostageBatchesFromAllNodesAsync(CancellationToken cancellationToken = default);
+ Task>> GetAllValidPostageBatchesFromAllNodesAsync(CancellationToken cancellationToken = default);
/// Get the balances with a specific peer including prepaid services
/// Swarm address of peer
/// Balance with the specific peer
/// A server side error occurred.
- Task GetBalanceWithPeerAsync(
+ Task GetBalanceWithPeerAsync(
string peerAddress,
CancellationToken cancellationToken = default);
@@ -284,18 +273,18 @@ Task GetBytesAsync(
/// Get the address of the chequebook contract used
/// Ethereum address of chequebook contract
/// A server side error occurred.
- Task GetChequeBookAddressAsync(CancellationToken cancellationToken = default);
+ Task GetChequebookAddressAsync(CancellationToken cancellationToken = default);
/// Get the balance of the chequebook
/// Balance of the chequebook
/// A server side error occurred.
- Task GetChequeBookBalanceAsync(CancellationToken cancellationToken = default);
+ Task GetChequebookBalanceAsync(CancellationToken cancellationToken = default);
/// Get last cashout action for the peer
/// Swarm address of peer
/// Cashout status
/// A server side error occurred.
- Task GetChequeBookCashoutForPeerAsync(
+ Task GetChequebookCashoutForPeerAsync(
string peerAddress,
CancellationToken cancellationToken = default);
@@ -303,7 +292,7 @@ Task GetChequeBookCashoutForPeerAsync(
/// Swarm address of peer
/// Last cheques
/// A server side error occurred.
- Task GetChequeBookChequeForPeerAsync(
+ Task GetChequebookChequeForPeerAsync(
string peerId,
CancellationToken cancellationToken = default);
@@ -329,7 +318,7 @@ Task GetChunkStreamAsync(
/// Swarm address of peer
/// Past-due consumption balance with the specific peer
/// A server side error occurred.
- Task GetConsumedBalanceWithPeerAsync(
+ Task GetConsumedBalanceWithPeerAsync(
string peerAddress,
CancellationToken cancellationToken = default);
@@ -357,7 +346,7 @@ Task GetFeedAsync(
/// Specify the timeout for chunk retrieval. The default is 30 seconds.
/// Ok
/// A server side error occurred.
- Task GetFileAsync(
+ Task GetFileAsync(
SwarmAddress address,
bool? swarmCache = null,
RedundancyStrategy? swarmRedundancyStrategy = null,
@@ -482,13 +471,21 @@ Task GetTransactionInfoAsync(
/// Get wallet balance for BZZ and xDai
///
/// Wallet balance info
- Task GetWalletBalance(CancellationToken cancellationToken = default);
+ Task GetWalletBalance(CancellationToken cancellationToken = default);
/// Get configured P2P welcome message
/// Welcome message
/// A server side error occurred.
Task GetWelcomeMessageAsync(CancellationToken cancellationToken = default);
+ /// Check if content is retrievable
+ /// Root hash of content (can be of any type: collection, file, chunk)
+ /// Returns if the content is retrievable
+ /// A server side error occurred.
+ Task IsContentRetrievableAsync(
+ SwarmHash hash,
+ CancellationToken cancellationToken = default);
+
/// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
///
/// Get all available loggers.
@@ -539,6 +536,8 @@ Task RefreshAuthAsync(
int expiry,
CancellationToken cancellationToken = default);
+ Task ResolveAddressToChunkReferenceAsync(SwarmAddress address);
+
/// Reupload a root hash to the network
/// Root hash of content (can be of any type: collection, file, chunk)
/// Ok
@@ -809,7 +808,7 @@ Task WalletWithdrawAsync(
/// Gas price for transaction
/// Transaction hash of the withdraw transaction
/// A server side error occurred.
- Task WithdrawFromChequeBookAsync(
+ Task WithdrawFromChequebookAsync(
BzzBalance amount,
XDaiBalance? gasPrice = null,
CancellationToken cancellationToken = default);
diff --git a/src/BeeNet/Manifest/IReadOnlyMantarayManifest.cs b/src/BeeNet.Util/Manifest/IReadOnlyMantarayManifest.cs
similarity index 100%
rename from src/BeeNet/Manifest/IReadOnlyMantarayManifest.cs
rename to src/BeeNet.Util/Manifest/IReadOnlyMantarayManifest.cs
diff --git a/src/BeeNet/Manifest/IReadOnlyMantarayNode.cs b/src/BeeNet.Util/Manifest/IReadOnlyMantarayNode.cs
similarity index 94%
rename from src/BeeNet/Manifest/IReadOnlyMantarayNode.cs
rename to src/BeeNet.Util/Manifest/IReadOnlyMantarayNode.cs
index 9861ed48..0a70e52f 100644
--- a/src/BeeNet/Manifest/IReadOnlyMantarayNode.cs
+++ b/src/BeeNet.Util/Manifest/IReadOnlyMantarayNode.cs
@@ -29,6 +29,6 @@ public interface IReadOnlyMantarayNode
// Methods.
Task> GetResourceMetadataAsync(string path);
- Task ResolveResourceHashAsync(string path);
+ Task ResolveChunkReferenceAsync(string path);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Manifest/ManifestEntry.cs b/src/BeeNet.Util/Manifest/ManifestEntry.cs
similarity index 93%
rename from src/BeeNet/Manifest/ManifestEntry.cs
rename to src/BeeNet.Util/Manifest/ManifestEntry.cs
index dfe06acb..e1071908 100644
--- a/src/BeeNet/Manifest/ManifestEntry.cs
+++ b/src/BeeNet.Util/Manifest/ManifestEntry.cs
@@ -20,10 +20,12 @@ namespace Etherna.BeeNet.Manifest
public class ManifestEntry
{
// Consts.
+ public const string ChunkEncryptKeyKey = "ChunkEncryptKey";
public const string ContentTypeKey = "Content-Type";
public const string FilenameKey = "Filename";
public const string WebsiteErrorDocPathKey = "website-error-document";
public const string WebsiteIndexDocPathKey = "website-index-document";
+ public const string UseRecursiveEncryptionKey = "recursiveEncrypt";
// Constructor.
private ManifestEntry(
diff --git a/src/BeeNet/Manifest/MantarayManifest.cs b/src/BeeNet.Util/Manifest/MantarayManifest.cs
similarity index 80%
rename from src/BeeNet/Manifest/MantarayManifest.cs
rename to src/BeeNet.Util/Manifest/MantarayManifest.cs
index 13b8161e..aa68674a 100644
--- a/src/BeeNet/Manifest/MantarayManifest.cs
+++ b/src/BeeNet.Util/Manifest/MantarayManifest.cs
@@ -12,25 +12,27 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Pipeline;
+using Etherna.BeeNet.Hashing.Pipeline;
using Etherna.BeeNet.Models;
using System;
using System.Threading.Tasks;
namespace Etherna.BeeNet.Manifest
{
+ public delegate IHasherPipeline BuildHasherPipeline();
+
public class MantarayManifest : IReadOnlyMantarayManifest
{
// Consts.
- public const string RootPath = "/";
+ public static readonly string RootPath = SwarmAddress.Separator.ToString();
// Fields.
- private readonly Func hasherBuilder;
+ private readonly BuildHasherPipeline hasherBuilder;
private readonly MantarayNode _rootNode;
// Constructors.
public MantarayManifest(
- Func hasherBuilder,
+ BuildHasherPipeline hasherBuilder,
bool isEncrypted)
: this(hasherBuilder,
new MantarayNode(isEncrypted
@@ -39,7 +41,7 @@ public MantarayManifest(
{ }
public MantarayManifest(
- Func hasherBuilder,
+ BuildHasherPipeline hasherBuilder,
MantarayNode rootNode)
{
this.hasherBuilder = hasherBuilder;
@@ -58,10 +60,10 @@ public void Add(string path, ManifestEntry entry)
_rootNode.Add(path, entry);
}
- public async Task GetHashAsync()
+ public async Task GetHashAsync()
{
await _rootNode.ComputeHashAsync(hasherBuilder).ConfigureAwait(false);
- return _rootNode.Hash;
+ return new SwarmChunkReference(_rootNode.Hash, null, false);
}
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Manifest/MantarayNode.cs b/src/BeeNet.Util/Manifest/MantarayNode.cs
similarity index 94%
rename from src/BeeNet/Manifest/MantarayNode.cs
rename to src/BeeNet.Util/Manifest/MantarayNode.cs
index 83663ea7..fa62f486 100644
--- a/src/BeeNet/Manifest/MantarayNode.cs
+++ b/src/BeeNet.Util/Manifest/MantarayNode.cs
@@ -12,9 +12,8 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Epoche;
using Etherna.BeeNet.Extensions;
-using Etherna.BeeNet.Hasher.Pipeline;
+using Etherna.BeeNet.Hashing;
using Etherna.BeeNet.Models;
using System;
using System.Collections.Generic;
@@ -27,9 +26,8 @@ public class MantarayNode : IReadOnlyMantarayNode
{
// Consts.
public const int ForksIndexSize = 32;
- public const char PathSeparator = '/';
- public static readonly byte[] Version02Hash =
- Keccak256.ComputeHash("mantaray:0.2").Take(VersionHashSize).ToArray();
+ public static readonly byte[] Version02Hash = new Hasher().ComputeHash(
+ "mantaray:0.2"u8.ToArray()).Take(VersionHashSize).ToArray();
public const int VersionHashSize = 31;
// Fields.
@@ -144,7 +142,7 @@ public void Add(string path, ManifestEntry entry)
}
}
- public async Task ComputeHashAsync(Func hasherPipelineBuilder)
+ public async Task ComputeHashAsync(BuildHasherPipeline hasherPipelineBuilder)
{
ArgumentNullException.ThrowIfNull(hasherPipelineBuilder, nameof(hasherPipelineBuilder));
@@ -157,7 +155,8 @@ public async Task ComputeHashAsync(Func hasherPipelineBuilder)
// Marshal current node, and set its hash.
using var hasherPipeline = hasherPipelineBuilder();
- _hash = await hasherPipeline.HashDataAsync(ToByteArray()).ConfigureAwait(false);
+ var hashingResult = await hasherPipeline.HashDataAsync(ToByteArray()).ConfigureAwait(false);
+ _hash = hashingResult.Hash;
// Clean forks.
_forks.Clear();
@@ -195,7 +194,7 @@ public Task> GetResourceMetadataAsync(string
throw new NotImplementedException();
}
- public Task ResolveResourceHashAsync(string path)
+ public Task ResolveChunkReferenceAsync(string path)
{
//this will be implemented probably into a base class
throw new NotImplementedException();
@@ -231,7 +230,7 @@ private byte[] ToByteArray()
private void UpdateFlagIsWithPathSeparator(string path)
{
- if (path.IndexOf(PathSeparator, StringComparison.InvariantCulture) > 0)
+ if (path.IndexOf(SwarmAddress.Separator, StringComparison.InvariantCulture) > 0)
SetNodeTypeFlag(NodeType.WithPathSeparator);
else
RemoveNodeTypeFlag(NodeType.WithPathSeparator);
diff --git a/src/BeeNet/Manifest/MantarayNodeFork.cs b/src/BeeNet.Util/Manifest/MantarayNodeFork.cs
similarity index 100%
rename from src/BeeNet/Manifest/MantarayNodeFork.cs
rename to src/BeeNet.Util/Manifest/MantarayNodeFork.cs
diff --git a/src/BeeNet/Manifest/NodeType.cs b/src/BeeNet.Util/Manifest/NodeType.cs
similarity index 100%
rename from src/BeeNet/Manifest/NodeType.cs
rename to src/BeeNet.Util/Manifest/NodeType.cs
diff --git a/src/BeeNet/Manifest/ReferencedMantarayManifest.cs b/src/BeeNet.Util/Manifest/ReferencedMantarayManifest.cs
similarity index 80%
rename from src/BeeNet/Manifest/ReferencedMantarayManifest.cs
rename to src/BeeNet.Util/Manifest/ReferencedMantarayManifest.cs
index c8ad660a..97a2fc90 100644
--- a/src/BeeNet/Manifest/ReferencedMantarayManifest.cs
+++ b/src/BeeNet.Util/Manifest/ReferencedMantarayManifest.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -26,7 +26,7 @@ public class ReferencedMantarayManifest : IReadOnlyMantarayManifest
// Constructors.
public ReferencedMantarayManifest(
- IChunkStore chunkStore,
+ IReadOnlyChunkStore chunkStore,
SwarmHash rootHash)
{
_rootNode = new ReferencedMantarayNode(chunkStore, rootHash, null, NodeType.Edge);
@@ -43,17 +43,15 @@ public async Task> GetResourceMetadataAsync(
if (!_rootNode.IsDecoded)
await _rootNode.DecodeFromChunkAsync().ConfigureAwait(false);
- return await RootNode.GetResourceMetadataAsync(
- address.RelativePath?.ToString() ?? "").ConfigureAwait(false);
+ return await RootNode.GetResourceMetadataAsync(address.Path).ConfigureAwait(false);
}
- public async Task ResolveResourceHashAsync(SwarmAddress address)
+ public async Task ResolveAddressToChunkReferenceAsync(SwarmAddress address)
{
if (!_rootNode.IsDecoded)
await _rootNode.DecodeFromChunkAsync().ConfigureAwait(false);
- return await RootNode.ResolveResourceHashAsync(
- address.RelativePath?.ToString() ?? "").ConfigureAwait(false);
+ return await RootNode.ResolveChunkReferenceAsync(address.Path).ConfigureAwait(false);
}
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Manifest/ReferencedMantarayNode.cs b/src/BeeNet.Util/Manifest/ReferencedMantarayNode.cs
similarity index 84%
rename from src/BeeNet/Manifest/ReferencedMantarayNode.cs
rename to src/BeeNet.Util/Manifest/ReferencedMantarayNode.cs
index 1b76c02b..6486ecfa 100644
--- a/src/BeeNet/Manifest/ReferencedMantarayNode.cs
+++ b/src/BeeNet.Util/Manifest/ReferencedMantarayNode.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using Newtonsoft.Json;
using System;
@@ -26,7 +26,7 @@ namespace Etherna.BeeNet.Manifest
public class ReferencedMantarayNode : IReadOnlyMantarayNode
{
// Fields.
- private readonly IChunkStore chunkStore;
+ private readonly IReadOnlyChunkStore chunkStore;
private SwarmHash? _entryHash;
private readonly Dictionary _forks = new();
private readonly Dictionary _metadata;
@@ -34,7 +34,7 @@ public class ReferencedMantarayNode : IReadOnlyMantarayNode
// Constructor.
public ReferencedMantarayNode(
- IChunkStore chunkStore,
+ IReadOnlyChunkStore chunkStore,
SwarmHash chunkHash,
Dictionary? metadata,
NodeType nodeTypeFlags)
@@ -43,12 +43,20 @@ public ReferencedMantarayNode(
Hash = chunkHash;
_metadata = metadata ?? new Dictionary();
NodeTypeFlags = nodeTypeFlags;
+
+ // Read metadata.
+ if (_metadata.TryGetValue(ManifestEntry.ChunkEncryptKeyKey, out var encryptKeyStr))
+ EntryEncryptionKey = new XorEncryptKey(encryptKeyStr);
+ if (_metadata.TryGetValue(ManifestEntry.UseRecursiveEncryptionKey, out var useRecursiveEncrypStr))
+ EntryUseRecursiveEncryption = bool.Parse(useRecursiveEncrypStr);
}
// Properties.
+ public XorEncryptKey? EntryEncryptionKey { get; }
public SwarmHash? EntryHash => IsDecoded
? _entryHash
: throw new InvalidOperationException("Node is not decoded from chunk");
+ public bool EntryUseRecursiveEncryption { get; }
public IReadOnlyDictionary Forks => IsDecoded
? _forks
: throw new InvalidOperationException("Node is not decoded from chunk");
@@ -94,17 +102,17 @@ public async Task> GetResourceMetadataAsync(
ArgumentNullException.ThrowIfNull(path, nameof(path));
// If the path is empty
- if (path.Length == 0)
+ if (path.Length == 0 || path == SwarmAddress.Separator.ToString())
{
//try to lookup for index document suffix
- if (!_forks.TryGetValue('/', out var rootFork) ||
- rootFork.Prefix != "/")
+ if (!_forks.TryGetValue(SwarmAddress.Separator, out var rootFork) ||
+ rootFork.Prefix != SwarmAddress.Separator.ToString())
throw new KeyNotFoundException($"Final path {path} can't be found");
- if (!rootFork.Node.Metadata.TryGetValue(ManifestEntry.WebsiteIndexDocPathKey, out var suffix))
+ if (!rootFork.Node.Metadata.TryGetValue(ManifestEntry.WebsiteIndexDocPathKey, out var indexDocPat))
throw new KeyNotFoundException($"Index document can't be found");
- path += suffix;
+ path = indexDocPat;
}
// Find the child fork.
@@ -124,26 +132,29 @@ public async Task> GetResourceMetadataAsync(
return await fork.Node.GetResourceMetadataAsync(childSubPath).ConfigureAwait(false);
}
- public async Task ResolveResourceHashAsync(string path)
+ public async Task ResolveChunkReferenceAsync(string path)
{
ArgumentNullException.ThrowIfNull(path, nameof(path));
// If the path is empty
- if (path.Length == 0)
+ if (path.Length == 0 || path == SwarmAddress.Separator.ToString())
{
//if entry is not null, return it
if (EntryHash.HasValue && EntryHash != SwarmHash.Zero)
- return EntryHash.Value;
+ return new SwarmChunkReference(
+ EntryHash.Value,
+ EntryEncryptionKey,
+ EntryUseRecursiveEncryption);
//try to lookup for index document suffix
- if (!_forks.TryGetValue('/', out var rootFork) ||
- rootFork.Prefix != "/")
+ if (!_forks.TryGetValue(SwarmAddress.Separator, out var rootFork) ||
+ rootFork.Prefix != SwarmAddress.Separator.ToString())
throw new KeyNotFoundException($"Final path {path} can't be found");
- if (!rootFork.Node.Metadata.TryGetValue(ManifestEntry.WebsiteIndexDocPathKey, out var suffix))
+ if (!rootFork.Node.Metadata.TryGetValue(ManifestEntry.WebsiteIndexDocPathKey, out var indexDocPat))
throw new KeyNotFoundException($"Index document can't be found");
- path += suffix;
+ path = indexDocPat;
}
// Find the child fork.
@@ -154,7 +165,7 @@ public async Task ResolveResourceHashAsync(string path)
if (!fork.Node.IsDecoded)
await fork.Node.DecodeFromChunkAsync().ConfigureAwait(false);
- return await fork.Node.ResolveResourceHashAsync(path[fork.Prefix.Length..]).ConfigureAwait(false);
+ return await fork.Node.ResolveChunkReferenceAsync(path[fork.Prefix.Length..]).ConfigureAwait(false);
}
// Helpers.
diff --git a/src/BeeNet/Manifest/ReferencedMantarayNodeFork.cs b/src/BeeNet.Util/Manifest/ReferencedMantarayNodeFork.cs
similarity index 100%
rename from src/BeeNet/Manifest/ReferencedMantarayNodeFork.cs
rename to src/BeeNet.Util/Manifest/ReferencedMantarayNodeFork.cs
diff --git a/src/BeeNet/Properties/AssemblyInfo.cs b/src/BeeNet.Util/Properties/AssemblyInfo.cs
similarity index 89%
rename from src/BeeNet/Properties/AssemblyInfo.cs
rename to src/BeeNet.Util/Properties/AssemblyInfo.cs
index 8bf40376..ae2d241d 100644
--- a/src/BeeNet/Properties/AssemblyInfo.cs
+++ b/src/BeeNet.Util/Properties/AssemblyInfo.cs
@@ -12,8 +12,6 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using System;
using System.Runtime.CompilerServices;
-[assembly: CLSCompliant(false)]
-[assembly: InternalsVisibleTo("BeeNet.Tests")]
\ No newline at end of file
+[assembly: InternalsVisibleTo("BeeNet.Util.UnitTest")]
\ No newline at end of file
diff --git a/src/BeeNet/Services/CalculatorService.cs b/src/BeeNet.Util/Services/CalculatorService.cs
similarity index 58%
rename from src/BeeNet/Services/CalculatorService.cs
rename to src/BeeNet.Util/Services/CalculatorService.cs
index 7920a9b7..9d4f6e8a 100644
--- a/src/BeeNet/Services/CalculatorService.cs
+++ b/src/BeeNet.Util/Services/CalculatorService.cs
@@ -12,16 +12,16 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Pipeline;
-using Etherna.BeeNet.Hasher.Postage;
-using Etherna.BeeNet.Hasher.Signer;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Pipeline;
+using Etherna.BeeNet.Hashing.Postage;
+using Etherna.BeeNet.Hashing.Signer;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Manifest;
using Etherna.BeeNet.Models;
using System;
using System.Collections.Generic;
using System.IO;
-using System.Linq;
+using System.Threading;
using System.Threading.Tasks;
namespace Etherna.BeeNet.Services
@@ -32,13 +32,15 @@ public async Task EvaluateDirectoryUploadAsync(
string directoryPath,
string? indexFilename = null,
string? errorFilename = null,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null)
{
// Checks.
- if (indexFilename?.Contains('/', StringComparison.InvariantCulture) == true)
+ if (indexFilename?.Contains(SwarmAddress.Separator, StringComparison.InvariantCulture) == true)
throw new ArgumentException(
"Index document suffix must not include slash character",
nameof(indexFilename));
@@ -51,6 +53,8 @@ public async Task EvaluateDirectoryUploadAsync(
new FakeSigner(),
postageStampIssuer,
new MemoryStampStore());
+
+ long totalMissedOptimisticHashing = 0;
// Try set index document.
if (indexFilename is null &&
@@ -63,7 +67,9 @@ public async Task EvaluateDirectoryUploadAsync(
chunkStore,
postageStamper,
redundancyLevel,
- encrypt),
+ encrypt,
+ 0,
+ chunkCuncorrency),
encrypt);
// Iterate through the files in the supplied directory.
@@ -77,22 +83,33 @@ public async Task EvaluateDirectoryUploadAsync(
chunkStore,
postageStamper,
redundancyLevel,
- encrypt);
+ encrypt,
+ compactLevel,
+ chunkCuncorrency);
var fileContentType = FileContentTypeProvider.GetContentType(file);
var fileName = Path.GetFileName(file);
using var fileStream = File.OpenRead(file);
- var fileHash = await fileHasherPipeline.HashDataAsync(fileStream).ConfigureAwait(false);
+ var fileHashingResult = await fileHasherPipeline.HashDataAsync(fileStream).ConfigureAwait(false);
+ totalMissedOptimisticHashing += fileHasherPipeline.MissedOptimisticHashing;
// Add file entry to dir manifest.
+ var fileEntryMetadata = new Dictionary
+ {
+ [ManifestEntry.ContentTypeKey] = fileContentType,
+ [ManifestEntry.FilenameKey] = fileName
+ };
+ if (fileHashingResult.EncryptionKey != null)
+ fileEntryMetadata.Add(ManifestEntry.ChunkEncryptKeyKey, fileHashingResult.EncryptionKey.ToString());
+ if (compactLevel > 0)
+ fileEntryMetadata.Add(ManifestEntry.UseRecursiveEncryptionKey, true.ToString());
+
dirManifest.Add(
Path.GetRelativePath(directoryPath, file),
- ManifestEntry.NewFile(fileHash, new Dictionary
- {
- [ManifestEntry.ContentTypeKey] = fileContentType,
- [ManifestEntry.FilenameKey] = fileName
- }));
+ ManifestEntry.NewFile(
+ fileHashingResult.Hash,
+ fileEntryMetadata));
}
// Store website information.
@@ -111,11 +128,12 @@ public async Task EvaluateDirectoryUploadAsync(
}
// Get manifest hash.
- var manifestHash = await dirManifest.GetHashAsync().ConfigureAwait(false);
+ var chunkHashingResult = await dirManifest.GetHashAsync().ConfigureAwait(false);
// Return result.
return new UploadEvaluationResult(
- manifestHash,
+ chunkHashingResult.Hash,
+ totalMissedOptimisticHashing,
postageStampIssuer);
}
@@ -123,9 +141,11 @@ public async Task EvaluateFileUploadAsync(
byte[] data,
string fileContentType,
string? fileName,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null)
{
using var stream = new MemoryStream(data);
@@ -133,9 +153,11 @@ public async Task EvaluateFileUploadAsync(
stream,
fileContentType,
fileName,
+ compactLevel,
encrypt,
redundancyLevel,
postageStampIssuer,
+ chunkCuncorrency,
chunkStore).ConfigureAwait(false);
}
@@ -143,9 +165,11 @@ public async Task EvaluateFileUploadAsync(
Stream stream,
string fileContentType,
string? fileName,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null)
{
chunkStore ??= new FakeChunkStore();
@@ -161,9 +185,11 @@ public async Task EvaluateFileUploadAsync(
chunkStore,
postageStamper,
redundancyLevel,
- encrypt);
- var fileHash = await fileHasherPipeline.HashDataAsync(stream).ConfigureAwait(false);
- fileName ??= fileHash.ToString(); //if missing, set file name with its address
+ encrypt,
+ compactLevel,
+ chunkCuncorrency);
+ var fileHashingResult = await fileHasherPipeline.HashDataAsync(stream).ConfigureAwait(false);
+ fileName ??= fileHashingResult.Hash.ToString(); //if missing, set file name with its address
// Create manifest.
var manifest = new MantarayManifest(
@@ -171,7 +197,9 @@ public async Task EvaluateFileUploadAsync(
chunkStore,
postageStamper,
redundancyLevel,
- encrypt),
+ encrypt,
+ 0,
+ chunkCuncorrency),
encrypt);
manifest.Add(
@@ -181,26 +209,33 @@ public async Task EvaluateFileUploadAsync(
{
[ManifestEntry.WebsiteIndexDocPathKey] = fileName,
}));
+
+ var fileEntryMetadata = new Dictionary
+ {
+ [ManifestEntry.ContentTypeKey] = fileContentType,
+ [ManifestEntry.FilenameKey] = fileName
+ };
+ if (fileHashingResult.EncryptionKey != null)
+ fileEntryMetadata.Add(ManifestEntry.ChunkEncryptKeyKey, fileHashingResult.EncryptionKey.ToString());
+ if (compactLevel > 0)
+ fileEntryMetadata.Add(ManifestEntry.UseRecursiveEncryptionKey, true.ToString());
manifest.Add(
fileName,
ManifestEntry.NewFile(
- fileHash,
- new Dictionary
- {
- [ManifestEntry.ContentTypeKey] = fileContentType,
- [ManifestEntry.FilenameKey] = fileName
- }));
+ fileHashingResult.Hash,
+ fileEntryMetadata));
- var manifestHash = await manifest.GetHashAsync().ConfigureAwait(false);
+ var chunkHashingResult = await manifest.GetHashAsync().ConfigureAwait(false);
// Return result.
return new UploadEvaluationResult(
- manifestHash,
+ chunkHashingResult.Hash,
+ fileHasherPipeline.MissedOptimisticHashing,
postageStampIssuer);
}
- public async Task> GetResourceMetadataFromChunksAsync(
+ public async Task> GetFileMetadataFromChunksAsync(
string chunkStoreDirectory,
SwarmAddress address)
{
@@ -213,9 +248,11 @@ public async Task> GetResourceMetadataFromCh
return await rootManifest.GetResourceMetadataAsync(address).ConfigureAwait(false);
}
- public async Task GetResourceStreamFromChunksAsync(
+ public async Task GetFileStreamFromChunksAsync(
string chunkStoreDirectory,
- SwarmAddress address)
+ SwarmAddress address,
+ string? fileCachePath = null,
+ CancellationToken? cancellationToken = default)
{
var chunkStore = new LocalDirectoryChunkStore(chunkStoreDirectory);
var chunkJoiner = new ChunkJoiner(chunkStore);
@@ -224,14 +261,57 @@ public async Task GetResourceStreamFromChunksAsync(
chunkStore,
address.Hash);
- var resourceHash = await rootManifest.ResolveResourceHashAsync(address).ConfigureAwait(false);
+ var chunkReference = await rootManifest.ResolveAddressToChunkReferenceAsync(address).ConfigureAwait(false);
- var memoryStream = new MemoryStream();
- var resourceData = await chunkJoiner.GetJoinedChunkDataAsync(resourceHash).ConfigureAwait(false);
- memoryStream.Write(resourceData.ToArray());
- memoryStream.Position = 0;
+ return await chunkJoiner.GetJoinedChunkDataAsync(
+ chunkReference,
+ fileCachePath,
+ cancellationToken).ConfigureAwait(false);
+ }
+
+ public Task WriteDataChunksAsync(
+ byte[] data,
+ string outputDirectory,
+ bool createDirectory = true,
+ ushort compactLevel = 0,
+ bool encrypt = false,
+ RedundancyLevel redundancyLevel = RedundancyLevel.None,
+ int? chunkCuncorrency = null)
+ {
+ using var stream = new MemoryStream(data);
+ return WriteDataChunksAsync(
+ stream,
+ outputDirectory,
+ createDirectory,
+ compactLevel,
+ encrypt,
+ redundancyLevel,
+ chunkCuncorrency);
+ }
+
+ public async Task WriteDataChunksAsync(
+ Stream stream,
+ string outputDirectory,
+ bool createDirectory = true,
+ ushort compactLevel = 0,
+ bool encrypt = false,
+ RedundancyLevel redundancyLevel = RedundancyLevel.None,
+ int? chunkCuncorrency = null)
+ {
+ var chunkStore = new LocalDirectoryChunkStore(outputDirectory, createDirectory);
+
+ // Create chunks and get file hash.
+ using var fileHasherPipeline = HasherPipelineBuilder.BuildNewHasherPipeline(
+ chunkStore,
+ new FakePostageStamper(),
+ redundancyLevel,
+ encrypt,
+ compactLevel,
+ chunkCuncorrency);
+ var fileHashingResult = await fileHasherPipeline.HashDataAsync(stream).ConfigureAwait(false);
- return memoryStream;
+ // Return file hash.
+ return fileHashingResult.Hash;
}
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Services/FeedService.cs b/src/BeeNet.Util/Services/FeedService.cs
similarity index 96%
rename from src/BeeNet/Services/FeedService.cs
rename to src/BeeNet.Util/Services/FeedService.cs
index d18f8126..7b365f11 100644
--- a/src/BeeNet/Services/FeedService.cs
+++ b/src/BeeNet.Util/Services/FeedService.cs
@@ -13,8 +13,9 @@
// If not, see .
using Etherna.BeeNet.Exceptions;
-using Etherna.BeeNet.Feeds;
+using Etherna.BeeNet.Hashing;
using Etherna.BeeNet.Models;
+using Etherna.BeeNet.Models.Feeds;
using Nethereum.Hex.HexConvertors.Extensions;
using System;
using System.IO;
@@ -22,17 +23,9 @@
namespace Etherna.BeeNet.Services
{
- public class FeedService : IFeedService
+ public class FeedService(IBeeClient gatewayClient)
+ : IFeedService
{
- // Fields.
- private readonly IBeeClient gatewayClient;
-
- // Constructor.
- public FeedService(IBeeClient gatewayClient)
- {
- this.gatewayClient = gatewayClient;
- }
-
// Methods.
public Task CreateNextEpochFeedChunkAsync(
string account,
@@ -65,7 +58,7 @@ public async Task CreateNextEpochFeedChunkAsync(
// Create new chunk.
var chunkPayload = SwarmFeedChunk.BuildChunkPayload(contentPayload, (ulong)at.ToUnixTimeSeconds());
- var chunkHash = SwarmFeedChunk.BuildHash(account, topic, nextEpochIndex);
+ var chunkHash = SwarmFeedChunk.BuildHash(account, topic, nextEpochIndex, new Hasher());
return new SwarmFeedChunk(nextEpochIndex, chunkPayload, chunkHash);
}
@@ -160,7 +153,7 @@ public async Task CreateNextEpochFeedChunkAsync(
TryGetFeedChunkAsync(account.HexToByteArray(), topic, index);
public Task TryGetFeedChunkAsync(byte[] account, byte[] topic, FeedIndexBase index) =>
- TryGetFeedChunkAsync(SwarmFeedChunk.BuildHash(account, topic, index), index);
+ TryGetFeedChunkAsync(SwarmFeedChunk.BuildHash(account, topic, index, new Hasher()), index);
public async Task TryGetFeedChunkAsync(SwarmHash hash, FeedIndexBase index)
{
@@ -244,7 +237,7 @@ internal static EpochFeedIndex FindStartingEpochOffline(EpochFeedIndex? knownNea
/// A tuple with found chunk (if any) and updated "at" date
internal async Task TryFindStartingEpochChunkOnlineAsync(byte[] account, byte[] topic, ulong at, EpochFeedIndex epochIndex)
{
- // Try get chunk payload on network.
+ // Try to get chunk payload on network.
var chunk = await TryGetFeedChunkAsync(account, topic, epochIndex).ConfigureAwait(false);
// If chunk exists and date is prior.
diff --git a/src/BeeNet/Services/FileContentTypeProvider.cs b/src/BeeNet.Util/Services/FileContentTypeProvider.cs
similarity index 100%
rename from src/BeeNet/Services/FileContentTypeProvider.cs
rename to src/BeeNet.Util/Services/FileContentTypeProvider.cs
diff --git a/src/BeeNet/Services/ICalculatorService.cs b/src/BeeNet.Util/Services/ICalculatorService.cs
similarity index 57%
rename from src/BeeNet/Services/ICalculatorService.cs
rename to src/BeeNet.Util/Services/ICalculatorService.cs
index 5f17d73f..17216da8 100644
--- a/src/BeeNet/Services/ICalculatorService.cs
+++ b/src/BeeNet.Util/Services/ICalculatorService.cs
@@ -12,11 +12,12 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Postage;
-using Etherna.BeeNet.Hasher.Store;
+using Etherna.BeeNet.Hashing.Postage;
+using Etherna.BeeNet.Hashing.Store;
using Etherna.BeeNet.Models;
using System.Collections.Generic;
using System.IO;
+using System.Threading;
using System.Threading.Tasks;
namespace Etherna.BeeNet.Services
@@ -29,18 +30,22 @@ public interface ICalculatorService
/// The directory to upload
/// The index default file
/// The error default file
+ /// Chunk compact level [0, 65535]
/// True to encrypt
/// Choose the redundancy level
/// Custom postage stamp issuer
+ /// Amount of concurrent chunk hashing tasks. Null to default
/// Optional custom chunk store
/// The upload evaluation result
Task EvaluateDirectoryUploadAsync(
string directoryPath,
string? indexFilename = null,
string? errorFilename = null,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null);
///
@@ -49,18 +54,22 @@ Task EvaluateDirectoryUploadAsync(
/// The file data in byte array
/// The file content type
/// The file name
+ /// Chunk compact level [0, 65535]
/// True to encrypt
/// Choose the redundancy level
/// Custom postage stamp issuer
+ /// Amount of concurrent chunk hashing tasks. Null to default
/// Optional custom chunk store
/// The upload evaluation result
Task EvaluateFileUploadAsync(
byte[] data,
string fileContentType,
string? fileName,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null);
///
@@ -69,18 +78,22 @@ Task EvaluateFileUploadAsync(
/// The file stream
/// The file content type
/// The file name
+ /// Chunk compact level [0, 65535]
/// True to encrypt
/// Choose the redundancy level
/// Custom postage stamp issuer
+ /// Amount of concurrent chunk hashing tasks. Null to default
/// Optional custom chunk store
/// The upload evaluation result
Task EvaluateFileUploadAsync(
Stream stream,
string fileContentType,
string? fileName,
+ ushort compactLevel = 0,
bool encrypt = false,
RedundancyLevel redundancyLevel = RedundancyLevel.None,
IPostageStampIssuer? postageStampIssuer = null,
+ int? chunkCuncorrency = null,
IChunkStore? chunkStore = null);
///
@@ -89,7 +102,7 @@ Task EvaluateFileUploadAsync(
/// The chunk directory
/// Resource address
/// Resource metadata
- Task> GetResourceMetadataFromChunksAsync(
+ Task> GetFileMetadataFromChunksAsync(
string chunkStoreDirectory,
SwarmAddress address);
@@ -98,9 +111,53 @@ Task> GetResourceMetadataFromChunksAsync(
///
/// The chunk directory
/// Resource address
+ /// Optional file where store read data. Necessary if data is >2GB
+ /// Optional cancellation token
/// Resource stream
- Task GetResourceStreamFromChunksAsync(
+ Task GetFileStreamFromChunksAsync(
string chunkStoreDirectory,
- SwarmAddress address);
+ SwarmAddress address,
+ string? fileCachePath = null,
+ CancellationToken? cancellationToken = default);
+
+ ///
+ /// Write data chunks on a local directory, without any manifest
+ ///
+ /// The data byte array input
+ /// The output directory path
+ /// If true, create if directory doesn't exist
+ /// Chunk compact level [0, 65535]
+ /// True to encrypt
+ /// Choose the redundancy level
+ /// Amount of concurrent chunk hashing tasks. Null to default
+ /// The data root hash
+ Task WriteDataChunksAsync(
+ byte[] data,
+ string outputDirectory,
+ bool createDirectory = true,
+ ushort compactLevel = 0,
+ bool encrypt = false,
+ RedundancyLevel redundancyLevel = RedundancyLevel.None,
+ int? chunkCuncorrency = null);
+
+ ///
+ /// Write data chunks on a local directory, without any manifest
+ ///
+ /// The data stream input
+ /// The output directory path
+ /// If true, create if directory doesn't exist
+ /// Chunk compact level [0, 65535]
+ /// True to encrypt
+ /// Choose the redundancy level
+ /// Amount of concurrent chunk hashing tasks. Null to default
+ /// The data root hash
+ Task WriteDataChunksAsync(
+ Stream stream,
+ string outputDirectory,
+ bool createDirectory = true,
+ ushort compactLevel = 0,
+ bool encrypt = false,
+ RedundancyLevel redundancyLevel = RedundancyLevel.None,
+ int? chunkCuncorrency = null);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/Services/IFeedService.cs b/src/BeeNet.Util/Services/IFeedService.cs
similarity index 98%
rename from src/BeeNet/Services/IFeedService.cs
rename to src/BeeNet.Util/Services/IFeedService.cs
index 4d9e1bba..0c06a468 100644
--- a/src/BeeNet/Services/IFeedService.cs
+++ b/src/BeeNet.Util/Services/IFeedService.cs
@@ -12,8 +12,8 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Feeds;
using Etherna.BeeNet.Models;
+using Etherna.BeeNet.Models.Feeds;
using System;
using System.Threading.Tasks;
diff --git a/src/BeeNet/Services/UploadEvaluationResult.cs b/src/BeeNet.Util/Services/UploadEvaluationResult.cs
similarity index 79%
rename from src/BeeNet/Services/UploadEvaluationResult.cs
rename to src/BeeNet.Util/Services/UploadEvaluationResult.cs
index 89cb0d5a..715f41ce 100644
--- a/src/BeeNet/Services/UploadEvaluationResult.cs
+++ b/src/BeeNet.Util/Services/UploadEvaluationResult.cs
@@ -12,7 +12,7 @@
// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
// If not, see .
-using Etherna.BeeNet.Hasher.Postage;
+using Etherna.BeeNet.Hashing.Postage;
using Etherna.BeeNet.Models;
using System;
@@ -23,9 +23,11 @@ public class UploadEvaluationResult
// Constructor.
internal UploadEvaluationResult(
SwarmHash hash,
+ long missedOptimisticHashing,
IPostageStampIssuer postageStampIssuer)
{
Hash = hash;
+ MissedOptimisticHashing = missedOptimisticHashing;
PostageStampIssuer = postageStampIssuer;
}
@@ -34,6 +36,8 @@ internal UploadEvaluationResult(
/// The upload resulting hash
///
public SwarmHash Hash { get; }
+
+ public long MissedOptimisticHashing { get; }
public IPostageStampIssuer PostageStampIssuer { get; }
@@ -41,7 +45,7 @@ internal UploadEvaluationResult(
/// Total batch space consumed in bytes
///
public long ConsumedSize =>
- PostageStampIssuer.MaxBucketCount *
+ PostageStampIssuer.Buckets.MaxBucketCollisions *
(long)Math.Pow(2, PostageBatch.BucketDepth) *
SwarmChunk.DataSize;
@@ -49,19 +53,11 @@ internal UploadEvaluationResult(
/// Available postage batch space after the upload, with minimum batch depth
///
public long RemainingPostageBatchSize => RequiredPostageBatchByteSize - ConsumedSize;
-
- ///
- /// Minimum required postage batch depth to handle the upload
- ///
- public int RequiredPostageBatchDepth =>
- Math.Max(
- (int)Math.Ceiling(Math.Log2(PostageStampIssuer.MaxBucketCount)) + PostageBatch.BucketDepth,
- PostageBatch.MinDepth);
///
/// Minimum required postage batch byte size
///
public long RequiredPostageBatchByteSize =>
- (long)(Math.Pow(2, RequiredPostageBatchDepth) * SwarmChunk.DataSize);
+ (long)(Math.Pow(2, PostageStampIssuer.Buckets.RequiredPostageBatchDepth) * SwarmChunk.DataSize);
}
}
\ No newline at end of file
diff --git a/src/BeeNet/BeeClient.cs b/src/BeeNet/BeeClient.cs
deleted file mode 100644
index 04f72991..00000000
--- a/src/BeeNet/BeeClient.cs
+++ /dev/null
@@ -1,704 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using Etherna.BeeNet.Clients;
-using Etherna.BeeNet.Exceptions;
-using Etherna.BeeNet.Models;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-using FileResponse = Etherna.BeeNet.Models.FileResponse;
-
-#if NET7_0_OR_GREATER
-using System.Formats.Tar;
-#endif
-
-namespace Etherna.BeeNet
-{
- [SuppressMessage("Design", "CA1054:URI-like parameters should not be strings")]
- public class BeeClient : IBeeClient, IDisposable
- {
- // Consts.
- public const int DefaultPort = 1633;
- public readonly TimeSpan DefaultTimeout = TimeSpan.FromMinutes(10);
-
- // Fields.
- private readonly BeeGeneratedClient generatedClient;
- private readonly HttpClient httpClient;
-
- private bool disposed;
-
- // Constructors.
- public BeeClient(
- string baseUrl = "http://localhost/",
- int port = DefaultPort,
- HttpClient? httpClient = null)
- : this(BuildBaseUrl(baseUrl, port), httpClient)
- { }
-
- public BeeClient(
- Uri baseUrl,
- HttpClient? httpClient = null)
- {
- this.httpClient = httpClient ?? new HttpClient { Timeout = DefaultTimeout };
-
- BaseUrl = baseUrl;
- generatedClient = new BeeGeneratedClient(this.httpClient) { BaseUrl = BaseUrl.ToString() };
- }
-
- // Dispose.
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposed) return;
-
- // Dispose managed resources.
- if (disposing)
- httpClient.Dispose();
-
- disposed = true;
- }
-
-
- // Properties.
- public Uri BaseUrl { get; }
-
- // Methods.
- public async Task> AccountingAsync(
- CancellationToken cancellationToken = default) =>
- (await generatedClient.AccountingAsync(cancellationToken).ConfigureAwait(false)).PeerData.ToDictionary(i => i.Key, i => new Account(i.Value));
-
- public async Task AuthenticateAsync(string role, int expiry) =>
- new(await generatedClient.AuthAsync(
- new Body
- {
- Role = role,
- Expiry = expiry
- }).ConfigureAwait(false));
-
- public async Task BuyPostageBatchAsync(
- BzzBalance amount,
- int depth,
- string? label = null,
- bool? immutable = null,
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.StampsPostAsync(
- amount.ToPlurString(),
- depth,
- label,
- immutable,
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false)).BatchID;
-
- public async Task CashoutChequeForPeerAsync(
- string peerId,
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ChequebookCashoutPostAsync(
- peerId,
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- public async Task CheckChunkExistsAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default)
- {
- try
- {
- await generatedClient.ChunksHeadAsync(hash.ToString(), cancellationToken).ConfigureAwait(false);
- return true;
- }
- catch (BeeNetApiException)
- {
- return false;
- }
- }
-
- public async Task CheckIsContentAvailableAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.StewardshipGetAsync((string)hash, cancellationToken).ConfigureAwait(false));
-
- public async Task CheckPinsAsync(
- SwarmHash? hash,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.PinsCheckAsync(hash?.ToString(), cancellationToken).ConfigureAwait(false));
-
- public async Task ConnectToPeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ConnectAsync(peerAddress, cancellationToken).ConfigureAwait(false)).Address;
-
- public async Task CreateFeedAsync(
- string owner,
- string topic,
- PostageBatchId batchId,
- string? type = null,
- bool? swarmPin = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.FeedsPostAsync(owner, topic, type, swarmPin, batchId.ToString(), cancellationToken).ConfigureAwait(false)).Reference;
-
- public async Task CreatePinAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.PinsPostAsync((string)hash, cancellationToken).ConfigureAwait(false));
-
- public async Task CreateTagAsync(
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.TagsPostAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task DeletePeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.PeersDeleteAsync(peerAddress, cancellationToken).ConfigureAwait(false));
-
- public async Task DeletePinAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.PinsDeleteAsync((string)hash, cancellationToken).ConfigureAwait(false));
-
- public Task DeleteTagAsync(
- long uid,
- CancellationToken cancellationToken = default) =>
- generatedClient.TagsDeleteAsync(uid, cancellationToken);
-
- public async Task DeleteTransactionAsync(
- string txHash,
- XDaiBalance? gasPrice = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.TransactionsDeleteAsync(
- txHash,
- gasPrice?.ToWeiLong(),
- cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- public async Task DepositIntoChequeBookAsync(
- BzzBalance amount,
- XDaiBalance? gasPrice = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ChequebookDepositAsync(
- amount.ToPlurLong(),
- gasPrice?.ToWeiLong(),
- cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- public async Task DilutePostageBatchAsync(
- PostageBatchId batchId,
- int depth,
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.StampsDiluteAsync(
- batchId.ToString(),
- depth,
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false)).BatchID;
-
- public async Task GetAddressesAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.AddressesAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task> GetAllBalancesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.BalancesGetAsync(cancellationToken).ConfigureAwait(false)).Balances.Select(i => new PeerBalance(i));
-
- public async Task> GetAllChequeBookChequesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.ChequebookChequeGetAsync(cancellationToken).ConfigureAwait(false)).Lastcheques.Select(i => new ChequebookChequeGet(i));
-
- public async Task> GetAllConsumedBalancesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.ConsumedGetAsync(cancellationToken).ConfigureAwait(false)).Balances.Select(i => new PeerBalance(i));
-
- public async Task> GetAllPeerAddressesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.PeersGetAsync(cancellationToken).ConfigureAwait(false)).Peers.Select(i => i.Address);
-
- public async Task> GetAllPinsAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.PinsGetAsync(cancellationToken).ConfigureAwait(false)).Reference
- .Select(h => new SwarmHash(h));
-
- public async Task GetAllSettlementsAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.SettlementsGetAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetAllTimeSettlementsAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.TimesettlementsAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task> GetAllValidPostageBatchesFromAllNodesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.BatchesAsync(cancellationToken).ConfigureAwait(false)).Batches.Select(i => new PostageBatchShort(i));
-
- public async Task GetBalanceWithPeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.BalancesGetAsync(peerAddress, cancellationToken).ConfigureAwait(false));
-
- public async Task GetBytesAsync(
- SwarmHash hash,
- bool? swarmCache = null,
- RedundancyStrategy? swarmRedundancyStrategy = null,
- bool? swarmRedundancyFallbackMode = null,
- string? swarmChunkRetrievalTimeout = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.BytesGetAsync(
- (string)hash,
- swarmCache,
- (SwarmRedundancyStrategy?)swarmRedundancyStrategy,
- swarmRedundancyFallbackMode,
- swarmChunkRetrievalTimeout,
- cancellationToken).ConfigureAwait(false)).Stream;
-
- public Task GetBytesHeadAsync(SwarmHash hash, CancellationToken cancellationToken = default) =>
- generatedClient.BytesHeadAsync(hash.ToString(), cancellationToken);
-
- public async Task> GetBlocklistedPeerAddressesAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.BlocklistAsync(cancellationToken).ConfigureAwait(false)).Select(i => i.Address.Address1);
-
- public async Task GetChainStateAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.ChainstateAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetChequeBookAddressAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.ChequebookAddressAsync(cancellationToken).ConfigureAwait(false)).ChequebookAddress;
-
- public async Task GetChequeBookBalanceAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.ChequebookBalanceAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetChequeBookCashoutForPeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.ChequebookCashoutGetAsync(peerAddress, cancellationToken).ConfigureAwait(false));
-
- public async Task GetChequeBookChequeForPeerAsync(
- string peerId,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.ChequebookChequeGetAsync(peerId, cancellationToken).ConfigureAwait(false));
-
- public async Task GetChunkAsync(
- SwarmHash hash,
- bool? swarmCache = null,
- CancellationToken cancellationToken = default)
- {
- var chunkDto = await generatedClient.ChunksGetAsync((string)hash, swarmCache, cancellationToken).ConfigureAwait(false);
- using var memoryStream = new MemoryStream();
- await chunkDto.Stream.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
- var data = memoryStream.ToArray();
- return new SwarmChunk(hash, data);
- }
-
- public async Task GetChunkStreamAsync(
- SwarmHash hash,
- bool? swarmCache = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ChunksGetAsync(hash.ToString(), swarmCache, cancellationToken).ConfigureAwait(false)).Stream;
-
- public async Task GetConsumedBalanceWithPeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.ConsumedGetAsync(peerAddress, cancellationToken).ConfigureAwait(false));
-
- public async Task GetFeedAsync(
- string owner,
- string topic,
- int? at = null,
- int? after = null,
- string? type = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.FeedsGetAsync(owner, topic, at, after, type, cancellationToken).ConfigureAwait(false)).Reference;
-
- public async Task GetFileAsync(
- SwarmAddress address,
- bool? swarmCache = null,
- RedundancyStrategy? swarmRedundancyStrategy = null,
- bool? swarmRedundancyFallbackMode = null,
- string? swarmChunkRetrievalTimeout = null,
- CancellationToken cancellationToken = default)
- {
- ArgumentNullException.ThrowIfNull(address, nameof(address));
-
- return address.RelativePath is null
- ? new(await generatedClient.BzzGetAsync(
- address.Hash.ToString(),
- swarmCache,
- (SwarmRedundancyStrategy2?)swarmRedundancyStrategy,
- swarmRedundancyFallbackMode,
- swarmChunkRetrievalTimeout,
- cancellationToken).ConfigureAwait(false))
- : new(await generatedClient.BzzGetAsync(
- address.Hash.ToString(),
- address.RelativePath.ToString(),
- (SwarmRedundancyStrategy3?)swarmRedundancyStrategy,
- swarmRedundancyFallbackMode,
- swarmChunkRetrievalTimeout,
- cancellationToken).ConfigureAwait(false));
- }
-
- public Task GetFileHeadAsync(SwarmHash hash, CancellationToken cancellationToken = default) =>
- generatedClient.BzzHeadAsync((string)hash, cancellationToken);
-
- public async Task GetHealthAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.HealthAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetNodeInfoAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.NodeAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task> GetOwnedPostageBatchesByNodeAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.StampsGetAsync(cancellationToken).ConfigureAwait(false)).Stamps.Select(i => new PostageBatch(i));
-
- public async Task> GetPendingTransactionsAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.TransactionsGetAsync(cancellationToken).ConfigureAwait(false)).PendingTransactions.Select(i => new TxInfo(i));
-
- public async Task GetPinStatusAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.PinsGetAsync((string)hash, cancellationToken).ConfigureAwait(false)).Reference;
-
- public async Task GetPostageBatchAsync(
- PostageBatchId batchId,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.StampsGetAsync(batchId.ToString(), cancellationToken).ConfigureAwait(false));
-
- public async Task GetReserveCommitmentAsync(int depth, string anchor1, string anchor2,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.RchashAsync(depth, anchor1, anchor2, cancellationToken).ConfigureAwait(false));
-
- public async Task GetReserveStateAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.ReservestateAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetSettlementsWithPeerAsync(
- string peerAddress,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.SettlementsGetAsync(peerAddress, cancellationToken).ConfigureAwait(false));
-
- public async Task GetStampsBucketsForBatchAsync(
- PostageBatchId batchId,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.StampsBucketsAsync(batchId.ToString(), cancellationToken).ConfigureAwait(false));
-
- public async Task GetSwarmTopologyAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.TopologyAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetTagInfoAsync(
- long uid,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.TagsGetAsync(uid, cancellationToken).ConfigureAwait(false));
-
- public async Task> GetTagsListAsync(
- int? offset = null,
- int? limit = null,
- CancellationToken cancellationToken = default) =>
- ((await generatedClient.TagsGetAsync(offset, limit, cancellationToken).ConfigureAwait(false)).Tags ?? Array.Empty()).Select(i => new TagInfo(i));
-
- public async Task GetTransactionInfoAsync(
- string txHash,
- CancellationToken cancellationToken = default) =>
- new(await generatedClient.TransactionsGetAsync(txHash, cancellationToken).ConfigureAwait(false));
-
- public async Task GetWalletBalance(CancellationToken cancellationToken = default) =>
- new(await generatedClient.WalletAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task GetWelcomeMessageAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.WelcomeMessageGetAsync(cancellationToken).ConfigureAwait(false)).WelcomeMessage;
-
- public async Task LoggersGetAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.LoggersGetAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task LoggersGetAsync(string exp, CancellationToken cancellationToken = default) =>
- new(await generatedClient.LoggersGetAsync(exp, cancellationToken).ConfigureAwait(false));
-
- public async Task LoggersPutAsync(string exp, CancellationToken cancellationToken = default) =>
- await generatedClient.LoggersPutAsync(exp, cancellationToken).ConfigureAwait(false);
-
- public async Task RebroadcastTransactionAsync(
- string txHash,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.TransactionsPostAsync(txHash, cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- public async Task RedistributionStateAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.RedistributionstateAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task RefreshAuthAsync(
- string role,
- int expiry,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.RefreshAsync(
- new Body2
- {
- Role = role,
- Expiry = expiry
- },
- cancellationToken).ConfigureAwait(false)).Key;
-
- public Task ReuploadContentAsync(
- SwarmHash hash,
- CancellationToken cancellationToken = default) =>
- generatedClient.StewardshipPutAsync((string)hash, cancellationToken: cancellationToken);
-
- public Task SendPssAsync(
- string topic,
- string targets,
- PostageBatchId batchId,
- string? recipient = null,
- CancellationToken cancellationToken = default) =>
- generatedClient.PssSendAsync(topic, targets, batchId.ToString(), recipient, cancellationToken);
-
- public Task SetWelcomeMessageAsync(
- string welcomeMessage,
- CancellationToken cancellationToken = default) =>
- generatedClient.WelcomeMessagePostAsync(
- new Body4
- {
- WelcomeMessage = welcomeMessage
- },
- cancellationToken);
-
- public async Task StakeDeleteAsync(
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- await generatedClient.StakeDeleteAsync(
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false);
-
- public async Task StakeGetAsync(CancellationToken cancellationToken = default) =>
- await generatedClient.StakeGetAsync(cancellationToken).ConfigureAwait(false);
-
- public async Task StakePostAsync(
- BzzBalance amount,
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- await generatedClient.StakePostAsync(
- amount.ToPlurString(),
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false);
-
- public async Task StatusNodeAsync(CancellationToken cancellationToken = default) =>
- new(await generatedClient.StatusAsync(cancellationToken).ConfigureAwait(false));
-
- public async Task> StatusPeersAsync(CancellationToken cancellationToken = default) =>
- (await generatedClient.StatusPeersAsync(cancellationToken).ConfigureAwait(false)).Stamps.Select(p => new StatusNode(p));
-
- public Task SubscribeToPssAsync(
- string topic,
- CancellationToken cancellationToken = default) =>
- generatedClient.PssSubscribeAsync(topic, cancellationToken);
-
- public async Task TopUpPostageBatchAsync(
- PostageBatchId batchId,
- BzzBalance amount,
- XDaiBalance? gasPrice = null,
- long? gasLimit = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.StampsTopupAsync(
- batchId.ToString(),
- amount.ToPlurLong(),
- gasPrice?.ToWeiLong(),
- gasLimit,
- cancellationToken).ConfigureAwait(false)).BatchID;
-
- public async Task TryConnectToPeerAsync(
- string peerId,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.PingpongAsync(peerId, cancellationToken).ConfigureAwait(false)).Rtt;
-
- public Task UpdateTagAsync(
- long uid,
- SwarmHash? hash = null,
- CancellationToken cancellationToken = default) =>
- generatedClient.TagsPatchAsync(
- uid,
- hash.HasValue ?
- new Body3 { Address = hash.Value.ToString() } :
- null,
- cancellationToken);
-
- public async Task UploadChunkAsync(PostageBatchId batchId,
- Stream chunkData,
- bool swarmPin = false,
- bool swarmDeferredUpload = true,
- long? swarmTag = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ChunksPostAsync(
- swarmTag,
- batchId.ToString(),
- chunkData,
- cancellationToken).ConfigureAwait(false)).Reference;
-
- public Task UploadChunksStreamAsync(
- PostageBatchId batchId,
- int? swarmTag = null,
- bool? swarmPin = null,
- CancellationToken cancellationToken = default) =>
- generatedClient.ChunksStreamAsync(swarmTag, batchId.ToString(), cancellationToken);
-
- public async Task UploadBytesAsync(
- PostageBatchId batchId,
- Stream body,
- int? swarmTag = null,
- bool? swarmPin = null,
- bool? swarmEncrypt = null,
- bool? swarmDeferredUpload = null,
- RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.BytesPostAsync(
- swarm_postage_batch_id: batchId.ToString(),
- swarm_tag: swarmTag,
- swarm_pin: swarmPin,
- swarm_deferred_upload: swarmDeferredUpload,
- swarm_encrypt: swarmEncrypt,
- swarm_redundancy_level: (int)swarmRedundancyLevel,
- body: body,
- cancellationToken).ConfigureAwait(false)).Reference;
-
-#if NET7_0_OR_GREATER
- public async Task UploadDirectoryAsync(
- PostageBatchId batchId,
- string directoryPath,
- int? swarmTag = null,
- bool? swarmPin = null,
- bool? swarmEncrypt = null,
- string? swarmIndexDocument = null,
- string? swarmErrorDocument = null,
- bool? swarmDeferredUpload = null,
- RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
- CancellationToken cancellationToken = default)
- {
- // Create tar file.
- using var memoryStream = new MemoryStream();
- await TarFile.CreateFromDirectoryAsync(directoryPath, memoryStream, false, cancellationToken).ConfigureAwait(false);
- memoryStream.Position = 0;
-
- // Try set index document.
- if (swarmIndexDocument is null &&
- File.Exists(Path.Combine(directoryPath, "index.html")))
- swarmIndexDocument = "index.html";
-
- // Upload directory.
- return (await generatedClient.BzzPostAsync(
- new FileParameter(memoryStream, null, "application/x-tar"),
- swarm_tag: swarmTag,
- swarm_pin: swarmPin,
- swarm_encrypt: swarmEncrypt,
- swarm_collection: true,
- swarm_index_document: swarmIndexDocument,
- swarm_error_document: swarmErrorDocument,
- swarm_postage_batch_id: batchId.ToString(),
- swarm_deferred_upload: swarmDeferredUpload,
- swarm_redundancy_level: (SwarmRedundancyLevel)swarmRedundancyLevel,
- cancellationToken: cancellationToken).ConfigureAwait(false)).Reference;
- }
-#endif
-
- public async Task UploadFileAsync(
- PostageBatchId batchId,
- Stream content,
- string? name = null,
- string? contentType = null,
- bool isFileCollection = false,
- int? swarmTag = null,
- bool? swarmPin = null,
- bool? swarmEncrypt = null,
- string? swarmIndexDocument = null,
- string? swarmErrorDocument = null,
- bool? swarmDeferredUpload = null,
- RedundancyLevel swarmRedundancyLevel = RedundancyLevel.None,
- CancellationToken cancellationToken = default)
- {
- return (await generatedClient.BzzPostAsync(
- new FileParameter(content, name, contentType),
- swarm_tag: swarmTag,
- swarm_pin: swarmPin,
- swarm_encrypt: swarmEncrypt,
- swarm_collection: isFileCollection,
- swarm_index_document: swarmIndexDocument,
- swarm_error_document: swarmErrorDocument,
- swarm_postage_batch_id: batchId.ToString(),
- swarm_deferred_upload: swarmDeferredUpload,
- swarm_redundancy_level: (SwarmRedundancyLevel)swarmRedundancyLevel,
- cancellationToken: cancellationToken).ConfigureAwait(false)).Reference;
- }
-
- public async Task UploadSocAsync(
- string owner,
- string id,
- string sig,
- PostageBatchId batchId,
- Stream body,
- bool? swarmPin = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.SocAsync(
- owner,
- id,
- sig,
- batchId.ToString(),
- body,
- swarmPin,
- cancellationToken).ConfigureAwait(false)).Reference;
-
- public async Task WalletWithdrawAsync(
- BzzBalance amount,
- string address,
- XDaiBalance coin,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.WalletWithdrawAsync(
- amount.ToPlurString(),
- address,
- coin.ToWeiString(),
- cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- public async Task WithdrawFromChequeBookAsync(
- BzzBalance amount,
- XDaiBalance? gasPrice = null,
- CancellationToken cancellationToken = default) =>
- (await generatedClient.ChequebookWithdrawAsync(
- amount.ToPlurLong(),
- gasPrice?.ToWeiLong(),
- cancellationToken).ConfigureAwait(false)).TransactionHash;
-
- // Helpers.
- private static Uri BuildBaseUrl(string url, int port)
- {
- var normalizedUrl = url;
- if (normalizedUrl.Last() != '/')
- normalizedUrl += '/';
-
- var baseUrl = "";
-
- var urlRegex = new Regex(@"^((?\w+)://)?(?[^/:]+)",
- RegexOptions.None, TimeSpan.FromMilliseconds(150));
- var urlMatch = urlRegex.Match(normalizedUrl);
-
- if (!urlMatch.Success)
- throw new ArgumentException("Url is not valid", nameof(url));
-
- if (!string.IsNullOrEmpty(urlMatch.Groups["proto"].Value))
- baseUrl += urlMatch.Groups["proto"].Value + "://";
-
- baseUrl += $"{urlMatch.Groups["host"].Value}:{port}";
-
- return new Uri(baseUrl);
- }
- }
-}
\ No newline at end of file
diff --git a/src/BeeNet/GlobalSuppressions.cs b/src/BeeNet/GlobalSuppressions.cs
deleted file mode 100644
index 2a923b49..00000000
--- a/src/BeeNet/GlobalSuppressions.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-// This file is used by Code Analysis to maintain SuppressMessage
-// attributes that are applied to this project.
-// Project-level suppressions either have no target or are given
-// a specific target and scoped to a namespace, type, member, etc.
-
-using System.Diagnostics.CodeAnalysis;
-
-[assembly: SuppressMessage("Usage", "CA1707:Remove the underscores from namespace name", Justification = "Version number should containt underscores", Scope = "namespaceanddescendants", Target = "~N:Etherna.BeeNet.Clients")]
diff --git a/src/BeeNet/Hasher/Pipeline/ChunkBmtPipelineStage.cs b/src/BeeNet/Hasher/Pipeline/ChunkBmtPipelineStage.cs
deleted file mode 100644
index 7d81bb9d..00000000
--- a/src/BeeNet/Hasher/Pipeline/ChunkBmtPipelineStage.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using Etherna.BeeNet.Hasher.Bmt;
-using Etherna.BeeNet.Models;
-using System;
-using System.Threading.Tasks;
-
-namespace Etherna.BeeNet.Hasher.Pipeline
-{
- ///
- /// Calculate hash of each chunk
- ///
- internal sealed class ChunkBmtPipelineStage(
- IHasherPipelineStage nextStage)
- : IHasherPipelineStage
- {
- // Dispose.
- public void Dispose()
- {
- nextStage.Dispose();
- }
-
- // Methods.
- public async Task FeedAsync(HasherPipelineFeedArgs args)
- {
- if (args.Data.Length < SwarmChunk.SpanSize)
- throw new InvalidOperationException("Data can't be shorter than span size here");
- if (args.Data.Length > SwarmChunk.SpanAndDataSize)
- throw new InvalidOperationException("Data can't be longer than chunk + span size here");
-
- args.Hash = SwarmChunkBmtHasher.Hash(
- args.Data[..SwarmChunk.SpanSize].ToArray(),
- args.Data[SwarmChunk.SpanSize..].ToArray());
-
- await nextStage.FeedAsync(args).ConfigureAwait(false);
- }
-
- public Task SumAsync() => nextStage.SumAsync();
- }
-}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Pipeline/ChunkFeederPipelineStage.cs b/src/BeeNet/Hasher/Pipeline/ChunkFeederPipelineStage.cs
deleted file mode 100644
index 12ddf915..00000000
--- a/src/BeeNet/Hasher/Pipeline/ChunkFeederPipelineStage.cs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using Etherna.BeeNet.Models;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Etherna.BeeNet.Hasher.Pipeline
-{
- ///
- /// Produce chunked data with span prefix for successive stages.
- /// Also controls the parallelism on chunk elaboration
- ///
- internal sealed class ChunkFeederPipelineStage(
- IHasherPipelineStage nextStage,
- int chunkConcurrency)
- : IHasherPipeline
- {
- // Fields.
- private readonly List nextStageTasks = new();
- private readonly SemaphoreSlim semaphore = new(chunkConcurrency, chunkConcurrency);
-
- private long passedBytes;
-
- // Constructor.
- public ChunkFeederPipelineStage(IHasherPipelineStage nextStage)
- : this(nextStage, Environment.ProcessorCount)
- { }
-
- // Dispose.
- public void Dispose()
- {
- nextStage.Dispose();
- semaphore.Dispose();
- }
-
- // Properties.
- public bool IsUsable { get; private set; } = true;
-
- // Methods.
- public async Task HashDataAsync(byte[] data)
- {
- ArgumentNullException.ThrowIfNull(data, nameof(data));
-
- using var memoryStream = new MemoryStream(data);
- return await HashDataAsync(memoryStream).ConfigureAwait(false);
- }
-
- public async Task HashDataAsync(Stream dataStream)
- {
- ArgumentNullException.ThrowIfNull(dataStream, nameof(dataStream));
-
- if (!IsUsable)
- throw new InvalidOperationException("Pipeline has already been used");
-
- // Make it no more usable.
- IsUsable = false;
-
- // Slicing the stream permits to avoid to load all the stream in memory at the same time.
- var chunkBuffer = new byte[SwarmChunk.DataSize];
- int chunkReadSize;
- do
- {
- chunkReadSize = await dataStream.ReadAsync(chunkBuffer).ConfigureAwait(false);
-
- if (chunkReadSize > 0 || //write only chunks with data
- passedBytes == 0) //or if the first and only one is empty
- {
- // Copy read data from buffer to a new chunk data byte[]. Include also span
- var chunkData = new byte[SwarmChunk.SpanSize + chunkReadSize];
- chunkBuffer.AsSpan(0, chunkReadSize).CopyTo(chunkData.AsSpan(SwarmChunk.SpanSize));
-
- // Write chunk span.
- SwarmChunk.WriteSpan(
- chunkData.AsSpan(0, SwarmChunk.SpanSize),
- (ulong)chunkReadSize);
-
- // Invoke next stage with parallelism on chunks.
- await semaphore.WaitAsync().ConfigureAwait(false);
- var feedArgs = new HasherPipelineFeedArgs(
- span: chunkData[..SwarmChunk.SpanSize],
- data: chunkData,
- numberId: passedBytes / SwarmChunk.DataSize);
- nextStageTasks.Add(
- Task.Run(async () =>
- {
- try
- {
- await nextStage.FeedAsync(feedArgs).ConfigureAwait(false);
- }
- finally
- {
- semaphore.Release();
- }
- }));
-
- passedBytes += chunkReadSize;
- }
- } while (chunkReadSize == SwarmChunk.DataSize);
-
- // Wait the end of all chunk computation.
- await Task.WhenAll(nextStageTasks).ConfigureAwait(false);
-
- return await nextStage.SumAsync().ConfigureAwait(false);
- }
- }
-}
\ No newline at end of file
diff --git a/src/BeeNet/Hasher/Store/ChunkJoiner.cs b/src/BeeNet/Hasher/Store/ChunkJoiner.cs
deleted file mode 100644
index 01009250..00000000
--- a/src/BeeNet/Hasher/Store/ChunkJoiner.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using Etherna.BeeNet.Models;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
-namespace Etherna.BeeNet.Hasher.Store
-{
- public class ChunkJoiner
- {
- // Fields.
- private readonly IChunkStore chunkStore;
-
- // Constructor.
- public ChunkJoiner(IChunkStore chunkStore)
- {
- this.chunkStore = chunkStore;
- }
-
- // Methods.
- public async Task> GetJoinedChunkDataAsync(SwarmHash hash)
- {
- var chunk = await chunkStore.GetAsync(hash).ConfigureAwait(false);
- var totalDataLength = SwarmChunk.SpanToLength(chunk.Span.Span);
-
- if (totalDataLength <= SwarmChunk.DataSize)
- return chunk.Data.ToArray();
-
- var joinedData = new List();
-
- for (int i = 0; i < chunk.Data.Length; i += SwarmHash.HashSize)
- {
- var childHash = new SwarmHash(chunk.Data[i..(i + SwarmHash.HashSize)].ToArray());
- joinedData.AddRange(await GetJoinedChunkDataAsync(childHash).ConfigureAwait(false));
- }
-
- return joinedData;
- }
- }
-}
\ No newline at end of file
diff --git a/src/BeeNet/Models/Account.cs b/src/BeeNet/Models/Account.cs
deleted file mode 100644
index 2a262d5d..00000000
--- a/src/BeeNet/Models/Account.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class Account
- {
- // Constructors.
- internal Account(Clients.Anonymous3 value)
- {
- ArgumentNullException.ThrowIfNull(value, nameof(value));
-
- Balance = BzzBalance.FromPlurString(value.Balance);
- ThresholdReceived = BzzBalance.FromPlurString(value.ThresholdReceived);
- ThresholdGiven = BzzBalance.FromPlurString(value.ThresholdGiven);
- SurplusBalance = BzzBalance.FromPlurString(value.SurplusBalance);
- ReservedBalance = BzzBalance.FromPlurString(value.ReservedBalance);
- ShadowReservedBalance = BzzBalance.FromPlurString(value.ShadowReservedBalance);
- GhostBalance = BzzBalance.FromPlurString(value.GhostBalance);
- }
-
- // Properties.
- public BzzBalance Balance { get; set; }
- public BzzBalance ThresholdReceived { get; set; }
- public BzzBalance ThresholdGiven { get; set; }
- public BzzBalance SurplusBalance { get; set; }
- public BzzBalance ReservedBalance { get; set; }
- public BzzBalance ShadowReservedBalance { get; set; }
- public BzzBalance GhostBalance { get; set; }
- }
-}
diff --git a/src/BeeNet/Models/ChequePayment.cs b/src/BeeNet/Models/ChequePayment.cs
deleted file mode 100644
index daf0f1c0..00000000
--- a/src/BeeNet/Models/ChequePayment.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using Etherna.BeeNet.Clients;
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class ChequePayment
- {
- // Constructors.
- internal ChequePayment(LastCashedCheque lastCashedCheque)
- {
- ArgumentNullException.ThrowIfNull(lastCashedCheque, nameof(lastCashedCheque));
-
- Beneficiary = lastCashedCheque.Beneficiary;
- Chequebook = lastCashedCheque.Chequebook;
- Payout = BzzBalance.FromPlurString(lastCashedCheque.Payout);
- }
- internal ChequePayment(Lastreceived lastReceived)
- {
- ArgumentNullException.ThrowIfNull(lastReceived, nameof(lastReceived));
-
- Beneficiary = lastReceived.Beneficiary;
- Chequebook = lastReceived.Chequebook;
- Payout = BzzBalance.FromPlurString(lastReceived.Payout);
- }
- internal ChequePayment(Lastreceived2 lastReceived)
- {
- ArgumentNullException.ThrowIfNull(lastReceived, nameof(lastReceived));
-
- Beneficiary = lastReceived.Beneficiary;
- Chequebook = lastReceived.Chequebook;
- Payout = BzzBalance.FromPlurString(lastReceived.Payout);
- }
- internal ChequePayment(Lastsent lastsent)
- {
- ArgumentNullException.ThrowIfNull(lastsent, nameof(lastsent));
-
- Beneficiary = lastsent.Beneficiary;
- Chequebook = lastsent.Chequebook;
- Payout = BzzBalance.FromPlurString(lastsent.Payout);
- }
- internal ChequePayment(Lastsent2 lastsent)
- {
- ArgumentNullException.ThrowIfNull(lastsent, nameof(lastsent));
-
- Beneficiary = lastsent.Beneficiary;
- Chequebook = lastsent.Chequebook;
- Payout = BzzBalance.FromPlurString(lastsent.Payout);
- }
-
- // Properties.
- public string Beneficiary { get; }
- public string Chequebook { get; }
- public BzzBalance Payout { get; }
- }
-}
diff --git a/src/BeeNet/Models/ChequebookCashoutGet.cs b/src/BeeNet/Models/ChequebookCashoutGet.cs
deleted file mode 100644
index 623a6149..00000000
--- a/src/BeeNet/Models/ChequebookCashoutGet.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-using System.Globalization;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class ChequebookCashoutGet
- {
- // Constructors.
- internal ChequebookCashoutGet(Clients.Response41 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Peer = response.Peer;
- LastCashedCheque = response.LastCashedCheque is not null ? new ChequePayment(response.LastCashedCheque) : null;
- TransactionHash = response.TransactionHash;
- Result = new ResultChequebook(response.Result);
- UncashedAmount = BzzBalance.FromPlurString(response.UncashedAmount);
- }
-
- // Properties.
- public string Peer { get; }
- public ChequePayment? LastCashedCheque { get; }
- public string TransactionHash { get; }
- public ResultChequebook Result { get; }
- public BzzBalance UncashedAmount { get; }
- }
-
-}
diff --git a/src/BeeNet/Models/ChequebookChequeGet.cs b/src/BeeNet/Models/ChequebookChequeGet.cs
deleted file mode 100644
index af9a7c5a..00000000
--- a/src/BeeNet/Models/ChequebookChequeGet.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class ChequebookChequeGet
- {
- // Constructors
- internal ChequebookChequeGet(Clients.Lastcheques response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Peer = response.Peer;
- LastReceived = response.Lastreceived is not null ? new ChequePayment(response.Lastreceived) : null;
- LastSent = response.Lastsent is not null ? new ChequePayment(response.Lastsent) : null;
- }
-
- internal ChequebookChequeGet(Clients.Response43 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Peer = response.Peer;
- LastReceived = response.Lastreceived is not null ? new ChequePayment(response.Lastreceived) : null;
- LastSent = response.Lastsent is not null ? new ChequePayment(response.Lastsent) : null;
- }
-
- // Properties.
- public string Peer { get; }
- public ChequePayment? LastReceived { get; }
- public ChequePayment? LastSent { get; }
- }
-}
diff --git a/src/BeeNet/Models/ConnectedPeers.cs b/src/BeeNet/Models/ConnectedPeers.cs
deleted file mode 100644
index 41645152..00000000
--- a/src/BeeNet/Models/ConnectedPeers.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class ConnectedPeers
- {
- // Constructors.
- internal ConnectedPeers(Clients.ConnectedPeers connectedPeers)
- {
- ArgumentNullException.ThrowIfNull(connectedPeers, nameof(connectedPeers));
-
- Address = connectedPeers.Address;
- LastSeenTimestamp = connectedPeers.Metrics.LastSeenTimestamp;
- SessionConnectionRetry = connectedPeers.Metrics.SessionConnectionRetry;
- ConnectionTotalDuration = connectedPeers.Metrics.ConnectionTotalDuration;
- SessionConnectionDuration = connectedPeers.Metrics.SessionConnectionDuration;
- SessionConnectionDirection = connectedPeers.Metrics.SessionConnectionDirection;
- LatencyEWMA = connectedPeers.Metrics.LatencyEWMA;
- }
-
- // Properties.
- public string Address { get; }
- public int LastSeenTimestamp { get; }
- public int SessionConnectionRetry { get; }
- public double ConnectionTotalDuration { get; }
- public double SessionConnectionDuration { get; }
- public string SessionConnectionDirection { get; }
- public int LatencyEWMA { get; }
- }
-
-}
diff --git a/src/BeeNet/Models/Health.cs b/src/BeeNet/Models/Health.cs
deleted file mode 100644
index c2548d73..00000000
--- a/src/BeeNet/Models/Health.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class Health
- {
- // Constructors.
- internal Health(Clients.Response9 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- StatusIsOk = response.Status switch
- {
- Clients.Response9Status.Ok => true,
- Clients.Response9Status.Nok => false,
- _ => throw new InvalidOperationException()
- };
- Version = response.Version;
- ApiVersion = response.ApiVersion;
- DebugApiVersion = response.DebugApiVersion;
- }
-
- internal Health(Clients.Response21 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- StatusIsOk = response.Status switch
- {
- Clients.Response21Status.Ok => true,
- Clients.Response21Status.Nok => false,
- _ => throw new InvalidOperationException()
- };
- Version = response.Version;
- ApiVersion = response.ApiVersion;
- DebugApiVersion = response.DebugApiVersion;
- }
-
- internal Health(Clients.Response40 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- StatusIsOk = response.Status switch
- {
- Clients.Response40Status.Ok => true,
- Clients.Response40Status.Nok => false,
- _ => throw new InvalidOperationException()
- };
- Version = response.Version;
- ApiVersion = response.ApiVersion;
- DebugApiVersion = response.DebugApiVersion;
- }
-
- // Properties.
- public bool StatusIsOk { get; }
- public string Version { get; }
- public string ApiVersion { get; }
- public string DebugApiVersion { get; }
- }
-}
diff --git a/src/BeeNet/Models/LogData.cs b/src/BeeNet/Models/LogData.cs
deleted file mode 100644
index d7f33e45..00000000
--- a/src/BeeNet/Models/LogData.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class LogData
- {
- // Constructors.
- internal LogData(Clients.Response63 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Tree = response.Tree.ToDictionary(i => i.Key, i => i.Value?.Plus?.ToList() ?? new List());
- Loggers = response.Loggers.Select(i => new Loggers(i)).ToList();
- }
-
- internal LogData(Clients.Response64 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Tree = response.Tree.ToDictionary(i => i.Key, i => i.Value?.Plus?.ToList() ?? new List());
- Loggers = response.Loggers.Select(i => new Loggers(i)).ToList();
- }
-
- // Properties.
- public IDictionary> Tree { get; }
- public ICollection Loggers { get; }
- }
-}
diff --git a/src/BeeNet/Models/Loggers.cs b/src/BeeNet/Models/Loggers.cs
deleted file mode 100644
index 3c25227e..00000000
--- a/src/BeeNet/Models/Loggers.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class Loggers
- {
- // Constructors.
- internal Loggers(Clients.Loggers loggers)
- {
- ArgumentNullException.ThrowIfNull(loggers, nameof(loggers));
-
- Id = loggers.Id;
- Logger = loggers.Logger;
- Subsystem = loggers.Subsystem;
- Verbosity = loggers.Verbosity;
- }
-
- internal Loggers(Clients.Loggers2 loggers)
- {
- ArgumentNullException.ThrowIfNull(loggers, nameof(loggers));
-
- Id = loggers.Id;
- Logger = loggers.Logger;
- Subsystem = loggers.Subsystem;
- Verbosity = loggers.Verbosity;
- }
-
- // Properties.
- public string Id { get; set; }
- public string Logger { get; set; }
- public string Subsystem { get; set; }
- public string Verbosity { get; set; }
- }
-}
diff --git a/src/BeeNet/Models/MessageResponse.cs b/src/BeeNet/Models/MessageResponse.cs
deleted file mode 100644
index e22a3d2c..00000000
--- a/src/BeeNet/Models/MessageResponse.cs
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class MessageResponse
- {
- // Constructors.
- internal MessageResponse(Clients.Response10 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Message = response.Message;
- Code = response.Code;
- }
-
- internal MessageResponse(Clients.Response12 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Message = response.Message;
- Code = response.Code;
- }
-
- internal MessageResponse(Clients.Response33 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- Message = response.Message;
- Code = response.Code;
- }
-
- // Properties.
- public string Message { get; }
- public int Code { get; }
- }
-}
diff --git a/src/BeeNet/Models/NodeInfo.cs b/src/BeeNet/Models/NodeInfo.cs
deleted file mode 100644
index c1b94354..00000000
--- a/src/BeeNet/Models/NodeInfo.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class NodeInfo
- {
- // Constructors.
- internal NodeInfo(Clients.Response31 response)
- {
- ArgumentNullException.ThrowIfNull(response, nameof(response));
-
- BeeMode = response.BeeMode switch
- {
- Clients.Response31BeeMode.Dev => InfoBeeMode.Dev,
- Clients.Response31BeeMode.Full => InfoBeeMode.Full,
- Clients.Response31BeeMode.Light => InfoBeeMode.Light,
- _ => throw new InvalidOperationException()
- };
- ChequebookEnabled = response.ChequebookEnabled;
- SwapEnabled = response.SwapEnabled;
- }
-
- // Methods.
- ///
- /// Gives back in what mode the Bee client has been started. The modes are mutually exclusive * `light` - light node; does not participate in forwarding or storing chunks * `full` - full node * `dev` - development mode; Bee client for development purposes, blockchain operations are mocked
- ///
- public InfoBeeMode BeeMode { get; }
- public bool ChequebookEnabled { get; }
- public bool SwapEnabled { get; }
- }
-}
diff --git a/src/BeeNet/Models/PeerBalance.cs b/src/BeeNet/Models/PeerBalance.cs
deleted file mode 100644
index f1f161bc..00000000
--- a/src/BeeNet/Models/PeerBalance.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-using System.Globalization;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class PeerBalance
- {
- // Constructors.
- internal PeerBalance(Clients.Balances balance)
- {
- ArgumentNullException.ThrowIfNull(balance, nameof(balance));
-
- Peer = balance.Peer;
- Balance = BzzBalance.FromPlurString(balance.Balance);
- }
-
- internal PeerBalance(Clients.Balances2 balance)
- {
- ArgumentNullException.ThrowIfNull(balance, nameof(balance));
-
- Peer = balance.Peer;
- Balance = BzzBalance.FromPlurString(balance.Balance);
- }
-
- internal PeerBalance(Clients.Response23 balance)
- {
- ArgumentNullException.ThrowIfNull(balance, nameof(balance));
-
- Peer = balance.Peer;
- Balance = BzzBalance.FromPlurString(balance.Balance);
- }
-
- internal PeerBalance(Clients.Response25 balance)
- {
- ArgumentNullException.ThrowIfNull(balance, nameof(balance));
-
- Peer = balance.Peer;
- Balance = BzzBalance.FromPlurString(balance.Balance);
- }
-
- // Properties.
- public string Peer { get; }
- public BzzBalance Balance { get; }
- }
-}
diff --git a/src/BeeNet/Models/PeerMetrics.cs b/src/BeeNet/Models/PeerMetrics.cs
deleted file mode 100644
index ec727259..00000000
--- a/src/BeeNet/Models/PeerMetrics.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class PeerMetrics
- {
- // Constructors
- internal PeerMetrics(Clients.Metrics metrics)
- {
- ArgumentNullException.ThrowIfNull(metrics, nameof(metrics));
-
- LastSeenTimestamp = metrics.LastSeenTimestamp;
- SessionConnectionRetry = metrics.SessionConnectionRetry;
- ConnectionTotalDuration = metrics.ConnectionTotalDuration;
- SessionConnectionDuration = metrics.SessionConnectionDuration;
- SessionConnectionDirection = metrics.SessionConnectionDirection;
- LatencyEWMA = metrics.LatencyEWMA;
- }
-
- // Properties.
- public int LastSeenTimestamp { get; }
- public int SessionConnectionRetry { get; }
- public double ConnectionTotalDuration { get; }
- public double SessionConnectionDuration { get; }
- public string SessionConnectionDirection { get; }
- public int LatencyEWMA { get; }
- }
-}
diff --git a/src/BeeNet/Models/PeersAggregate.cs b/src/BeeNet/Models/PeersAggregate.cs
deleted file mode 100644
index 4a66baf1..00000000
--- a/src/BeeNet/Models/PeersAggregate.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2021-present Etherna SA
-// This file is part of Bee.Net.
-//
-// Bee.Net is free software: you can redistribute it and/or modify it under the terms of the
-// GNU Lesser General Public License as published by the Free Software Foundation,
-// either version 3 of the License, or (at your option) any later version.
-//
-// Bee.Net is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-// See the GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License along with Bee.Net.
-// If not, see .
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-
-namespace Etherna.BeeNet.Models
-{
- public sealed class PeersAggregate
- {
- // Constructors.
- internal PeersAggregate(Clients.Anonymous2 anonymous)
- {
- ArgumentNullException.ThrowIfNull(anonymous, nameof(anonymous));
-
- Population = anonymous.Population;
- Connected = anonymous.Connected;
- DisconnectedPeers = anonymous.DisconnectedPeers
- ?.Select(k => new DisconnectedPeers(k)) ?? new List();
- ConnectedPeers = anonymous.ConnectedPeers
- ?.Select(k => new ConnectedPeers(k)) ?? new List();
- }
-
- // Properties.
- public int Population { get; }
- public int Connected { get; }
- public IEnumerable