Exemple #1
0
        public void Run(PrimaryReplica primaryReplica, CancellationToken cancellationToken)
        {
            // process transactions
            // process messages
            Task.Factory.StartNew(async() =>
            {
                Log("Running...");

                while (cancellationToken.IsCancellationRequested == false)
                {
                    var transaction = GenerateTransaction();

                    // Log($"The transaction #{transaction} was generated.");

                    // a new transaction was generated -> send this to primary replica
                    primaryReplica.SendTransaction(transaction);

                    // Log($"The transaction #{transaction} was sent to the primary replica.");

                    await Task.Delay(10);
                }

                Log("Stopped.");
            }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
Exemple #2
0
        private static void RunClients(PrimaryReplica primaryReplica, CancellationToken cancellationToken)
        {
            var clients = Enumerable.Range(0, ClientsCount)
                          .Select(cid => new Client(cid))
                          .ToArray();

            foreach (var client in clients)
            {
                client.Run(primaryReplica, cancellationToken);
            }
        }
Exemple #3
0
        private static PrimaryReplica RunReplicas(CancellationToken cancellationToken)
        {
            var rnd        = new Random(Environment.TickCount);
            var replicaIds = Enumerable.Range(0, ActiveReplicasCount + PassiveReplicasCount + FaultyReplicasCount).ToArray();

            var workingReplicaIds = replicaIds
                                    //.OrderBy(r => rnd.Next(replicaIds.Length))
                                    .Take(ActiveReplicasCount + PassiveReplicasCount)
                                    .ToArray();

            var faultyReplicaIds = replicaIds
                                   .Except(workingReplicaIds)
                                   .ToArray();

            var activeReplicaIds = workingReplicaIds
                                   .Take(ActiveReplicasCount)
                                   .ToArray();

            var passiveReplicaIds = workingReplicaIds
                                    .Except(activeReplicaIds)
                                    .ToArray();

            var primaryReplicaId = activeReplicaIds.First();
            var primaryReplica   = new PrimaryReplica(primaryReplicaId);

            var secondaryReplicas = activeReplicaIds
                                    .Where(rid => rid != primaryReplicaId)
                                    .Select(rid => new Replica(rid, true)
            {
                PrimaryReplica = primaryReplica
            })
                                    .ToArray();


            foreach (var secondaryReplica in secondaryReplicas)
            {
                secondaryReplica.Run(secondaryReplicas, cancellationToken);
            }

            primaryReplica.Run(secondaryReplicas, cancellationToken);

            return(primaryReplica);
        }
        public static void Handle(
            TransactionMessage message,
            PrimaryReplica primaryReplica,
            ref ConcurrentBag <int> block,
            ConcurrentQueue <int[]> blockExchange)
        {
            var transaction = message.Transaction;

            block.Add(transaction);

            var now = DateTime.Now;

            if (block.Count >= MinTransactionsCountInBlock)
            {
                var blockCopy = block.ToArray();

                block = new ConcurrentBag <int>();

                // publish block to start working on consensus
                blockExchange.Enqueue(blockCopy);

                Log(primaryReplica, $"New block arrived for consensus (TransactionCounts: {blockCopy.Length}).");
            }
        }
Exemple #5
0
        public static void Handle(
            SecretShareMessage message,
            PrimaryReplica primaryReplica,
            IEnumerable <ReplicaBase> activeRelicas,
            int[] block,
            ICollection <int[]> blockchain,
            ref bool isCommitted,
            ref bool hasConsensus,
            byte[] signedSecretHashAndCounterViewNumber,
            ConcurrentDictionary <int, string> verifiedChildShareSecrets)
        {
            var childReplicaId       = message.ReplicaId;
            var childrenSecretShares = message.ReplicaSecretShares;

            Log(primaryReplica, "ChildReplicaId: {0}, ChildrenSecretShare: [{1}]", childReplicaId, string.Join(",", childrenSecretShares.Select(ridssh => $"{{{ridssh.Key}:{ridssh.Value}}}")));

            foreach (var childReplicaShare in childrenSecretShares)
            {
                // TODO: hashes of primary children should be checked as well
                verifiedChildShareSecrets.TryAdd(childReplicaShare.Key, childReplicaShare.Value);
            }

            if (verifiedChildShareSecrets.Keys.OrderBy(_ => _)
                .SequenceEqual(activeRelicas.Select(r => r.Id).OrderBy(_ => _)) == false)
            {
                return;
            }

            var verifiedSecretShares = verifiedChildShareSecrets
                                       .Select(x => new { ReplicaId = x.Key, SecretShare = x.Value })
                                       .OrderBy(x => x.ReplicaId)
                                       .Select(x => x.SecretShare)
                                       .ToList();

            var secret = string.Join(string.Empty, verifiedSecretShares);

            uint secretHash;
            uint counter;
            uint viewNumber;

            primaryReplica.Tee.GetHashAndCounterViewNumber(
                primaryReplica.PublicKey,
                signedSecretHashAndCounterViewNumber,
                out secretHash,
                out counter,
                out viewNumber);

            if (Crypto.GetHash(secret + counter + viewNumber) != secretHash)
            {
                Log(primaryReplica, "Send RequestViewChangeMessage to all active replicas.");
                throw new InvalidOperationException("Invalid secret hash.");
            }

            if (!isCommitted)
            {
                verifiedChildShareSecrets.Clear();

                Thread.Sleep(rnd.Next(MinTimeToAddBlockIntoBlockchain, MaxTimeToAddBlockIntoBlockchain));

                blockchain.Add(block);

                var request          = string.Join(string.Empty, block);
                var commitResult     = blockchain.Count;
                var commitResultHash = Crypto.GetHash(request) | (uint)commitResult;

                var signedCommitResultHashCounterViewNumber = primaryReplica.Tee.RequestCounter(commitResultHash);

                Log(primaryReplica, "Broadcast a committed block.");

                // the block was added on primary replica to blockchain -> we need to sync this across replicas
                Network.EmulateLatency();

                foreach (var activeRelica in activeRelicas)
                {
                    activeRelica.SendMessage(new CommitMessage
                    {
                        Secret       = secret,
                        CommitResult = commitResult,
                        CommitResultHashCounterViewNumber = signedCommitResultHashCounterViewNumber
                    });
                }

                isCommitted = true;
            }
            else
            {
                hasConsensus = true;
            }
        }