private static int CompareCandidateHash(CandidateDeltaBroadcast x, CandidateDeltaBroadcast y) { var xByteArray = x?.Hash?.ToByteArray(); var yByteArray = y?.Hash?.ToByteArray(); return (ByteUtil.ByteListMinSizeComparer.Default.Compare( xByteArray, yByteArray)); }
private void AddCandidateToCandidateHashLookup(CandidateDeltaBroadcast candidate, int rankingFactor, string candidateCacheKey) { var scoredDelta = new ScoredCandidateDelta(candidate, 100 * rankingFactor + 1); _candidatesCache.Set(candidateCacheKey, scoredDelta, _cacheEntryOptions()); _logger.Verbose("Candidate {hash} with previous hash {previousHash} has score {scored}", candidate.Hash.ToByteArray().ToBase32(), candidate.PreviousDeltaDfsHash.ToByteArray().ToBase32(), scoredDelta.Score); }
private void AddCandidateToPreviousHashLookup(CandidateDeltaBroadcast candidate, string candidateCacheKey) { var candidatesForPreviousHash = _candidatesCache.GetOrCreate(GetCandidateListCacheKey(candidate), c => { c.SetOptions(_cacheEntryOptions()); return(new ConcurrentBag <string>()); }); candidatesForPreviousHash.Add(candidateCacheKey); _logger.Verbose("Candidates for previous hash {previousHash} are {candidates}", candidate.PreviousDeltaDfsHash.ToByteArray().ToBase32(), candidatesForPreviousHash); }
public void CandidateDeltaBroadcastDao_CandidateDeltaBroadcast_Should_Be_Convertible() { var candidateDeltaBroadcastDao = GetMapper <CandidateDeltaBroadcastDao>(); var previousHash = _hashProvider.ComputeMultiHash(Encoding.UTF8.GetBytes("previousHash")); var hash = _hashProvider.ComputeMultiHash(Encoding.UTF8.GetBytes("anotherHash")); var original = new CandidateDeltaBroadcast { Hash = hash.ToArray().ToByteString(), ProducerId = PeerIdHelper.GetPeerId("test"), PreviousDeltaDfsHash = previousHash.ToArray().ToByteString() }; var candidateDeltaBroadcast = candidateDeltaBroadcastDao.ToDao(original); var reconverted = candidateDeltaBroadcast.ToProtoBuff(); reconverted.Should().Be(original); }
public void OnNext(CandidateDeltaBroadcast candidate) { try { var rankingFactor = GetProducerRankFactor(candidate); var candidateCacheKey = GetCandidateCacheKey(candidate); if (_candidatesCache.TryGetValue <IScoredCandidateDelta>(candidateCacheKey, out var retrievedScoredDelta)) { retrievedScoredDelta.IncreasePopularity(1); _logger.Debug("Candidate {candidate} increased popularity to {score}", candidate, retrievedScoredDelta.Score); return; } AddCandidateToCandidateHashLookup(candidate, rankingFactor, candidateCacheKey); AddCandidateToPreviousHashLookup(candidate, candidateCacheKey); } catch (Exception e) { _logger.Error(e, "Failed to Vote on the candidate delta {0}", candidate); } }
private int GetProducerRankFactor(CandidateDeltaBroadcast candidate) { var preferredProducers = _deltaProducersProvider .GetDeltaProducersFromPreviousDelta(new MultiHash(candidate.PreviousDeltaDfsHash.ToByteArray())); var ranking = preferredProducers.ToList() .FindIndex(p => p.Equals(candidate.ProducerId)); var identifier = candidate.ProducerId; _logger.Verbose("ranking for block produced by {producerId} = {ranking}", identifier, ranking); if (ranking == -1) { throw new KeyNotFoundException( $"Producer {candidate.ProducerId} " + $"should not be sending candidate deltas with previous hash " + $"{candidate.PreviousDeltaDfsHash.ToByteArray().ToBase32()}"); } return(preferredProducers.Count - ranking); }
public static string GetCandidateListCacheKey(CandidateDeltaBroadcast candidate) => nameof(DeltaVoter) + "-" + candidate.PreviousDeltaDfsHash.ToByteArray().ToBase32();
///<inheritdoc /> public CandidateDeltaBroadcast BuildCandidateDelta(MultiHash previousDeltaHash) { _logger.Debug("Building candidate delta locally"); var allTransactions = _transactionRetriever.GetMempoolTransactionsByPriority(); Guard.Argument(allTransactions, nameof(allTransactions)) .NotNull("Mempool content returned null, check the mempool is actively running"); var includedTransactions = GetValidTransactionsForDelta(allTransactions); var salt = GetSaltFromPreviousDelta(previousDeltaHash); var rawAndSaltedEntriesBySignature = includedTransactions.SelectMany( t => t.PublicEntries.Select(e => new RawEntryWithSaltedAndHashedEntry(e, salt, _hashProvider))); // (Eα;Oα) var shuffledEntriesBytes = rawAndSaltedEntriesBySignature .OrderBy(v => v.SaltedAndHashedEntry, ByteUtil.ByteListComparer.Default) .SelectMany(v => v.RawEntry.ToByteArray()) .ToArray(); // dn var signaturesInOrder = includedTransactions .Select(p => p.Signature.ToByteArray()) .OrderBy(s => s, ByteUtil.ByteListComparer.Default) .SelectMany(b => b) .ToArray(); // xf var summedFees = includedTransactions.Sum(t => t.SummedEntryFees()); //∆Ln,j = L(f/E) + dn + E(xf, j) var coinbaseEntry = new CoinbaseEntry { Amount = summedFees.ToUint256ByteString(), ReceiverPublicKey = _producerUniqueId.PublicKey.ToByteString() }; var globalLedgerStateUpdate = shuffledEntriesBytes .Concat(signaturesInOrder) .Concat(coinbaseEntry.ToByteArray()) .ToArray(); //hj var candidate = new CandidateDeltaBroadcast { // h∆j Hash = _hashProvider.ComputeMultiHash(globalLedgerStateUpdate).ToArray().ToByteString(), // Idj ProducerId = _producerUniqueId, PreviousDeltaDfsHash = previousDeltaHash.ToArray().ToByteString() }; _logger.Debug("Building full delta locally"); var producedDelta = new Delta { PreviousDeltaDfsHash = previousDeltaHash.ToArray().ToByteString(), MerkleRoot = candidate.Hash, CoinbaseEntries = { coinbaseEntry }, PublicEntries = { includedTransactions.SelectMany(t => t.PublicEntries) }, TimeStamp = Timestamp.FromDateTime(_dateTimeProvider.UtcNow) }; _logger.Debug("Adding local candidate delta"); _deltaCache.AddLocalDelta(candidate, producedDelta); return(candidate); }