// https://github.com/ethereum/EIPs/issues/1186 public ResultWrapper <AccountProof> eth_getProof(Address accountAddress, byte[][] storageKeys, BlockParameter blockParameter) { BlockHeader header; try { header = _blockchainBridge.FindHeader(blockParameter); if (header == null) { return(ResultWrapper <AccountProof> .Fail($"{blockParameter} block not found", ErrorCodes.ResourceNotFound, null)); } } catch (Exception ex) { return(ResultWrapper <AccountProof> .Fail(ex.Message, ErrorCodes.InternalError, null)); } AccountProofCollector accountProofCollector = new AccountProofCollector(accountAddress, storageKeys); _blockchainBridge.RunTreeVisitor(accountProofCollector, header.StateRoot); return(ResultWrapper <AccountProof> .Success(accountProofCollector.BuildResult())); }
private async Task <ResultWrapper <Keccak> > SendTx(Transaction tx, TxHandlingOptions txHandlingOptions = TxHandlingOptions.None) { try { Keccak txHash = await _txSender.SendTransaction(tx, txHandlingOptions | TxHandlingOptions.PersistentBroadcast); return(ResultWrapper <Keccak> .Success(txHash)); } catch (SecurityException e) { return(ResultWrapper <Keccak> .Fail(e.Message, ErrorCodes.AccountLocked)); } catch (Exception e) { if (_logger.IsError) { _logger.Error("Failed to send transaction.", e); } return(ResultWrapper <Keccak> .Fail(e.Message, ErrorCodes.TransactionRejected)); } }
public Task <ResultWrapper <bool> > baseline_track(Address contractAddress) { ResultWrapper <bool> result; // can potentially warn user if tree is not deployed at the address if (contractAddress == null) { result = ResultWrapper <bool> .Fail("Contract address was NULL"); } else if (TryAddTree(contractAddress)) { UpdateMetadata(contractAddress); result = ResultWrapper <bool> .Success(true); } else { result = ResultWrapper <bool> .Fail( $"{contractAddress} is already tracked or no contract at given address", ErrorCodes.InvalidInput); } return(Task.FromResult(result)); }
public ResultWrapper <byte[]> eth_sign(Address addressData, byte[] message) { Signature sig; try { Address address = addressData; string messageText = _messageEncoding.GetString(message); const string signatureTemplate = "\x19Ethereum Signed Message:\n{0}{1}"; string signatureText = string.Format(signatureTemplate, messageText.Length, messageText); sig = _blockchainBridge.Sign(address, Keccak.Compute(signatureText)); } catch (Exception) { return(ResultWrapper <byte[]> .Fail($"Unable to sign as {addressData}")); } if (_logger.IsTrace) { _logger.Trace($"eth_sign request {addressData}, {message}, result: {sig}"); } return(ResultWrapper <byte[]> .Success(sig.Bytes)); }
public ResultWrapper <TransactionForRpc> eth_getTransactionByHash(Keccak transactionHash) { try { _readerWriterLockSlim.EnterReadLock(); (Core.TransactionReceipt receipt, Transaction transaction) = _blockchainBridge.GetTransaction(transactionHash); if (transaction == null) { return(ResultWrapper <TransactionForRpc> .Fail($"Cannot find transaction for hash: {transactionHash}", ErrorType.NotFound)); } var transactionModel = new TransactionForRpc(receipt.BlockHash, receipt.BlockNumber, receipt.Index, transaction); if (Logger.IsTrace) { Logger.Trace($"eth_getTransactionByHash request {transactionHash}, result: {transactionModel.Hash}"); } return(ResultWrapper <TransactionForRpc> .Success(transactionModel)); } finally { _readerWriterLockSlim.ExitReadLock(); } }
public ValueTask <ResultWrapper <Keccak> > deposit_deploy(Address senderAddress) { ResultWrapper <Keccak> result; if (_depositContract == null) { result = ResultWrapper <Keccak> .Fail("Deposit contract address not specified.", ErrorCodes.InternalError); return(new ValueTask <ResultWrapper <Keccak> >(result)); } Transaction tx = _depositContract.Deploy(senderAddress); Keccak txHash = _txPoolBridge.SendTransaction(tx, TxHandlingOptions.ManagedNonce); if (_logger.IsInfo) { _logger.Info($"Sent transaction at price {tx.GasPrice} to {tx.SenderAddress}"); } result = ResultWrapper <Keccak> .Success(txHash); return(new ValueTask <ResultWrapper <Keccak> >(result)); }
public ResultWrapper <BlockForRpc> eth_getBlockByHash(Keccak blockHash, bool returnFullTransactionObjects) { try { _readerWriterLockSlim.EnterReadLock(); var block = _blockchainBridge.FindBlock(blockHash, false); if (block == null) { return(ResultWrapper <BlockForRpc> .Fail($"Cannot find block for hash: {blockHash}", ErrorType.NotFound)); } if (Logger.IsDebug) { Logger.Debug($"eth_getBlockByHash request {blockHash}, result: {block}"); } return(ResultWrapper <BlockForRpc> .Success(new BlockForRpc(block, returnFullTransactionObjects))); } finally { _readerWriterLockSlim.ExitReadLock(); } }
private ResultWrapper <Core.Block> GetBlock(BlockParameter blockParameter) { switch (blockParameter.Type) { case BlockParameterType.Pending: var pending = _blockchainBridge.FindBlock(_blockchainBridge.BestSuggested.Hash, false); return(ResultWrapper <Core.Block> .Success(pending)); // TODO: a pending block for sealEngine, work in progress case BlockParameterType.Latest: return(ResultWrapper <Core.Block> .Success(_blockchainBridge.RetrieveHeadBlock())); case BlockParameterType.Earliest: var genesis = _blockchainBridge.RetrieveGenesisBlock(); return(ResultWrapper <Core.Block> .Success(genesis)); case BlockParameterType.BlockId: if (blockParameter.BlockId?.Value == null) { return(ResultWrapper <Core.Block> .Fail($"Block id is required for {BlockParameterType.BlockId}", ErrorType.InvalidParams)); } var value = blockParameter.BlockId.GetValue(); if (!value.HasValue) { return(ResultWrapper <Core.Block> .Fail("Invalid block id", ErrorType.InvalidParams)); } throw new NotImplementedException(); // TODO: TKS - discuss with me later, there was a rebuilt of BlockStore / Blockchain, work in progress now, so just commenting it out // var block = _blockTree.FindBlock(value.Value); // if (block == null) // { // return ResultWrapper<Core.Block>.Fail($"Cannot find block for {value.Value}", ErrorType.NotFound); // } // return ResultWrapper<Core.Block>.Success(block); default: throw new Exception($"BlockParameterType not supported: {blockParameter.Type}"); } }
public ResultWrapper <Block> eth_getUncleByBlockNumberAndIndex(BlockParameter blockParameter, Quantity positionIndex) { if (_blockchainBridge.Head == null) { return(ResultWrapper <Block> .Fail($"Incorrect head block: {(_blockchainBridge.Head != null ? "HeadBlock is null" : "HeadBlock header is null")}")); } var result = GetBlock(blockParameter); if (result.Result.ResultType == ResultType.Failure) { return(ResultWrapper <Block> .Fail(result.Result.Error, result.ErrorType)); } var index = positionIndex.GetValue(); if (!index.HasValue) { return(ResultWrapper <Block> .Fail("Position Index is required", ErrorType.InvalidParams)); } if (index.Value < 0 || index.Value > result.Data.Ommers.Length - 1) { return(ResultWrapper <Block> .Fail("Position Index is incorrect", ErrorType.InvalidParams)); } var ommerHeader = result.Data.Ommers[(int)index.Value]; var ommer = _blockchainBridge.FindBlock(ommerHeader.Hash, false); if (ommer == null) { return(ResultWrapper <Block> .Fail($"Cannot find ommer for hash: {ommerHeader.Hash}", ErrorType.NotFound)); } var blockModel = _modelMapper.MapBlock(ommer, false); Logger.Debug($"eth_getUncleByBlockNumberAndIndex request {blockParameter}, index: {positionIndex.ToJson()}, result: {GetJsonLog(blockModel.ToJson())}"); return(ResultWrapper <Block> .Success(blockModel)); }
public Task <ResultWrapper <Keccak> > baseline_getRoot( Address contractAddress, BlockParameter?blockParameter = null) { bool isTracked = TryGetTracked(contractAddress, out BaselineTree? tree); ResultWrapper <Keccak> result; if (!isTracked || tree == null) { result = ResultWrapper <Keccak> .Fail( $"{contractAddress} tree is not tracked", ErrorCodes.InvalidInput); } else { if (blockParameter == null || blockParameter == BlockParameter.Latest) { result = ResultWrapper <Keccak> .Success(tree.Root); } else { SearchResult <BlockHeader> searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { result = ResultWrapper <Keccak> .Fail(searchResult); } else { var historicalTree = _baselineTreeHelper.CreateHistoricalTree(contractAddress, searchResult.Object.Number); result = ResultWrapper <Keccak> .Success(historicalTree.Root); } } } return(Task.FromResult(result)); }
private ResultWrapper <Core.Block> GetBlock(BlockParameter blockParameter) { switch (blockParameter.Type) { case BlockParameterType.Pending: var pending = _blockchainBridge.FindBlock(_blockchainBridge.BestSuggested.Hash, false); return(ResultWrapper <Core.Block> .Success(pending)); // TODO: a pending block for sealEngine, work in progress case BlockParameterType.Latest: return(ResultWrapper <Core.Block> .Success(_blockchainBridge.RetrieveHeadBlock())); case BlockParameterType.Earliest: var genesis = _blockchainBridge.RetrieveGenesisBlock(); return(ResultWrapper <Core.Block> .Success(genesis)); case BlockParameterType.BlockId: if (blockParameter.BlockId?.Value == null) { return(ResultWrapper <Core.Block> .Fail($"Block id is required for {BlockParameterType.BlockId}", ErrorType.InvalidParams)); } var value = blockParameter.BlockId.GetValue(); if (!value.HasValue) { return(ResultWrapper <Core.Block> .Fail("Invalid block id", ErrorType.InvalidParams)); } var block = _blockchainBridge.FindBlock(new UInt256(value.Value)); if (block == null) { return(ResultWrapper <Core.Block> .Fail($"Cannot find block for {value.Value}", ErrorType.NotFound)); } return(ResultWrapper <Core.Block> .Success(block)); default: throw new Exception($"BlockParameterType not supported: {blockParameter.Type}"); } }
public ResultWrapper <TransactionForRpc> eth_getTransactionByBlockHashAndIndex(Keccak blockHash, UInt256 positionIndex) { SearchResult <Block> searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); if (searchResult.IsError) { return(ResultWrapper <TransactionForRpc> .Fail(searchResult)); } Block block = searchResult.Object; if (positionIndex < 0 || positionIndex > block.Transactions.Length - 1) { return(ResultWrapper <TransactionForRpc> .Fail("Position Index is incorrect", ErrorCodes.InvalidParams)); } Transaction transaction = block.Transactions[(int)positionIndex]; RecoverTxSenderIfNeeded(transaction); TransactionForRpc transactionModel = new TransactionForRpc(block.Hash, block.Number, (int)positionIndex, transaction); return(ResultWrapper <TransactionForRpc> .Success(transactionModel)); }
public ResultWrapper <string> eth_call(TransactionForRpc transactionCall, BlockParameter blockParameter = null) { SearchResult <BlockHeader> searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { return(ResultWrapper <string> .Fail(searchResult)); } BlockHeader header = searchResult.Object; if (!HasStateForBlock(header)) { return(ResultWrapper <string> .Fail($"No state available for block {header.Hash}", ErrorCodes.ResourceUnavailable)); } FixCallTx(transactionCall, header); Transaction tx = transactionCall.ToTransaction(); BlockchainBridge.CallOutput result = _blockchainBridge.Call(header, tx); return(result.Error != null ? ResultWrapper <string> .Fail("VM execution error.", ErrorCodes.ExecutionError, result.Error) : ResultWrapper <string> .Success(result.OutputData.ToHexString(true))); }
public async Task <ResultWrapper <Keccak> > baseline_deploy(Address address, string contractType) { ResultWrapper <Keccak> result; try { var bytecode = await GetContractBytecode(contractType); try { Keccak txHash = await DeployBytecode(address, contractType, bytecode); result = ResultWrapper <Keccak> .Success(txHash); } catch (Exception e) { result = ResultWrapper <Keccak> .Fail( $"Provided bytecode could not be deployed. {e}", ErrorCodes.InternalError); } } catch (IOException e) { result = ResultWrapper <Keccak> .Fail( $"{contractType} bytecode could not be loaded. {e}", ErrorCodes.ResourceNotFound); } catch (Exception e) { result = ResultWrapper <Keccak> .Fail( $"{contractType} bytecode could not be loaded. {e}", ErrorCodes.InternalError); } return(result); }
public ResultWrapper <Transaction> eth_getTransactionByBlockNumberAndIndex(BlockParameter blockParameter, Quantity positionIndex) { if (_blockchainBridge.Head == null) { return(ResultWrapper <Transaction> .Fail($"Incorrect head block: {(_blockchainBridge.Head != null ? "HeadBlock is null" : "HeadBlock header is null")}")); } var result = GetBlock(blockParameter); if (result.Result.ResultType == ResultType.Failure) { return(ResultWrapper <Transaction> .Fail(result.Result.Error, result.ErrorType)); } var index = positionIndex.AsNumber(); if (!index.HasValue) { return(ResultWrapper <Transaction> .Fail("Position Index is required", ErrorType.InvalidParams)); } if (index.Value < 0 || index.Value > result.Data.Transactions.Length - 1) { return(ResultWrapper <Transaction> .Fail("Position Index is incorrect", ErrorType.InvalidParams)); } Core.Block block = result.Data; var transaction = block.Transactions[(int)index.Value]; var transactionModel = _modelMapper.MapTransaction(block.Hash, block.Number, (int)index.Value, transaction); if (Logger.IsDebug) { Logger.Debug($"eth_getTransactionByBlockNumberAndIndex request {blockParameter}, index: {positionIndex.ToJson()}, result: {GetJsonLog(transactionModel.ToJson())}"); } return(ResultWrapper <Transaction> .Success(transactionModel)); }
public ResultWrapper <TransactionTrace> debug_traceTransactionByBlockAndIndex(BlockParameter blockParameter, int index) { UInt256?blockNo = blockParameter.BlockId.AsNumber(); if (!blockNo.HasValue) { throw new InvalidDataException("Block number value incorrect"); } var transactionTrace = _debugBridge.GetTransactionTrace(blockNo.Value, index); if (transactionTrace == null) { return(ResultWrapper <TransactionTrace> .Fail($"Cannot find transactionTrace {blockNo}", ErrorType.NotFound)); } var transactionModel = _modelMapper.MapTransactionTrace(transactionTrace); if (Logger.IsTrace) { Logger.Trace($"{nameof(debug_traceTransactionByBlockAndIndex)} request {blockNo}, result: {GetJsonLog(transactionModel.ToJson())}"); } return(ResultWrapper <TransactionTrace> .Success(transactionModel)); }
public ResultWrapper <BlockTraceItem[]> debug_traceBlockByNumber(Quantity blockNumber) { UInt256?blockNo = blockNumber.AsNumber(); if (!blockNo.HasValue) { throw new InvalidDataException("Expected block number value"); } var blockTrace = _debugBridge.GetBlockTrace(blockNo.Value); if (blockTrace == null) { return(ResultWrapper <BlockTraceItem[]> .Fail($"Trace is null for block {blockNo}", ErrorType.NotFound)); } var blockTraceModel = _modelMapper.MapBlockTrace(blockTrace); if (Logger.IsTrace) { Logger.Trace($"{nameof(debug_traceBlockByNumber)} request {blockNumber}, result: {GetJsonLog(blockTraceModel.Select(btm => btm.ToJson()))}"); } return(ResultWrapper <BlockTraceItem[]> .Success(blockTraceModel)); }
public Task <ResultWrapper <long> > baseline_getCount( Address contractAddress, BlockParameter?blockParameter = null) { bool isTracked = TryGetTracked(contractAddress, out BaselineTree? tree); ResultWrapper <long> result; if (!isTracked || tree == null) { result = ResultWrapper <long> .Fail( $"{contractAddress} tree is not tracked", ErrorCodes.InvalidInput); } else { if (blockParameter == null) { result = ResultWrapper <long> .Success(tree.Count); } else { SearchResult <BlockHeader> searchResult = _blockFinder.SearchForHeader(blockParameter); if (searchResult.IsError) { result = ResultWrapper <long> .Fail(searchResult); } else { result = ResultWrapper <long> .Success(tree.GetBlockCount(searchResult.Object.Number)); } } } return(Task.FromResult(result)); }
public ResultWrapper <IEnumerable <object> > eth_getFilterChanges(UInt256 filterId) { int id = (int)filterId; FilterType filterType = _blockchainBridge.GetFilterType(id); switch (filterType) { case FilterType.BlockFilter: { return(_blockchainBridge.FilterExists(id) ? ResultWrapper <IEnumerable <object> > .Success(_blockchainBridge.GetBlockFilterChanges(id)) : ResultWrapper <IEnumerable <object> > .Fail($"Filter with id: '{filterId}' does not exist.")); } case FilterType.PendingTransactionFilter: { return(_blockchainBridge.FilterExists(id) ? ResultWrapper <IEnumerable <object> > .Success(_blockchainBridge .GetPendingTransactionFilterChanges(id)) : ResultWrapper <IEnumerable <object> > .Fail($"Filter with id: '{filterId}' does not exist.")); } case FilterType.LogFilter: { return(_blockchainBridge.FilterExists(id) ? ResultWrapper <IEnumerable <object> > .Success( _blockchainBridge.GetLogFilterChanges(id).ToArray()) : ResultWrapper <IEnumerable <object> > .Fail($"Filter with id: '{filterId}' does not exist.")); } default: { throw new NotSupportedException($"Filter type {filterType} is not supported"); } } }
public ResultWrapper <IEnumerable <FilterLog> > eth_getLogs(Filter filter) { IEnumerable <FilterLog> GetLogs(BlockParameter blockParameter, BlockParameter toBlockParameter, CancellationTokenSource cancellationTokenSource, CancellationToken token) { using (cancellationTokenSource) { foreach (FilterLog log in _blockchainBridge.GetLogs(blockParameter, toBlockParameter, filter.Address, filter.Topics, token)) { yield return(log); } } } BlockParameter fromBlock = filter.FromBlock; BlockParameter toBlock = filter.ToBlock; try { CancellationTokenSource cancellationTokenSource = new(_rpcConfig.Timeout); return(ResultWrapper <IEnumerable <FilterLog> > .Success(GetLogs(fromBlock, toBlock, cancellationTokenSource, cancellationTokenSource.Token))); } catch (ArgumentException e) { switch (e.Message) { case ILogFinder.NotFoundError: return(ResultWrapper <IEnumerable <FilterLog> > .Fail(e.Message, ErrorCodes.ResourceNotFound)); default: return(ResultWrapper <IEnumerable <FilterLog> > .Fail(e.Message, ErrorCodes.InvalidParams)); } } }
public ResultWrapper <TransactionForRpc> eth_getTransactionByBlockNumberAndIndex(BlockParameter blockParameter, BigInteger positionIndex) { try { _readerWriterLockSlim.EnterReadLock(); if (_blockchainBridge.Head == null) { return(ResultWrapper <TransactionForRpc> .Fail($"Incorrect head block")); } var result = GetBlock(blockParameter); if (result.Result.ResultType == ResultType.Failure) { return(ResultWrapper <TransactionForRpc> .Fail(result.Result.Error, result.ErrorType)); } if (positionIndex < 0 || positionIndex > result.Data.Transactions.Length - 1) { return(ResultWrapper <TransactionForRpc> .Fail("Position Index is incorrect", ErrorType.InvalidParams)); } Block block = result.Data; var transaction = block.Transactions[(int)positionIndex]; var transactionModel = new TransactionForRpc(block.Hash, block.Number, (int)positionIndex, transaction); if (Logger.IsDebug) { Logger.Debug($"eth_getTransactionByBlockNumberAndIndex request {blockParameter}, index: {positionIndex}, result: {transactionModel.Hash}"); } return(ResultWrapper <TransactionForRpc> .Success(transactionModel)); } finally { _readerWriterLockSlim.ExitReadLock(); } }
public ResultWrapper <Data> eth_sign(Data address, Data message) { //TODO check how to deal with password SecureString secureString = new SecureString(); secureString.AppendChar('?'); var privateKey = _blockchainBridge.GetKey(new Address(address.Value), secureString); if (privateKey.Item2.ResultType == ResultType.Failure) { return(ResultWrapper <Data> .Fail("Incorrect address")); } var messageText = Encoding.GetEncoding(ConfigurationProvider.MessageEncoding).GetString(message.Value); var signatureText = string.Format(ConfigurationProvider.SignatureTemplate, messageText.Length, messageText); var signature = _blockchainBridge.Sign(privateKey.Item1, Keccak.Compute(signatureText)); if (Logger.IsTrace) { Logger.Trace($"eth_sign request {address.ToJson()}, {message.ToJson()}, result: {signature}"); } return(ResultWrapper <Data> .Success(new Data(signature.Bytes))); }
public ResultWrapper <byte[]> eth_snapshot() { return(ResultWrapper <byte[]> .Fail("eth_snapshot not supported")); }
public ResultWrapper <bool?> eth_submitHashrate(string hashRate, string id) { return(ResultWrapper <bool?> .Fail("eth_submitHashrate not supported", ErrorType.MethodNotFound, null)); }
public ResultWrapper <bool?> eth_submitWork(byte[] nonce, Keccak headerPowHash, byte[] mixDigest) { return(ResultWrapper <bool?> .Fail("eth_submitWork not supported", ErrorType.MethodNotFound, null)); }
public ResultWrapper <IEnumerable <byte[]> > eth_getWork() { return(ResultWrapper <IEnumerable <byte[]> > .Fail("eth_getWork not supported")); }
public ResultWrapper <bool> eth_submitHashrate(string hashRate, string id) { return(ResultWrapper <bool> .Fail("eth_submitHashrate not supported")); }
protected ResultWrapper <TResult> GetInputError(BlockchainBridge.CallOutput result) => ResultWrapper <TResult> .Fail(result.Error ?? string.Empty, ErrorCodes.InvalidInput);
public ResultWrapper <IEnumerable <byte[]> > eth_getWork() { return(ResultWrapper <IEnumerable <byte[]> > .Fail("eth_getWork not supported", ErrorCodes.MethodNotFound)); }
public ResultWrapper <IEnumerable <FilterLog> > eth_getLogs(Filter filter) { IEnumerable <FilterLog> GetLogs(IEnumerable <FilterLog> logs, CancellationTokenSource cancellationTokenSource) { using (cancellationTokenSource) { foreach (FilterLog log in logs) { yield return(log); } } } // because of lazy evaluation of enumerable, we need to do the validation here first CancellationTokenSource cancellationTokenSource = new(_rpcConfig.Timeout); CancellationToken cancellationToken = cancellationTokenSource.Token; SearchResult <BlockHeader> fromBlockResult; SearchResult <BlockHeader> toBlockResult; if (filter.FromBlock == filter.ToBlock) { fromBlockResult = toBlockResult = _blockFinder.SearchForHeader(filter.ToBlock); } else { toBlockResult = _blockFinder.SearchForHeader(filter.ToBlock); if (toBlockResult.IsError) { cancellationTokenSource.Dispose(); return(ResultWrapper <IEnumerable <FilterLog> > .Fail(toBlockResult)); } cancellationToken.ThrowIfCancellationRequested(); fromBlockResult = _blockFinder.SearchForHeader(filter.FromBlock); } if (fromBlockResult.IsError) { cancellationTokenSource.Dispose(); return(ResultWrapper <IEnumerable <FilterLog> > .Fail(fromBlockResult)); } cancellationToken.ThrowIfCancellationRequested(); long fromBlockNumber = fromBlockResult.Object !.Number; long toBlockNumber = toBlockResult.Object !.Number; if (fromBlockNumber > toBlockNumber && toBlockNumber != 0) { cancellationTokenSource.Dispose(); return(ResultWrapper <IEnumerable <FilterLog> > .Fail($"'From' block '{fromBlockNumber}' is later than 'to' block '{toBlockNumber}'.", ErrorCodes.InvalidParams)); } try { IEnumerable <FilterLog> filterLogs = _blockchainBridge.GetLogs(filter.FromBlock, filter.ToBlock, filter.Address, filter.Topics, cancellationToken); return(ResultWrapper <IEnumerable <FilterLog> > .Success(GetLogs(filterLogs, cancellationTokenSource))); } catch (ResourceNotFoundException exception) { return(ResultWrapper <IEnumerable <FilterLog> > .Fail(exception.Message, ErrorCodes.ResourceNotFound)); } }