-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Commit phase - AKKA Model #422
Changes from 7 commits
63847fc
064ebc9
5f3e99a
f0c2ada
14a31e6
6b23061
c8eb77b
bdb9d96
91dcaad
d1d950d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
using System.IO; | ||
using Neo.IO; | ||
|
||
namespace Neo.Consensus | ||
{ | ||
internal class CommitAgreement : ConsensusMessage | ||
{ | ||
/// <summary> | ||
/// Block hash of the signature | ||
/// </summary> | ||
public UInt256 BlockHash; | ||
|
||
/// <summary> | ||
/// Constructors | ||
/// </summary> | ||
public CommitAgreement() : base(ConsensusMessageType.CommitAgreement) { } | ||
|
||
public override void Deserialize(BinaryReader reader) | ||
{ | ||
base.Deserialize(reader); | ||
BlockHash = reader.ReadSerializable<UInt256>(); | ||
} | ||
|
||
public override void Serialize(BinaryWriter writer) | ||
{ | ||
base.Serialize(writer); | ||
writer.Write(BlockHash); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -74,6 +74,18 @@ private void ChangeTimer(TimeSpan delay) | |||||
private void CheckExpectedView(byte view_number) | ||||||
{ | ||||||
if (context.ViewNumber == view_number) return; | ||||||
if (context.State.HasFlag(ConsensusState.CommitSent)) | ||||||
{ | ||||||
if (context.State.HasFlag(ConsensusState.SignatureSent)) | ||||||
{ | ||||||
// If signature was sent, we send again | ||||||
|
||||||
SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex])); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @shargon ,if a node (in commit phase) receives change view request, and re-send prepareResponse. From current code, the node (who have sent the changeView request ) will not accept prepareResponse because the viewNumber does not match. We may need to find a way to accept the re-send prepareResponse. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is just for dropped packets (network errors), maybe there are a disconnection, and this packet never arrive to your CN. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes. Imagine one CN(A) sent ChangeView request to other CN if it did not collect enough PrepareResponse on time because the network error. Then A increases its view number. But when other CN(B) receives the ChangeView message, it resends prepareResponse because B is in commit phase now. In this situation, even if A re-connect with B, A will not accept B's resent prepareResponse message because view numbers do not match anymore. But we need to let A accepts this message and move on to commit phase as B, right ? |
||||||
} | ||||||
|
||||||
return; | ||||||
} | ||||||
|
||||||
if (context.ExpectedView.Count(p => p == view_number) >= context.M) | ||||||
{ | ||||||
InitializeConsensus(view_number); | ||||||
|
@@ -82,8 +94,30 @@ private void CheckExpectedView(byte view_number) | |||||
|
||||||
private void CheckSignatures() | ||||||
{ | ||||||
if (!context.State.HasFlag(ConsensusState.CommitSent) && | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @shargon, neo/neo/Consensus/ConsensusService.cs Line 353 in 064ebc9
neo/neo/Consensus/ConsensusService.cs Line 52 in 064ebc9
|
||||||
context.Signatures.Count(p => p != null) >= context.M && | ||||||
context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) | ||||||
{ | ||||||
// Send my commit | ||||||
|
||||||
context.State |= ConsensusState.CommitSent; | ||||||
SignAndRelay(context.MakeCommitAgreement()); | ||||||
|
||||||
Log($"Commit sent: height={context.BlockIndex} hash={context.CommitHash} state={context.State}"); | ||||||
} | ||||||
} | ||||||
|
||||||
private void OnCommitAgreement(ConsensusPayload payload, CommitAgreement message) | ||||||
{ | ||||||
if (context.State.HasFlag(ConsensusState.BlockSent) || | ||||||
!context.TryToCommit(payload, message)) return; | ||||||
|
||||||
Log($"{nameof(OnCommitAgreement)}: height={payload.BlockIndex} hash={message.BlockHash.ToString()} view={message.ViewNumber} index={payload.ValidatorIndex}"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||
|
||||||
if (context.Signatures.Count(p => p != null) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) | ||||||
{ | ||||||
context.State |= ConsensusState.BlockSent; | ||||||
|
||||||
Contract contract = Contract.CreateMultiSigContract(context.M, context.Validators); | ||||||
Block block = context.MakeHeader(); | ||||||
ContractParametersContext sc = new ContractParametersContext(block); | ||||||
|
@@ -96,8 +130,8 @@ private void CheckSignatures() | |||||
sc.Verifiable.Witnesses = sc.GetWitnesses(); | ||||||
block.Transactions = context.TransactionHashes.Select(p => context.Transactions[p]).ToArray(); | ||||||
Log($"relay block: {block.Hash}"); | ||||||
|
||||||
system.LocalNode.Tell(new LocalNode.Relay { Inventory = block }); | ||||||
context.State |= ConsensusState.BlockSent; | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -178,18 +212,21 @@ private void Log(string message, LogLevel level = LogLevel.Info) | |||||
|
||||||
private void OnChangeViewReceived(ConsensusPayload payload, ChangeView message) | ||||||
{ | ||||||
Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber}"); | ||||||
if (message.NewViewNumber <= context.ExpectedView[payload.ValidatorIndex]) | ||||||
return; | ||||||
|
||||||
Log($"{nameof(OnChangeViewReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} nv={message.NewViewNumber}"); | ||||||
|
||||||
context.ExpectedView[payload.ValidatorIndex] = message.NewViewNumber; | ||||||
CheckExpectedView(message.NewViewNumber); | ||||||
} | ||||||
|
||||||
private void OnConsensusPayload(ConsensusPayload payload) | ||||||
{ | ||||||
if (payload.ValidatorIndex == context.MyIndex) return; | ||||||
if (payload.Version != ConsensusContext.Version) | ||||||
return; | ||||||
if (payload.ValidatorIndex == context.MyIndex || | ||||||
payload.Version != ConsensusContext.Version || | ||||||
payload.ValidatorIndex >= context.Validators.Length) return; | ||||||
|
||||||
if (payload.PrevHash != context.PrevHash || payload.BlockIndex != context.BlockIndex) | ||||||
{ | ||||||
if (context.Snapshot.Height + 1 < payload.BlockIndex) | ||||||
|
@@ -198,7 +235,7 @@ private void OnConsensusPayload(ConsensusPayload payload) | |||||
} | ||||||
return; | ||||||
} | ||||||
if (payload.ValidatorIndex >= context.Validators.Length) return; | ||||||
|
||||||
ConsensusMessage message; | ||||||
try | ||||||
{ | ||||||
|
@@ -208,8 +245,10 @@ private void OnConsensusPayload(ConsensusPayload payload) | |||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
if (message.ViewNumber != context.ViewNumber && message.Type != ConsensusMessageType.ChangeView) | ||||||
return; | ||||||
|
||||||
switch (message.Type) | ||||||
{ | ||||||
case ConsensusMessageType.ChangeView: | ||||||
|
@@ -221,6 +260,9 @@ private void OnConsensusPayload(ConsensusPayload payload) | |||||
case ConsensusMessageType.PrepareResponse: | ||||||
OnPrepareResponseReceived(payload, (PrepareResponse)message); | ||||||
break; | ||||||
case ConsensusMessageType.CommitAgreement: | ||||||
OnCommitAgreement(payload, (CommitAgreement)message); | ||||||
break; | ||||||
} | ||||||
} | ||||||
|
||||||
|
@@ -233,15 +275,22 @@ private void OnPersistCompleted(Block block) | |||||
|
||||||
private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest message) | ||||||
{ | ||||||
if (context.State.HasFlag(ConsensusState.RequestReceived)) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good move! Avoiding this repeated message. |
||||||
return; | ||||||
|
||||||
Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}"); | ||||||
if (!context.State.HasFlag(ConsensusState.Backup) || context.State.HasFlag(ConsensusState.RequestReceived)) | ||||||
|
||||||
if (!context.State.HasFlag(ConsensusState.Backup)) | ||||||
return; | ||||||
|
||||||
if (payload.ValidatorIndex != context.PrimaryIndex) return; | ||||||
|
||||||
if (payload.Timestamp <= context.Snapshot.GetHeader(context.PrevHash).Timestamp || payload.Timestamp > DateTime.UtcNow.AddMinutes(10).ToTimestamp()) | ||||||
{ | ||||||
Log($"Timestamp incorrect: {payload.Timestamp}", LogLevel.Warning); | ||||||
return; | ||||||
} | ||||||
|
||||||
context.State |= ConsensusState.RequestReceived; | ||||||
context.Timestamp = payload.Timestamp; | ||||||
context.Nonce = message.Nonce; | ||||||
|
@@ -271,9 +320,11 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m | |||||
|
||||||
private void OnPrepareResponseReceived(ConsensusPayload payload, PrepareResponse message) | ||||||
{ | ||||||
Log($"{nameof(OnPrepareResponseReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex}"); | ||||||
if (context.State.HasFlag(ConsensusState.BlockSent)) return; | ||||||
if (context.Signatures[payload.ValidatorIndex] != null) return; | ||||||
|
||||||
Log($"{nameof(OnPrepareResponseReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex}"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Very good! |
||||||
|
||||||
Block header = context.MakeHeader(); | ||||||
if (header == null || !Crypto.Default.VerifySignature(header.GetHashData(), message.Signature, context.Validators[payload.ValidatorIndex].EncodePoint(false))) return; | ||||||
context.Signatures[payload.ValidatorIndex] = message.Signature; | ||||||
|
@@ -360,6 +411,20 @@ public static Props Props(NeoSystem system, Wallet wallet) | |||||
|
||||||
private void RequestChangeView() | ||||||
{ | ||||||
if (context.State.HasFlag(ConsensusState.CommitSent)) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let's remove this and filter before, @shargon. else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || (context.State.HasFlag(ConsensusState.Backup) && !context.State.HasFlag(ConsensusState.CommitSent)) ) at line neo/neo/Consensus/ConsensusService.cs Line 384 in 6b23061
|
||||||
{ | ||||||
// Lock view change on timer | ||||||
|
||||||
if (context.State.HasFlag(ConsensusState.SignatureSent)) | ||||||
{ | ||||||
// If signature was sent, we send again | ||||||
|
||||||
SignAndRelay(context.MakePrepareResponse(context.Signatures[context.MyIndex])); | ||||||
} | ||||||
|
||||||
return; | ||||||
} | ||||||
|
||||||
context.State |= ConsensusState.ViewChanging; | ||||||
context.ExpectedView[context.MyIndex]++; | ||||||
Log($"request change view: height={context.BlockIndex} view={context.ViewNumber} nv={context.ExpectedView[context.MyIndex]} state={context.State}"); | ||||||
|
@@ -370,6 +435,8 @@ private void RequestChangeView() | |||||
|
||||||
private void SignAndRelay(ConsensusPayload payload) | ||||||
{ | ||||||
if (payload == null) return; | ||||||
|
||||||
ContractParametersContext sc; | ||||||
try | ||||||
{ | ||||||
|
@@ -380,6 +447,7 @@ private void SignAndRelay(ConsensusPayload payload) | |||||
{ | ||||||
return; | ||||||
} | ||||||
|
||||||
sc.Verifiable.Witnesses = sc.GetWitnesses(); | ||||||
system.LocalNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,5 +13,6 @@ internal enum ConsensusState : byte | |
SignatureSent = 0x10, | ||
BlockSent = 0x20, | ||
ViewChanging = 0x40, | ||
CommitSent = 0x80, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct 0x80. |
||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you need to Relay your CommitAgreement again too. Not sure. Or is it implicit by PrepareResponse message?