Beispiel #1
0
        private ConsensusMessage CreateCoinMessage(Signature share)
        {
            var shareBytes = share.ToBytes().ToArray();
            var message    = new ConsensusMessage
            {
                Coin = new CommonCoinMessage
                {
                    Agreement      = _coinId.Agreement,
                    Epoch          = _coinId.Epoch,
                    SignatureShare = ByteString.CopyFrom(shareBytes, 0, shareBytes.Length)
                }
            };

            return(new ConsensusMessage(message));
        }
Beispiel #2
0
        public override void ProcessMessage(MessageEnvelope envelope)
        {
            if (envelope.External)
            {
                var message = envelope.ExternalMessage;
                if (message is null)
                {
                    _lastMessage = "Failed to decode external message";
                    throw new ArgumentNullException();
                }
                // These checks are somewhat redundant, but whatever
                if (message.PayloadCase != ConsensusMessage.PayloadOneofCase.Coin)
                {
                    _lastMessage = $"consensus message of type {message.PayloadCase} routed to CommonCoin protocol";
                    throw new ArgumentException(
                              $"consensus message of type {message.PayloadCase} routed to CommonCoin protocol");
                }

                if (message.Validator.Era != _coinId.Era ||
                    message.Coin.Agreement != _coinId.Agreement ||
                    message.Coin.Epoch != _coinId.Epoch)
                {
                    _lastMessage = $"era, agreement or epoch of message mismatched: message({message.Validator.Era}, "
                                   + $"{message.Coin.Agreement}, {message.Coin.Epoch}), coin ({_coinId.Era}, "
                                   + $"{_coinId.Agreement}, {_coinId.Epoch})";
                    throw new ArgumentException("era, agreement or epoch of message mismatched");
                }

                // To create signature from the message, some requirements need to be fulfilled, otherwise it can
                // throw exception (for example maybe a fixed length of the input bytes or maybe valid array of bytes)
                try
                {
                    Logger.LogTrace($"Received share from {envelope.ValidatorIndex}");
                    _lastMessage = $"Received share from {envelope.ValidatorIndex}";
                    var signatureShare = Signature.FromBytes(message.Coin.SignatureShare.ToByteArray());
                    if (!_thresholdSigner.AddShare(envelope.ValidatorIndex, signatureShare, out var signature))
                    {
                        _lastMessage =
                            $"Faulty behaviour from player {envelope.ValidatorIndex}, {message.PrettyTypeString()}, {message.Coin.SignatureShare.ToByteArray().ToHex()}: bad signature share";
                        Logger.LogWarning(
                            $"Faulty behaviour from player {envelope.ValidatorIndex}, {message.PrettyTypeString()}, {message.Coin.SignatureShare.ToByteArray().ToHex()}: bad signature share");
                        return; // potential fault evidence
                    }

                    if (signature == null)
                    {
                        _lastMessage = "signature == null";
                        return;
                    }

                    _result = new CoinResult(signature.RawSignature.ToBytes());
                }
                catch (Exception exception)
                {
                    var pubKey = Broadcaster.GetPublicKeyById(envelope.ValidatorIndex) !.ToHex();
                    Logger.LogWarning(
                        $"Exception occured while handling message from validator {envelope.ValidatorIndex} " +
                        $"({pubKey}). Exception: {exception}");
                }

                CheckResult();
            }
            else
            {
                var message = envelope.InternalMessage;
                if (message is null)
                {
                    _lastMessage = "Failed to decode internal message";
                    throw new ArgumentNullException();
                }
                switch (message)
                {
                case ProtocolRequest <CoinId, object?> _:
                    _lastMessage = "ProtocolRequest";
                    var signatureShare = _thresholdSigner.Sign();
                    _requested = ResultStatus.Requested;
                    CheckResult();
                    var msg = CreateCoinMessage(signatureShare);
                    Broadcaster.Broadcast(msg);
                    break;

                case ProtocolResult <CoinId, CoinResult> _:
                    _lastMessage = "ProtocolResult";
                    Terminate();
                    break;

                default:
                    _lastMessage = $"Binary broadcast protocol handles messages of type {message.GetType()}";
                    throw new InvalidOperationException(
                              $"Binary broadcast protocol handles messages of type {message.GetType()}");
                }
            }
        }