private BaseResponse <bool> AcceptBlock(DAM.Block.BlockBase incomingBlock, string senderNodeId)
        {
            if (incomingBlock == null)
            {
                return(new ErrorResponse <bool>("The incoming block cannot be null!", false));
            }

            if (_blockchainService.BlockExists(incomingBlock.UniqueId))
            {
                _statisticService.RegisterRejectedBlock();
                return(new ErrorResponse <bool>("The block already exists!", false));
            }

            var mappedBlock = LocalMapper.Map <BlockBase>(incomingBlock);

            if (incomingBlock is DAM.Block.Block block && !incomingBlock.IsGenesis)
            {
                var parentBlockValidationResult = ValidateParentBlock(block, senderNodeId);
                if (!parentBlockValidationResult.IsSuccess)
                {
                    _statisticService.RegisterRejectedBlock();
                    return(parentBlockValidationResult);
                }

                var parentBlock = _blockchainService.GetBlock(block.ParentUniqueId);
                if (parentBlock == null || parentBlock.Depth + 1 != mappedBlock.Depth)
                {
                    _statisticService.RegisterRejectedBlock();
                    return(new ErrorResponse <bool>("The depth of incoming block is incorrect!", false));
                }

                var mappedParentBlock = LocalMapper.Map <BlockBase>(parentBlock);
                ((Block)mappedBlock).Parent = mappedParentBlock;
            }

            var duplicatesValidationResult = ValidateTransactionsDuplicates(mappedBlock);

            if (!duplicatesValidationResult.IsSuccess)
            {
                return(duplicatesValidationResult);
            }

            var validationResult = _blockchainValidator.Validate(mappedBlock);

            if (!validationResult.IsSuccess)
            {
                _statisticService.RegisterRejectedBlock();
                return(new ErrorResponse <bool>("The validation for the block failed!", false, validationResult.Errors));
            }

            _blockchainService.AddBlock(incomingBlock);
            return(new SuccessResponse <bool>("The block has been accepted and appended!", true));
        }
        public async Task <BlockchainAddResult> AddAsync(Block newBlock)
        {
            var duplicateBlock = _queryHandlerGetBlock.Handle(new GetBlockQuery()
            {
                BlockHash = newBlock.BlockHash
            });

            if (duplicateBlock != null)
            {
                return(new BlockchainAddResult()
                {
                    IsSuccessful = false,
                    Error = BlockchainAddResultError.AlreadyAdded
                });
            }

            var previousBlockDb = _queryHandlerGetBlock.Handle(new GetBlockQuery()
            {
                BlockHash = newBlock.BlockHashPrevious
            });

            if (previousBlockDb == null)
            {
                return(new BlockchainAddResult()
                {
                    IsSuccessful = false,
                    Error = BlockchainAddResultError.LackOfPreviousBlock
                });
            }

            var validationResult = _blockchainValidator.Validate(newBlock, new Block(previousBlockDb), _hashCash.Validate);

            if (!validationResult)
            {
                return(new BlockchainAddResult()
                {
                    IsSuccessful = false,
                    Error = BlockchainAddResultError.ValidationError
                });
            }

            foreach (var msg in newBlock.Messages)
            {
                var result = await _messageStore.TryAddAsync(msg);
            }

            var queryResult = _queryHandlerAddBlock.Handle(new AddBlockQuery()
            {
                NewBlock = newBlock
            });

            if (!queryResult)
            {
                return(new BlockchainAddResult()
                {
                    IsSuccessful = false,
                    Error = BlockchainAddResultError.InternalError
                });
            }

            var markResult = _queryHandlerMarkMainChain.Handle(new MarkMainChainQuery()
            {
            });

            if (!markResult)
            {
                return(new BlockchainAddResult()
                {
                    IsSuccessful = false,
                    Error = BlockchainAddResultError.InternalError
                });
            }

            return(new BlockchainAddResult()
            {
                IsSuccessful = true,
                Error = BlockchainAddResultError.None
            });
        }