Skip to content

Commit

Permalink
Introduce IReadOnlyStateProvider and ChainHeadReadOnlyStateProvider/C… (
Browse files Browse the repository at this point in the history
#2526)

* Introduce IReadOnlyStateProvider and ChainHeadReadOnlyStateProvider/ChainHeadStateProvider

* fix json debug log

* Add docs + comments for StateProvider

* docs + NDM fix
  • Loading branch information
LukaszRozmej committed Nov 30, 2020
1 parent 3c4bb97 commit 580fc53
Show file tree
Hide file tree
Showing 17 changed files with 176 additions and 50 deletions.
8 changes: 8 additions & 0 deletions src/Nethermind/Nethermind.Api/IApiWithBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,15 @@ public interface IApiWithBlockchain : IApiWithStores, IBlockchainBridgeFactory
IRewardCalculatorSource? RewardCalculatorSource { get; set; }
ISealer? Sealer { get; set; }
ISealValidator? SealValidator { get; set; }

/// <summary>
/// Can be used only for processing blocks, on all other contexts use <see cref="StateReader"/> or <see cref="ChainHeadStateProvider"/>.
/// </summary>
/// <remarks>
/// DO NOT USE OUTSIDE OF PROCESSING BLOCK CONTEXT!
/// </remarks>
IStateProvider? StateProvider { get; set; }
IReadOnlyStateProvider? ChainHeadStateProvider { get; set; }
IStateReader? StateReader { get; set; }
IStorageProvider? StorageProvider { get; set; }
ITransactionProcessor? TransactionProcessor { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) 2018 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library 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.
//
// The Nethermind library 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 the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Int256;
using Nethermind.State;
using Nethermind.Trie;

namespace Nethermind.Blockchain
{
public class ChainHeadReadOnlyStateProvider : IReadOnlyStateProvider
{
private readonly IBlockTree _blockTree;
private readonly IStateReader _stateReader;

public ChainHeadReadOnlyStateProvider(IBlockTree blockTree, IStateReader stateReader)
{
_blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
_stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader));
}

public Keccak StateRoot => _blockTree.Head?.StateRoot ?? Keccak.EmptyTreeHash;

public Account GetAccount(Address address) => _stateReader.GetAccount(StateRoot, address);

public UInt256 GetNonce(Address address) => _stateReader.GetNonce(StateRoot, address);

public UInt256 GetBalance(Address address) => _stateReader.GetBalance(StateRoot, address);

public Keccak GetStorageRoot(Address address) => _stateReader.GetStorageRoot(StateRoot, address);

public byte[] GetCode(Address address) => _stateReader.GetCode(StateRoot, address);

public byte[] GetCode(Keccak codeHash) => _stateReader.GetCode(codeHash);

public Keccak GetCodeHash(Address address)
{
Account account = GetAccount(address);
return account?.CodeHash ?? Keccak.OfAnEmptyString;
}

public void Accept(ITreeVisitor visitor, Keccak stateRoot)
{
_stateReader.RunTreeVisitor(visitor, stateRoot);
}

public bool AccountExists(Address address) => GetAccount(address) != null;


public bool IsEmptyAccount(Address address) => GetAccount(address).IsEmpty;

public bool IsDeadAccount(Address address)
{
Account account = GetAccount(address);
return account?.IsEmpty ?? true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ public partial interface IValidatorContract

public sealed partial class ValidatorContract : CallableContract, IValidatorContract
{
private readonly IAbiEncoder _abiEncoder;
private readonly IStateProvider _stateProvider;
private readonly ISigner _signer;

Expand All @@ -80,7 +79,6 @@ public sealed partial class ValidatorContract : CallableContract, IValidatorCont
ISigner signer)
: base(transactionProcessor, abiEncoder, contractAddress)
{
_abiEncoder = abiEncoder ?? throw new ArgumentNullException(nameof(abiEncoder));
_stateProvider = stateProvider ?? throw new ArgumentNullException(nameof(stateProvider));
_signer = signer ?? throw new ArgumentNullException(nameof(signer));
Constant = GetConstant(readOnlyTransactionProcessorSource);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public class PermissionBasedTxFilter : ITxFilter
{
private readonly VersionedContract<ITransactionPermissionContract> _contract;
private readonly Cache _cache;
private readonly IStateProvider _stateProvider;
private readonly IReadOnlyStateProvider _stateProvider;
private readonly ILogger _logger;

public PermissionBasedTxFilter(
VersionedContract<ITransactionPermissionContract> contract,
Cache cache,
IStateProvider stateProvider,
IReadOnlyStateProvider stateProvider,
ILogManager logManager)
{
_contract = contract ?? throw new ArgumentNullException(nameof(contract));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public partial class ReportingContractBasedValidator : IAuRaValidator, IReportin
private readonly ContractBasedValidator _contractValidator;
private readonly long _posdaoTransition;
private readonly ITxSender _posdaoTxSender;
private readonly IStateProvider _stateProvider;
private readonly IReadOnlyStateProvider _stateProvider;
private readonly Cache _cache;
private readonly ITxSender _nonPosdaoTxSender;
private readonly ILogger _logger;
Expand All @@ -60,7 +60,7 @@ public partial class ReportingContractBasedValidator : IAuRaValidator, IReportin
ITxSender txSender,
ITxPool txPool,
IMiningConfig miningConfig,
IStateProvider stateProvider,
IReadOnlyStateProvider stateProvider,
Cache cache,
ILogManager logManager)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ public void Init()
transactionVerifier, gasPriceService, timestamper, logManager);
_api.AccountService = new AccountService(configManager, dataStreamService, providerService,
sessionService, consumerNotifier, wallet, configId, consumerAddress, logManager);
_api.NdmAccountUpdater = new NdmAccountUpdater(ndmWebSocketsModule, consumerAddress, _api.MainBlockProcessor, _api.StateProvider);
_api.NdmAccountUpdater = new NdmAccountUpdater(ndmWebSocketsModule, consumerAddress, _api.MainBlockProcessor, _api.ChainHeadStateProvider);
ProxyService proxyService = new ProxyService(jsonRpcClientProxy, configManager, configId, logManager);
_api.ConsumerService = new ConsumerService(_api.AccountService, dataAssetService, dataRequestService,
dataConsumerService, dataStreamService, depositManager, depositApprovalService, providerService,
Expand Down
12 changes: 12 additions & 0 deletions src/Nethermind/Nethermind.DataMarketplace.Infrastructure/NdmApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -364,12 +364,24 @@ public IMonitoringService MonitoringService
set => _nethermindApi.SyncServer = value;
}

/// <summary>
/// Can be used only for processing blocks, on all other contexts use <see cref="StateReader"/> or <see cref="ChainHeadStateProvider"/>.
/// </summary>
/// <remarks>
/// DO NOT USE OUTSIDE OF PROCESSING BLOCK CONTEXT!
/// </remarks>
public IStateProvider? StateProvider
{
get => _nethermindApi.StateProvider;
set => _nethermindApi.StateProvider = value;
}

public IReadOnlyStateProvider? ChainHeadStateProvider
{
get => _nethermindApi.ChainHeadStateProvider;
set => _nethermindApi.ChainHeadStateProvider = value;
}

public IStateReader? StateReader
{
get => _nethermindApi.StateReader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ public class NdmAccountUpdater : INdmAccountUpdater
private readonly Address _accountAddress;
private readonly Address? _coldWalletAddress;
private readonly IBlockProcessor _blockProcessor;
private readonly IStateProvider _stateProvider;
private readonly IReadOnlyStateProvider _stateProvider;
private UInt256? _balance;
private UInt256? _coldBalance;
private UInt256? _nonce;
private UInt256? _coldNonce;

public NdmAccountUpdater(IWebSocketsModule module, Address accountAddress, IBlockProcessor blockProcessor, IStateProvider stateProvider, Address? coldWalletAddress = null)
public NdmAccountUpdater(IWebSocketsModule module, Address accountAddress, IBlockProcessor blockProcessor, IReadOnlyStateProvider stateProvider, Address? coldWalletAddress = null)
{
_blockProcessor = blockProcessor ?? throw new ArgumentNullException(nameof(blockProcessor));
_webSocketsModule = module ?? throw new ArgumentNullException(nameof(module));
Expand Down Expand Up @@ -90,4 +90,4 @@ private async void UpdateColdWalletNonce(object? sender, BlockProcessedEventArgs
await _webSocketsModule.SendAsync(new WebSocketsMessage("update-cold-nonce", "", _coldNonce));
}
}
}
}
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.JsonRpc/JsonRpcProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ public async Task<JsonRpcResult> ProcessAsync(string request)
}

singleRequestWatch.Stop();
if (_logger.IsDebug) _logger.Debug($" {requestIndex++}/{rpcRequest.Collection.Count} JSON RPC request - {jsonRpcRequest} handled after {singleRequestWatch.Elapsed.TotalMilliseconds}");
if (_logger.IsDebug) _logger.Debug($" {++requestIndex}/{rpcRequest.Collection.Count} JSON RPC request - {jsonRpcRequest} handled after {singleRequestWatch.Elapsed.TotalMilliseconds}");
responses.Add(response);
reports.Add(new RpcReport(jsonRpcRequest.Method, singleRequestWatch.ElapsedMicroseconds(), isSuccess));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public IBlockchainBridge CreateBlockchainBridge()
public ISynchronizer? Synchronizer { get; set; }
public ISyncServer? SyncServer { get; set; }
public IStateProvider? StateProvider { get; set; }
public IReadOnlyStateProvider? ChainHeadStateProvider { get; set; }
public IStateReader? StateReader { get; set; }
public IStorageProvider? StorageProvider { get; set; }
public IStaticNodesManager? StaticNodesManager { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ protected virtual Task InitBlockchain()
_get.DbProvider.StateDb,
_get.DbProvider.CodeDb,
_get.LogManager);

ReadOnlyDbProvider readOnly = new ReadOnlyDbProvider(_api.DbProvider, false);
var stateReader = _set.StateReader = new StateReader(readOnly.StateDb, readOnly.CodeDb, _api.LogManager);
_set.ChainHeadStateProvider = new ChainHeadReadOnlyStateProvider(_get.BlockTree, stateReader);


PersistentTxStorage txStorage = new PersistentTxStorage(_get.DbProvider.PendingTxsDb);

Expand Down Expand Up @@ -136,8 +141,6 @@ protected virtual Task InitBlockchain()
_get.SpecProvider,
_get.LogManager);

ReadOnlyDbProvider readOnly = new ReadOnlyDbProvider(_api.DbProvider, false);
_set.StateReader = new StateReader(readOnly.StateDb, readOnly.CodeDb, _api.LogManager);
_set.TxPoolInfoProvider = new TxPoolInfoProvider(_api.StateReader, _api.TxPool);

var mainBlockProcessor = _set.MainBlockProcessor = CreateBlockProcessor();
Expand Down Expand Up @@ -192,7 +195,7 @@ protected virtual Task InitBlockchain()
_api.EthereumEcdsa,
_api.SpecProvider,
_api.Config<ITxPoolConfig>(),
_api.StateProvider,
_api.ChainHeadStateProvider,
_api.LogManager,
CreateTxPoolTxComparer());

Expand Down Expand Up @@ -230,4 +233,4 @@ protected virtual void InitSealEngine()
{
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public InitializeBlockchainAuRa(AuRaNethermindApi api) : base(api)
protected override BlockProcessor CreateBlockProcessor()
{
if (_api.SpecProvider == null) throw new StepDependencyException(nameof(_api.SpecProvider));
if (_api.ChainHeadStateProvider == null) throw new StepDependencyException(nameof(_api.ChainHeadStateProvider));
if (_api.BlockValidator == null) throw new StepDependencyException(nameof(_api.BlockValidator));
if (_api.RewardCalculatorSource == null) throw new StepDependencyException(nameof(_api.RewardCalculatorSource));
if (_api.TransactionProcessor == null) throw new StepDependencyException(nameof(_api.TransactionProcessor));
Expand All @@ -69,7 +70,7 @@ protected override BlockProcessor CreateBlockProcessor()

var processingReadOnlyTransactionProcessorSource = new ReadOnlyTxProcessorSource(_api.DbProvider, _api.BlockTree, _api.SpecProvider, _api.LogManager);
var txPermissionFilterOnlyTxProcessorSource = new ReadOnlyTxProcessorSource(_api.DbProvider, _api.BlockTree, _api.SpecProvider, _api.LogManager);
ITxFilter? txPermissionFilter = TxFilterBuilders.CreateTxPermissionFilter(_api, txPermissionFilterOnlyTxProcessorSource, _api.StateProvider);
ITxFilter? txPermissionFilter = TxFilterBuilders.CreateTxPermissionFilter(_api, txPermissionFilterOnlyTxProcessorSource, _api.ChainHeadStateProvider);

var processor = new AuRaBlockProcessor(
_api.SpecProvider,
Expand Down Expand Up @@ -253,15 +254,15 @@ protected override TxPool.TxPool CreateTxPool(PersistentTxStorage txStorage)
NethermindApi.Config<IMiningConfig>(),
_api,
txPoolReadOnlyTransactionProcessorSource,
_api.StateProvider!,
_api.ChainHeadStateProvider!,
minGasPricesContractDataStore);

return new FilteredTxPool(
txStorage,
_api.EthereumEcdsa,
_api.SpecProvider,
NethermindApi.Config<ITxPoolConfig>(),
_api.StateProvider,
_api.ChainHeadStateProvider,
_api.LogManager,
CreateTxPoolTxComparer(txPriorityContract, localDataSource),
new TxFilterAdapter(_api.BlockTree, txPoolFilter));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static ITxFilter CreateStandardTxFilter(IMiningConfig miningConfig)
return gasPriceTxFilter;
}

public static ITxFilter? CreateTxPermissionFilter(AuRaNethermindApi api, IReadOnlyTransactionProcessorSource readOnlyTxProcessorSource, IStateProvider stateProvider)
public static ITxFilter? CreateTxPermissionFilter(AuRaNethermindApi api, IReadOnlyTransactionProcessorSource readOnlyTxProcessorSource, IReadOnlyStateProvider stateProvider)
{
if (api.ChainSpec == null) throw new StepDependencyException(nameof(api.ChainSpec));

Expand Down Expand Up @@ -88,7 +88,7 @@ public static ITxFilter CreateStandardTxFilter(IMiningConfig miningConfig)
IMiningConfig miningConfig,
AuRaNethermindApi api,
IReadOnlyTransactionProcessorSource readOnlyTxProcessorSource,
IStateProvider stateProvider,
IReadOnlyStateProvider stateProvider,
IDictionaryContractDataStore<TxPriorityContract.Destination>? minGasPricesContractDataStore)
{
ITxFilter baseAuRaTxFilter = CreateBaseAuRaTxFilter(miningConfig, api, readOnlyTxProcessorSource, minGasPricesContractDataStore);
Expand Down
51 changes: 51 additions & 0 deletions src/Nethermind/Nethermind.State/IReadOnlyStateProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2018 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library 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.
//
// The Nethermind library 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 the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.Int256;
using Nethermind.Trie;

namespace Nethermind.State
{
public interface IReadOnlyStateProvider
{
Keccak StateRoot { get; }

Account GetAccount(Address address);

UInt256 GetNonce(Address address);

UInt256 GetBalance(Address address);

Keccak GetStorageRoot(Address address);

byte[] GetCode(Address address);

byte[] GetCode(Keccak codeHash);

Keccak GetCodeHash(Address address);

void Accept(ITreeVisitor visitor, Keccak stateRoot);

bool AccountExists(Address address);

bool IsDeadAccount(Address address);

bool IsEmptyAccount(Address address);
}
}

0 comments on commit 580fc53

Please sign in to comment.