Ejemplo n.º 1
0
 public StateFixture()
 {
     f   = new Final();
     h   = new Hnv();
     pd  = new Prepared();
     ppd = new PrePrepared();
     vcd = new ViewChanged();
     v   = new View();
 }
Ejemplo n.º 2
0
        private IMessage ProcessMessage(State s, ulong sender, ulong receiver, BlockID origin, IMessage msg)
        {
            var(node, round) = msg.NodeRound();
            if (s.Data.ContainsKey(new Final(node, round)))
            {
                return(null);
            }
            var v = s.GetView(node, round);

            Debug.WriteLine($"Processing message from block block.id={origin} message={msg}");

            switch (msg)
            {
            case PrePrepare m:
                if (v != m.View)
                {
                    return(null);
                }
                var pp = new PrePrepared(node, round, m.View);
                if (s.Data.ContainsKey(pp))
                {
                    return(null);
                }
                ulong size = sender > receiver ? sender : receiver;
                // var b = s.GetBitSet(NodeCount, m);
                var b = s.GetBitSet((int)size, m);
                b.SetPrepare(sender);
                b.SetPrepare(receiver);
                if (s.Data == null)
                {
                    s.Data = new StateKV()
                    {
                        { pp, m }
                    };
                }
                else
                {
                    s.Data[pp] = m;
                }
                return(new Prepare(m.Hash, node, round, receiver, m.View));

            case Prepare m:
                if (v > m.View)
                {
                    return(null);
                }
                if (v < m.View)
                {
                    // b = s.GetBitSet(NodeCount, m.Pre());
                    b = s.GetBitSet((int)sender, m.Pre());
                    b.SetPrepare(m.Sender);
                    return(null);
                }
                // b = s.GetBitSet(NodeCount, m.Pre());
                b = s.GetBitSet((int)sender, m.Pre());
                b.SetPrepare(m.Sender);

                Debug.WriteLine($"Prepare count == {b.PrepareCount()}");

                if (b.PrepareCount() != Quorum2f1)
                {
                    return(null);
                }
                if (b.HasCommit(receiver))
                {
                    return(null);
                }
                b.SetCommit(receiver);
                var p = new Prepared(node, round, m.View);
                if (!s.Data.ContainsKey(p))
                {
                    if (s.Data == null)
                    {
                        s.Data = new StateKV()
                        {
                            { p, m.Hash }
                        };
                    }
                    else
                    {
                        s.Data[p] = m.Hash;
                    }
                }
                return(new Commit(m.Hash, node, round, receiver, m.View));

            case Commit m:
                if (v < m.View)
                {
                    return(null);
                }
                // b = s.GetBitSet(NodeCount, m.Pre());
                b = s.GetBitSet((int)sender, m.Pre());
                b.SetCommit(m.Sender);

                Debug.WriteLine($"Commit count == {b.CommitCount()}");

                if (b.CommitCount() != Quorum2f1)
                {
                    return(null);
                }
                var nr = new NodeRound(node, round);
                if (s.Final.ContainsKey(nr))
                {
                    return(null);
                }
                if (s.Final == null)
                {
                    s.Final = new Dictionary <NodeRound, string>()
                    {
                        { nr, m.Hash }
                    };
                }
                else
                {
                    s.Final[nr] = m.Hash;
                }
                Deliver(node, round, m.Hash);
                return(null);

            case ViewChange m:
                if (v > m.View)
                {
                    return(null);
                }
                Dictionary <ulong, string> vcs;
                var key = new ViewChanged(node, round, v);
                if (s.Data.ContainsKey(key))
                {
                    var val = s.Data[key];
                    vcs = (Dictionary <ulong, string>)val;
                }
                else
                {
                    vcs = new Dictionary <ulong, string>();
                    if (s.Data == null)
                    {
                        s.Data = new StateKV()
                        {
                            { key, vcs }
                        };
                    }
                    else
                    {
                        s.Data[key] = vcs;
                    }
                }
                vcs[m.Sender] = m.Hash;
                if (vcs.Count != Quorum2f1)
                {
                    return(null);
                }
                s.Data[new View(node, round)] = m.View;
                var hash = "";
                foreach (KeyValuePair <ulong, string> item in vcs)
                {
                    var hval = item.Value;
                    if (hval != "")
                    {
                        if (hash != "" && hval != hash)
                        {
                            Console.WriteLine($"Got multiple hashes in a view change node.id={node} round={round} hash={hash} hash.alt={hval}");
                        }
                        hash = hval;
                    }
                }
                return(new NewView(hash, node, round, receiver, m.View));

            case NewView m:
                if (v > m.View)
                {
                    return(null);
                }
                var viewKey = new Hnv(node, round, m.View);
                if (s.Data.ContainsKey(viewKey))
                {
                    return(null);
                }
                if (s.Data == null)
                {
                    s.Data = new StateKV();
                }
                s.Data[new View(node, round)] = m.View;
                var tval = origin.Round + s.Timeout + 5;
                if (!s.Timeouts.ContainsKey(tval))
                {
                    s.Timeouts[tval] = new List <Timeout>();
                }
                s.Timeouts[tval].Add(new Timeout(node, round, m.View));
                s.Data[viewKey] = true;
                return(new PrePrepare(m.Hash, node, round, m.View));

            default:
                throw new Exception($"blockmania: unknown message kind to process: {msg.Kind()}");
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="s"></param>
        /// <param name="sender"></param>
        /// <param name="receiver"></param>
        /// <param name="origin"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        private IMessage ProcessMessage(State s, ulong sender, ulong receiver, Block origin, IMessage msg)
        {
            _logger.Here().Debug("State: {@State}, Sender: {@Sender}, Receiver: {@Receiver}, Origin: {@Origin}, Message: {@Message}",
                                 s, sender.ToString(), receiver.ToString(), origin, msg);

            var(node, round) = msg.NodeRound();
            if (s.Data.ContainsKey(new Final(node, round)))
            {
                _logger.Here().Debug("State contains final, node: {@Node}, round: {@Round}",
                                     node, round);

                return(null);
            }
            var v = s.GetView(node, round);

            _logger.Here().Debug("Processing message from block block.id: {@BlockID}, message: {@Message}",
                                 origin, msg);

            switch (msg)
            {
            case PrePrepare m:
                if (v != m.View)
                {
                    return(null);
                }
                var pp = new PrePrepared(node, round, m.View);
                if (s.Data.ContainsKey(pp))
                {
                    return(null);
                }
                var size = sender > receiver ? sender : receiver;
                // var b = s.GetBitSet(NodeCount, m);
                var b = s.GetBitSet((int)size, m);
                b.SetPrepare(sender);
                b.SetPrepare(receiver);
                if (s.Data == null)
                {
                    s.Data = new StateKV {
                        { pp, m }
                    };
                }
                else
                {
                    s.Data[pp] = m;
                }

                _logger.Here().Debug("PrePrepare, node: {@Node}, round: {@Round}, sender: {@Sender}, hash: {@Hash}",
                                     node.ToString(), round.ToString(), receiver.ToString(), m.Hash);

                return(new Prepare(m.Hash, node, round, receiver, m.View));

            case Prepare m:
                if (v > m.View)
                {
                    return(null);
                }
                if (v < m.View)
                {
                    // b = s.GetBitSet(NodeCount, m.Pre());
                    b = s.GetBitSet((int)sender, m.Pre());
                    b.SetPrepare(m.Sender);
                    return(null);
                }
                // b = s.GetBitSet(NodeCount, m.Pre());
                b = s.GetBitSet((int)sender, m.Pre());
                b.SetPrepare(m.Sender);

                _logger.Here().Debug("Prepare count: {@PrepareCount}", b.PrepareCount());

                if (b.PrepareCount() != Quorum2f1)
                {
                    return(null);
                }
                if (b.HasCommit(receiver))
                {
                    return(null);
                }
                b.SetCommit(receiver);
                var p = new Prepared(node, round, m.View);
                if (s.Data.ContainsKey(p))
                {
                    return(new Commit(m.Hash, node, round, receiver, m.View));
                }
                if (s.Data == null)
                {
                    s.Data = new StateKV()
                    {
                        { p, m.Hash }
                    };
                }
                else
                {
                    s.Data[p] = m.Hash;
                }

                _logger.Here().Debug("Prepare, node: {@Node}, round: {@Round}, sender: {@Sender}, hash: {@Hash}",
                                     node.ToString(), round.ToString(), receiver.ToString(), m.Hash);

                return(new Commit(m.Hash, node, round, receiver, m.View));

            case Commit m:
                if (v < m.View)
                {
                    return(null);
                }
                // b = s.GetBitSet(NodeCount, m.Pre());
                b = s.GetBitSet((int)sender, m.Pre());
                b.SetCommit(m.Sender);

                _logger.Here().Debug("Commit count: {@CommitCount}", b.CommitCount());

                if (b.CommitCount() != Quorum2f1)
                {
                    return(null);
                }
                var nr = new NodeRound(node, round);
                if (s.Final.ContainsKey(nr))
                {
                    return(null);
                }
                if (s.Final == null)
                {
                    s.Final = new Dictionary <NodeRound, string>()
                    {
                        { nr, m.Hash }
                    };
                }
                else
                {
                    s.Final[nr] = m.Hash;
                }

                _logger.Here().Debug("Deliver, node: {@Node}, round: {@Round}, hash: {@Hash}",
                                     node.ToString(), round.ToString(), m.Hash);

                Deliver(node, round, m.Hash);
                return(null);

            case ViewChange m:
                if (v > m.View)
                {
                    return(null);
                }
                Dictionary <ulong, string> vcs;
                var key = new ViewChanged(node, round, v);
                if (s.Data.ContainsKey(key))
                {
                    var val = s.Data[key];
                    vcs = (Dictionary <ulong, string>)val;
                }
                else
                {
                    vcs = new Dictionary <ulong, string>();
                    if (s.Data == null)
                    {
                        s.Data = new StateKV()
                        {
                            { key, vcs }
                        };
                    }
                    else
                    {
                        s.Data[key] = vcs;
                    }
                }
                vcs[m.Sender] = m.Hash;
                if (vcs.Count != Quorum2f1)
                {
                    return(null);
                }
                s.Data[new View(node, round)] = m.View;
                var hash = "";
                foreach (var hval in vcs.Select(item => item.Value).Where(hval => hval != ""))
                {
                    if (hash != "" && hval != hash)
                    {
                        _logger.Here().Debug("Got multiple hashes in a view change node.id: {@Node}, round: {Round}, hash={@Hash} hash.alt={@HashAlt}",
                                             node.ToString(), round.ToString(), hash, hval);
                    }
                    hash = hval;
                }

                _logger.Here().Debug("ViewChange, node: {@Node}, round: {@Round}, sender: {@Sender}, hash: {@Hash}",
                                     node.ToString(), round.ToString(), receiver.ToString(), m.Hash);

                return(new NewView(hash, node, round, receiver, m.View));

            case NewView m:
                if (v > m.View)
                {
                    return(null);
                }
                var viewKey = new Hnv(node, round, m.View);
                if (s.Data.ContainsKey(viewKey))
                {
                    return(null);
                }
                s.Data ??= new StateKV();
                s.Data[new View(node, round)] = m.View;
                var tval = origin.Round + s.Timeout + 5;
                if (!s.Timeouts.ContainsKey(tval))
                {
                    s.Timeouts[tval] = new List <Timeout>();
                }
                s.Timeouts[tval].Add(new Timeout(node, round, m.View));
                s.Data[viewKey] = true;

                _logger.Here().Debug("NewView -> PrePrepare, node: {@Node}, round: {@Round}, hash: {@Hash}",
                                     node.ToString(), round.ToString(), m.Hash);

                return(new PrePrepare(m.Hash, node, round, m.View));

            default:
                throw new Exception($"blockmania: unknown message kind to process: {msg.Kind()}");
            }
        }