public override void Bind(Instance r) { WaitQuorum(r, MessageType.Propose, msgs => { var x = PickMostFrequentValue( msgs.Where(m => Archiver.CanCommit(m.Value)) ); var v = x.Count > r.Proposers.Count / 2 ? x.Value : null; Broadcast(r, MessageType.Select, v); }); WaitQuorum(r, MessageType.Select, msgs => { var x = PickMostFrequentValue(msgs.Where(m => m.Value != null)); if (x.Count >= f + 1) { Terminate(r, x.Value); Proposer.Reset(); } else { if (x.Count > 0) { Proposer.Set(x.Value); } else { Proposer.Reset(); } } }); }
private void BindAsAccepter(Instance r) { WaitMessage(r, MessageType.Propose, msg => { var n = (long)msg.Value; if (n > minNumber) { minNumber = n; SendTo(msg.Source, r, MessageType.Ack, accepted); } else { SendTo(msg.Source, r, MessageType.Nack, minNumber); } }); WaitMessage(r, MessageType.Select, msg => { var x = msg.Value as NumberedValue; if (x.Number >= minNumber && Archiver.CanCommit(x.Value)) { accepted = x; SendTo(msg.Source, r, MessageType.Accept, x); } }); WaitMessage(r, MessageType.Decide, msg => { var x = msg.Value as NumberedValue; Terminate(r, x); }); }
private void BindAsCoordinator(Instance r) { WaitQuorum(r, MessageType.Propose, msgs => { var v = PickMostRecentValue( msgs.Where(m => Archiver.CanCommit(m.Value)) ); Broadcast(r, MessageType.Select, v); }); WaitQuorum(r, MessageType.Ack, msgs => { var v = PickMostRecentValue(msgs); Broadcast(r, MessageType.Decide, v); Terminate(r, v); }); }
private void BindAsProposer(Instance r) { WaitQuorum(r, MessageType.Ack, msgs => { var v = PickHighestNumberedValue(msgs)?.Value ?? Proposer.GetProposal(); if (Archiver.CanCommit(v)) { var x = new NumberedValue(v, proposalNumber); Broadcast(r, MessageType.Select, x); } }); WaitMessage(r, MessageType.Nack, msg => { if (msg.Value != null) { var n = (long)msg.Value; if (n > minNumber) { minNumber = Math.Max(n, minNumber); if (RandomExtensions.Tryout(0.5)) { Propose(r); } } } }); WaitQuorum(r, MessageType.Accept, msgs => { var m = msgs.Select(m => m.Value).Distinct(); if (m.Count() == 1) { var x = m.Single() as NumberedValue; Terminate(r, x); Broadcast(r, MessageType.Decide, x); } }); }
private Block MineBlock(Instance r) { Block b = null; var found = false; var v = Proposer.GetProposal(); var c = counter; while (!IsTerminated(r) && Archiver.CanCommit(v) && !found) { if (b == null || counter > c) { c = counter; var h = GetHeadFromLongestChain(v); if (h == null) { break; } b = new Block(v, h); } b.IncrementPoW(); found = b.VerifyPoW(); } return(found ? b : null); }