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); }
private void BroadcastBVal(bool value) { var b = value ? 1 : 0; _wasBvalBroadcasted[b] = true; Broadcaster.Broadcast(CreateBValMessage(b)); }
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(); }
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)); }
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"); }
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(); }
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"); }
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(); }
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); }
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; }
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"); } }
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 }); } }
protected override void OnFinish() { base.OnFinish(); broadcaster.Broadcast(new Event()); }
/// <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); }
public override async Task ProcessAsync() { Broadcaster.Broadcast($"Hello {_value}!"); }
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()}"); } } }
/// <summary> /// Signals /// </summary> public void Broadcast() { Broadcaster.Broadcast(); }