Пример #1
0
        public GenericResponse NewBlockAnnouncement(BlockHeader header)
        {
            try
            {
                if (ApplicationState.ConsensusState != ConsensusStates.WaitingForSpeaker &&
                    ApplicationState.ConsensusState != ConsensusStates.CreatingBlock)
                {
                    return(new GenericResponse(null, ResponseCodes.Success, ResponseMessages.Success));
                }

                //TODO: verify sender signature
                //VerifySignature(callerNode.WalletAddress);

                ApplicationLog.Info("Received new block");

                DataServices dataServices = new DataServices();

                //Validate if sender is current speaker
                if (callerNode.ServerAddress != ApplicationState.CurrentSpeaker.ServerAddress &&
                    callerNode.WalletAddress != ApplicationState.CurrentSpeaker.WalletAddress)
                {
                    ApplicationLog.Info("Speaker Not Recognized");
                    return(new GenericResponse(null, ResponseCodes.SpeakerNotRecognized, ResponseMessages.SpeakerNotRecognized));
                }

                //If first epoch, no need to validate as transactions will unlikely tally due to different start consensus time
                if (ApplicationState.LiveEpochCount == 1 &&
                    ApplicationState.CurrentSpeaker.ServerAddress != ApplicationState.Node.ServerAddress)
                {
                    dataServices.ClearPendingTxUpToId(header.LastTransactionId);
                    return(new GenericResponse(null, ResponseCodes.Success, ResponseMessages.Success));
                }

                //Validate block transactions with local pending transactions
                //Note: If somehow this node received all transactions but not in the correct order, block will be discarded
                //and wait for correction during re-sync in subsequent epochs
                if (header.Hash != dataServices.HashBlockHeaderAndTransactions(header, dataServices.GetPendingTxUpTo(header.LastTransactionId)))
                {
                    //Pending Transaction And Block Mismatch
                    ApplicationLog.Info("Pending Transaction And Block Mismatch");
                    return(new GenericResponse(null, ResponseCodes.PendingTransactionAndBlockMismatch, ResponseMessages.PendingTransactionAndBlockMismatch));
                }

                //Create Block
                var newBlock = dataServices.CreateBlockAndClearPendingTx(header);

                //Attach block fee
                newBlock = dataServices.AttachBlockFee(newBlock, ApplicationState.CurrentSpeaker);

                //Add block to chain
                dataServices.SaveBlockToChain(newBlock);
                ApplicationLog.Info("New block added to chain. Index: " + header.Index);

                return(new GenericResponse(null, ResponseCodes.Success, ResponseMessages.Success));
            }
            catch (Exception ex)
            {
                ApplicationLog.Exception(ex);
                return(new GenericResponse(null, ResponseCodes.Error, ResponseMessages.Error));
            }
            finally
            {
                //Resume next iteration of consensus
                ConsensusServices consensusServices = new ConsensusServices();
                consensusServices.NextEpoch();
            }
        }