public void TestBroadcaster()
        {
            var test      = new Broadcaster();
            var listener  = new TestListener();
            var listener2 = new TestListener();

            test.AddListener(listener);
            Assert.AreEqual(1, test.listeners.Count);
            test.RemoveListener(listener);
            Assert.AreEqual(0, test.listeners.Count);

            test.AddListener(listener);
            test.AddListener(listener2);
            test.Broadcast(new Event("hello"));
            Assert.AreEqual("hello", listener.lastMessage);
            Assert.AreEqual("hello", listener2.lastMessage);

            test.RemoveListener(listener);
            test.Broadcast(new Event("goodbye"));
            Assert.AreEqual("hello", listener.lastMessage);
            Assert.AreEqual("goodbye", listener2.lastMessage);

            test.Clear();
            Assert.AreEqual(0, test.listeners.Count);
        }
Example #2
0
        private void BroadcastBVal(bool value)
        {
            var b = value ? 1 : 0;

            _wasBvalBroadcasted[b] = true;
            Broadcaster.Broadcast(CreateBValMessage(b));
        }
Example #3
0
 private void RevisitAuxMessages()
 {
     if (_confSent)
     {
         return;
     }
     if (_binValues.Values().Sum(b => _receivedAux[b ? 1 : 0]) < N - F)
     {
         return;
     }
     Logger.LogTrace($"{_broadcastId}: conf message sent with set {_binValues}");
     Broadcaster.Broadcast(CreateConfMessage(_binValues));
     _confSent = true;
     RevisitConfMessages();
 }
Example #4
0
        private void TrySignHeader()
        {
            Logger.LogTrace("TrySignHeader");
            if (_receipts is null || _nonce is null || _blockProducer is null)
            {
                Logger.LogTrace($"Not ready yet: _hasges {_receipts is null}, _nonce {_nonce is null}, _blockProducer {_blockProducer is null}");
                return;
            }

            if (!(_header is null))
            {
                Logger.LogTrace("Header already exists");
                return;
            }
            try
            {
                Logger.LogTrace("Try to create header");
                _header = _blockProducer.CreateHeader((ulong)Id.Era, _receipts, _nonce.Value, out _receipts);
                if (_header == null)
                {
                    Logger.LogTrace("Failed to create header");
                    return;
                }
            }
            catch (Exception e)
            {
                Logger.LogError($"Cannot sign header because of {e}");
                Terminate();
                Environment.Exit(1);
                return;
            }

            var signature = _crypto.SignHashed(
                _header.Keccak().ToBytes(),
                _keyPair.PrivateKey.Encode(), _useNewChainId
                ).ToSignature(_useNewChainId);

            Logger.LogTrace(
                $"Signed header {_header.Keccak().ToHex()} with pubKey {_keyPair.PublicKey.ToHex()}"
                );
            Broadcaster.Broadcast(CreateSignedHeaderMessage(_header, signature));
        }
Example #5
0
 private void TrySendReadyMessageFromReady()
 {
     var(bestRootCnt, bestRoot) = _readyMessages
                                  .Where(x => x != null)
                                  .GroupBy(x => x !.MerkleTreeRoot)
                                  .Select(m => (cnt: m.Count(), key: m.Key))
                                  .OrderByDescending(x => x.cnt)
                                  .First();
     if (bestRootCnt != F + 1)
     {
         return;
     }
     if (_readySent)
     {
         return;
     }
     Broadcaster.Broadcast(CreateReadyMessage(bestRoot));
     _readySent = true;
     Logger.LogTrace($"Protocol {Id} got enough READYs and broadcasted READY message");
 }
Example #6
0
        private void HandleBValMessage(int sender, BValMessage bval)
        {
            if (bval.Epoch != _broadcastId.Epoch || bval.Agreement != _broadcastId.Agreement)
            {
                throw new ArgumentException("era, agreement or epoch of message mismatched");
            }

            var b = bval.Value ? 1 : 0;

            if (_receivedValues[sender].Contains(b == 1))
            {
                Logger.LogTrace($"{_broadcastId}: double receive message {bval} from {sender}");
                return;
            }

            _receivedValues[sender].Add(b == 1);
            ++_receivedCount[b];

            if (!_wasBvalBroadcasted[b] && _receivedCount[b] >= F + 1)
            {
                BroadcastBVal(bval.Value);
            }

            if (_receivedCount[b] < 2 * F + 1)
            {
                return;
            }
            if (_binValues.Contains(b == 1))
            {
                return;
            }

            _binValues = _binValues.Add(b == 1);
            if (_binValues.Count() == 1)
            {
                Broadcaster.Broadcast(CreateAuxMessage(b));
            }

            RevisitAuxMessages();
            RevisitConfMessages();
        }
Example #7
0
        private void TrySendReadyMessageFromEchos()
        {
            if (_readySent)
            {
                return;
            }
            var(bestRootCnt, bestRoot) = _echoMessages
                                         .Where(x => x != null)
                                         .GroupBy(x => x !.MerkleTreeRoot)
                                         .Select(m => (cnt: m.Count(), key: m.Key))
                                         .OrderByDescending(x => x.cnt)
                                         .First();
            if (bestRootCnt != N - F)
            {
                return;
            }
            var interpolationData = _echoMessages
                                    .WithIndex()
                                    .Where(x => bestRoot.Equals(x.item?.MerkleTreeRoot))
                                    .Select(t => (echo: t.item !, t.index))
                                    .Take(N - 2 * F)
                                    .ToArray();
            var restoredData       = DecodeFromEchos(interpolationData);
            var restoredMerkleTree = ConstructMerkleTree(
                restoredData
                .Batch(interpolationData.First().echo.Data.Length)
                .Select(x => x.ToArray())
                .ToArray()
                );

            if (!restoredMerkleTree[1].Equals(bestRoot))
            {
                Logger.LogError($"{Id}: Interpolated result merkle root does not match!");
                Abort();
                return;
            }

            Broadcaster.Broadcast(CreateReadyMessage(bestRoot));
            _readySent = true;
            Logger.LogTrace($"Protocol {Id} got enough ECHOs and broadcasted READY message");
        }
Example #8
0
        private void HandleCommonSubset(ProtocolResult <CommonSubsetId, ISet <EncryptedShare> > result)
        {
            Logger.LogTrace($"Common subset finished {result.From}");
            foreach (var share in result.Result)
            {
                var dec = _privateKey.Decrypt(share);
                _taken[share.Id]          = true;
                _receivedShares[share.Id] = share;
                // todo think about async access to protocol method. This may pose threat to protocol internal invariants
                CheckDecryptedShares(share.Id);
                Broadcaster.Broadcast(CreateDecryptedMessage(dec));
            }

            _takenSet = true;

            foreach (var share in result.Result)
            {
                CheckDecryptedShares(share.Id);
            }

            CheckResult();
        }
Example #9
0
        private static QAcidRunner <Unit> Broadcast(Broadcaster broadcaster, ThreadInfo info)
        {
            return
                (from canact in
                 "when threadswitch is false".If(
                     () => info.ThreadSwitch == false,
                     from start in "start broadcasting".Act(
                         () =>
            {
                info.ThreadSwitch = true;
                info.ExceptionFromThread = null;
                info.Thread =
                    new Thread(
                        () => info.ExceptionFromThread =
                            GetExceptionThrownBy(
                                () => broadcaster.Broadcast(null)));

                info.Thread.Start();
            })
                     from spec in "Broadcast : No Exception is thrown".Spec(() => info.ExceptionFromThread == null)
                     select Unit.Instance)
                 select Unit.Instance);
        }
Example #10
0
        private void Broadcaster_BroadcastVerb_SendsUdpPacket(string verb, out bool online, out bool offline)
        {
            online  = false;
            offline = false;
            bool flaggedOnline = false, flaggedOffline = false;

            listener.Listen(0);
            try
            {
                listener.InstanceOnline  += (sender, ea) => flaggedOnline = true;
                listener.InstanceOffline += (sender, ea) => flaggedOffline = true;

                Broadcaster.Broadcast(verb, 0);
                Thread.Sleep(100);
            }
            finally
            {
                listener.Stop();
            }

            online  = flaggedOnline;
            offline = flaggedOffline;
        }
Example #11
0
        private void HandleValMessage(ValMessage val, int validator)
        {
            var validatorPubKey = Wallet.EcdsaPublicKeySet[validator].ToHex();

            if (_sentValMessage[validator])
            {
                Logger.LogWarning($"{Id}: validator {validator} ({validatorPubKey}) tried to send VAL message twice");
                return;
            }

            Logger.LogTrace(
                $"Protocol {Id} got VAL message from {validator} ({validatorPubKey}), sending ECHO"
                );

            _sentValMessage[validator] = true;
            // Before sending echo, we can check if validator == val.SenderId, means if the val message is from the correct validator
            // Because one validator cannot produce val message of another validator, it can only send echo.
            // If we don't check this condition, there could be potential issue, for example, a malicious validator (id = x) sends a
            // val message that has random shards but correct MerkleProof and uses val.SenderId = y (another validator), and sends to
            // validator with id = z. It will be constructed as echo message and sent to everyone by validator, id = z, this echo will
            // pass the CheckEchoMessage(). Now every honest validator will think that val message of validator of id = y is confirmed
            // by echo message from validator of id = z. When the correct val message of id = y will come to id = z, he will send echo
            // again but others will not accept it, because id = z already sent echo for id = y, (but it was from malicious id = x),
            // because the correct echo for each pair is received only once.
            if (validator == val.SenderId)
            {
                Broadcaster.Broadcast(CreateEchoMessage(val));
            }
            else
            {
                var pubKey = Broadcaster.GetPublicKeyById(validator) !.ToHex();
                Logger.LogWarning(
                    $"Faulty behaviour: val message with sender id: {val.SenderId} came from validator: " +
                    $"{validator} ({pubKey}), which should not happen. Val message for {val.SenderId} should come " +
                    $"from {val.SenderId}. Not sending echo message for this val message");
            }
        }
Example #12
0
        public ActionResult Subscription()
        {
            var encodedString = this.Request.QueryString["validationToken"];

            if (encodedString != null)
            {
                // Ack the webhook subscription
                var decodedString = HttpUtility.UrlDecode(encodedString);
                var res           = new ContentResult()
                {
                    Content = decodedString, ContentType = "text/plain", ContentEncoding = System.Text.Encoding.UTF8
                };
                return(res);
            }
            else
            {
                // signal clients
                Broadcaster.Broadcast();
                return(new ContentResult()
                {
                    Content = "", ContentType = "text/plain", ContentEncoding = System.Text.Encoding.UTF8
                });
            }
        }
Example #13
0
        protected override void OnFinish()
        {
            base.OnFinish();

            broadcaster.Broadcast(new Event());
        }
Example #14
0
 /// <summary>
 /// Usually this would be published due to an internal state or data change
 /// </summary>
 /// <param name="message"></param>
 /// <returns></returns>
 public async Task Broadcast(Simple message)
 {
     await Broadcaster.Broadcast(message);
 }
Example #15
0
 public override async Task ProcessAsync()
 {
     Broadcaster.Broadcast($"Hello {_value}!");
 }
Example #16
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()}");
                }
            }
        }
Example #17
0
 /// <summary>
 /// Signals
 /// </summary>
 public void Broadcast()
 {
     Broadcaster.Broadcast();
 }