public bool TryGetFavouriteDelta(MultiHash previousDeltaDfsHash, out FavouriteDeltaBroadcast favourite) { Guard.Argument(previousDeltaDfsHash, nameof(previousDeltaDfsHash)).NotNull(); _logger.Debug("Retrieving favourite candidate delta for the successor of delta {0}", previousDeltaDfsHash); var cacheKey = GetCandidateListCacheKey(previousDeltaDfsHash); if (!_candidatesCache.TryGetValue(cacheKey, out ConcurrentBag <string> candidates)) { _logger.Debug("Failed to retrieve any scored candidate with previous delta {0}", previousDeltaDfsHash.ToBase32()); favourite = default; return(false); } var bestCandidate = candidates.Select(c => _candidatesCache.Get(c) as IScoredCandidateDelta) .Where(c => c != null) .OrderByDescending(c => c.Score) .ThenBy(c => c.Candidate.Hash.ToByteArray(), ByteUtil.ByteListMinSizeComparer.Default) .First().Candidate; favourite = new FavouriteDeltaBroadcast { Candidate = bestCandidate, VoterId = _localPeerIdentifier }; _logger.Debug("Retrieved favourite candidate delta {candidate} for the successor of delta {previousDelta}", bestCandidate.Hash.ToByteArray().ToBase32(), previousDeltaDfsHash.ToBase32()); return(true); }
/// <inheritdoc /> public void BroadcastFavouriteCandidateDelta(FavouriteDeltaBroadcast favourite) { Guard.Argument(favourite, nameof(favourite)).NotNull().Require(c => c.IsValid()); var protocolMessage = favourite.ToProtocolMessage(_peerId, CorrelationId.GenerateCorrelationId()); _broadcastManager.BroadcastAsync(protocolMessage); _logger.Debug("Started broadcasting favourite candidate {0}", favourite); }
public void When_receiving_bad_favourite_should_log_and_not_hit_the_cache(FavouriteDeltaBroadcast badFavourite, Type exceptionType) { var elector = new DeltaElector(_cache, _deltaProducersProvider, _reputationManager, _logger); elector.OnNext(badFavourite); _cache.DidNotReceiveWithAnyArgs().TryGetValue(Arg.Any <object>(), out Arg.Any <object>()); _cache.DidNotReceiveWithAnyArgs().CreateEntry(Arg.Any <object>()); }
public void FavouriteDeltaBroadcastDao_FavouriteDeltaBroadcast_Should_Be_Convertible() { var original = new FavouriteDeltaBroadcast { Candidate = DeltaHelper.GetCandidateDelta(_hashProvider, producerId: PeerIdHelper.GetPeerId("not me")), VoterId = PeerIdHelper.GetPeerId("test") }; var contextDao = original.ToDao <FavouriteDeltaBroadcast, FavouriteDeltaBroadcastDao>(_mapperProvider); var reconverted = contextDao.ToProtoBuff <FavouriteDeltaBroadcastDao, FavouriteDeltaBroadcast>(_mapperProvider); reconverted.Should().Be(original); }
public void FavouriteDeltaBroadcast_IsValid_Should_Not_Throw_On_Valid_FavouriteDeltaBroadcast() { var candidate = new FavouriteDeltaBroadcast { Candidate = new CandidateDeltaBroadcast { ProducerId = new PeerId { PublicKey = "producer".ToUtf8ByteString() }, Hash = ByteString.CopyFromUtf8("hash"), PreviousDeltaDfsHash = ByteString.CopyFromUtf8("ok") }, VoterId = new PeerId { PublicKey = "voter".ToUtf8ByteString() }, }; candidate.IsValid().Should().BeTrue(); }
public void OnNext(FavouriteDeltaBroadcast candidate) { _logger.Verbose("Favourite candidate delta received {favourite}", candidate); try { Guard.Argument(candidate, nameof(candidate)).NotNull().Require(f => f.IsValid()); var cid = candidate.Candidate.PreviousDeltaDfsHash.ToByteArray().ToCid(); if (!_deltaProducersProvider .GetDeltaProducersFromPreviousDelta(cid) .Any(p => p.Equals(candidate.VoterId))) { var reputationChange = new ReputationChange(candidate.VoterId, ReputationEventType.VoterIsNotProducer); _reputationManager.OnNext(reputationChange); _logger.Debug( "Voter {voter} is not a producer for this cycle succeeding {deltaHash} and its vote has been discarded.", candidate.VoterId, candidate.Candidate.PreviousDeltaDfsHash); return; } var candidateListKey = GetCandidateListCacheKey(candidate); if (_candidatesCache.TryGetValue(candidateListKey, out ConcurrentDictionary <FavouriteDeltaBroadcast, bool> retrieved)) { retrieved.TryAdd(candidate, default); return; } _candidatesCache.Set(candidateListKey, new ConcurrentDictionary <FavouriteDeltaBroadcast, bool>( new[] { new KeyValuePair <FavouriteDeltaBroadcast, bool>(candidate, false) }, FavouriteByHashAndVoterComparer.Default), _cacheEntryOptions()); } catch (Exception e) { _logger.Error(e, "Failed to process favourite delta {0}", candidate); } }
public void OnNext(FavouriteDeltaBroadcast candidate) { _logger.Verbose("Favourite candidate delta received {favourite}", candidate); try { Guard.Argument(candidate, nameof(candidate)).NotNull().Require(f => f.IsValid()); var multiHash = new MultiHash(candidate.Candidate.PreviousDeltaDfsHash.ToByteArray()); if (!_deltaProducersProvider .GetDeltaProducersFromPreviousDelta(multiHash) .Any(p => p.Equals(candidate.VoterId))) { //https://github.com/catalyst-network/Catalyst.Node/issues/827 _logger.Debug( "Voter {voter} is not a producer for this cycle succeeding {deltaHash} and its vote has been discarded.", candidate.VoterId, candidate.Candidate.PreviousDeltaDfsHash); return; } var candidateListKey = GetCandidateListCacheKey(candidate, _hashProvider); if (_candidatesCache.TryGetValue(candidateListKey, out ConcurrentDictionary <FavouriteDeltaBroadcast, bool> retrieved)) { retrieved.TryAdd(candidate, default); return; } _candidatesCache.Set(candidateListKey, new ConcurrentDictionary <FavouriteDeltaBroadcast, bool>( new[] { new KeyValuePair <FavouriteDeltaBroadcast, bool>(candidate, false) }, FavouriteByHashAndVoterComparer.Default), _cacheEntryOptions()); } catch (Exception e) { _logger.Error(e, "Failed to process favourite delta {0}", candidate); } }
public static string GetCandidateListCacheKey(FavouriteDeltaBroadcast candidate) { return(nameof(DeltaElector) + "-" + candidate.Candidate.PreviousDeltaDfsHash.ToByteArray().ToCid()); }
public void FavouriteDeltaBroadcast_IsValid_Should_Throw_On_Invalid_FavouriteDeltaBroadcast(FavouriteDeltaBroadcast favourite) { favourite.IsValid().Should().BeFalse(); }
public static string GetCandidateListCacheKey(FavouriteDeltaBroadcast candidate, IHashProvider hashProvider) { return(nameof(DeltaElector) + "-" + hashProvider.Cast(candidate.Candidate.PreviousDeltaDfsHash.ToByteArray())); }
public void FavouriteByHashComparer_should_differentiate_by_candidate_hash_and_voter_only(FavouriteDeltaBroadcast x, FavouriteDeltaBroadcast y, bool comparisonResult) { var xHashCode = FavouriteByHashAndVoterComparer.Default.GetHashCode(x); var yHashCode = FavouriteByHashAndVoterComparer.Default.GetHashCode(y); if (xHashCode != 0 && yHashCode != 0) { xHashCode.Equals(yHashCode).Should().Be(comparisonResult); } FavouriteByHashAndVoterComparer.Default.Equals(x, y).Should().Be(comparisonResult); }