public void BuildDeltaEmptyPoolContent()
        {
            var transactionRetriever = Substitute.For <IDeltaTransactionRetriever>();

            transactionRetriever.GetMempoolTransactionsByPriority()
            .Returns(new List <TransactionBroadcast>());

            var deltaBuilder = new DeltaBuilder(transactionRetriever, _randomFactory, _hashProvider, _peerSettings, _cache, _dateTimeProvider, _logger);

            var candidate = deltaBuilder.BuildCandidateDelta(_previousDeltaHash);

            ValidateDeltaCandidate(candidate, _zeroCoinbaseEntry.ToByteArray());

            _cache.Received(1).AddLocalDelta(Arg.Is(candidate), Arg.Any <Delta>());
        }
        public void BuildDeltaCheckForAccuracy()
        {
            var transactions = Enumerable.Range(0, 20).Select(i =>
            {
                var transaction = TransactionHelper.GetPublicTransaction(
                    amount: (uint)i,
                    receiverPublicKey: i.ToString(),
                    transactionFees: (ulong)_random.Next(),
                    timestamp: _random.Next(),
                    signature: i.ToString());
                return(transaction);
            }).ToList();

            var transactionRetriever = Substitute.For <IDeltaTransactionRetriever>();

            transactionRetriever.GetMempoolTransactionsByPriority().Returns(transactions);

            var selectedTransactions = transactions.Where(t => t.IsPublicTransaction && t.HasValidEntries()).ToArray();

            var expectedCoinBase = new CoinbaseEntry
            {
                Amount            = selectedTransactions.Sum(t => t.SummedEntryFees()).ToUint256ByteString(),
                ReceiverPublicKey = _producerId.PublicKey.ToByteString()
            };

            var salt = BitConverter.GetBytes(
                _randomFactory.GetDeterministicRandomFromSeed(_previousDeltaHash.ToArray()).NextInt());

            var rawAndSaltedEntriesBySignature = selectedTransactions.SelectMany(
                t => t.PublicEntries.Select(e => new
            {
                RawEntry             = e,
                SaltedAndHashedEntry = _hashProvider.ComputeMultiHash(e.ToByteArray().Concat(salt))
            }));

            var shuffledEntriesBytes = rawAndSaltedEntriesBySignature
                                       .OrderBy(v => v.SaltedAndHashedEntry.ToArray(), ByteUtil.ByteListComparer.Default)
                                       .SelectMany(v => v.RawEntry.ToByteArray())
                                       .ToArray();

            var signaturesInOrder = selectedTransactions
                                    .Select(p => p.Signature.ToByteArray())
                                    .OrderBy(s => s, ByteUtil.ByteListComparer.Default)
                                    .SelectMany(b => b)
                                    .ToArray();

            var expectedBytesToHash = shuffledEntriesBytes.Concat(signaturesInOrder)
                                      .Concat(expectedCoinBase.ToByteArray()).ToArray();

            var deltaBuilder = new DeltaBuilder(transactionRetriever, _randomFactory, _hashProvider, _peerSettings, _cache, _dateTimeProvider, _logger);
            var candidate    = deltaBuilder.BuildCandidateDelta(_previousDeltaHash);

            ValidateDeltaCandidate(candidate, expectedBytesToHash);

            _cache.Received(1).AddLocalDelta(Arg.Is(candidate), Arg.Any <Delta>());
        }
Ejemplo n.º 3
0
        private byte[] BuildExpectedBytesToHash(PublicEntry[] selectedTransactions, byte[] shuffledEntriesBytes)
        {
            var signaturesInOrder = selectedTransactions
                                    .Select(p => p.Signature.ToByteArray())
                                    .OrderBy(s => s, ByteUtil.ByteListComparer.Default)
                                    .SelectMany(b => b)
                                    .ToArray();

            var expectedCoinBase = new CoinbaseEntry
            {
                Amount            = selectedTransactions.Sum(t => t.GasPrice.ToUInt256() * t.GasLimit).ToUint256ByteString(),
                ReceiverPublicKey = _producerId.PublicKey.ToByteString()
            };

            var expectedBytesToHash = shuffledEntriesBytes.Concat(signaturesInOrder)
                                      .Concat(expectedCoinBase.ToByteArray()).ToArray();

            return(expectedBytesToHash);
        }
        ///<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);
        }