From e97daeb3e6ee59c1f69b55f7ede5b1310109f76a Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 13:16:34 -0300 Subject: [PATCH 01/43] Draft 0.1 for dBFT 3.0 --- .../Consensus/ConsensusContext.Get.cs | 9 ++- .../Consensus/ConsensusContext.MakePayload.cs | 58 ++++++++++++------- src/DBFTPlugin/Consensus/ConsensusContext.cs | 26 ++++++--- .../Consensus/ConsensusService.Check.cs | 50 +++++++++++----- .../Consensus/ConsensusService.OnMessage.cs | 43 ++++++++------ src/DBFTPlugin/Consensus/ConsensusService.cs | 52 +++++++++++------ src/DBFTPlugin/Messages/Commit.cs | 7 ++- src/DBFTPlugin/Messages/PreCommit.cs | 30 ++++++++++ src/DBFTPlugin/Messages/PrepareResponse.cs | 4 ++ src/DBFTPlugin/Types/ConsensusMessageType.cs | 1 + 10 files changed, 196 insertions(+), 84 deletions(-) create mode 100644 src/DBFTPlugin/Messages/PreCommit.cs diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 5f1b69560..2e3b02940 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -56,12 +56,19 @@ private PreparationPayloadCompact GetPreparationPayloadCompact(ExtensiblePayload } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte GetPrimaryIndex(byte viewNumber) + public byte GetPriorityPrimaryIndex(byte viewNumber) { int p = ((int)Block.Index - viewNumber) % Validators.Length; return p >= 0 ? (byte)p : (byte)(p + Validators.Length); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public byte GetFallbackPrimaryIndex(byte viewNumber) + { + int p = ((int)Block.Index - viewNumber + 1) % Validators.Length; + return p >= 0 ? (byte)p : (byte)(p + Validators.Length); + } + public UInt160 GetSender(int index) { return Contract.CreateSignatureRedeemScript(Validators[index]).ToScriptHash(); diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index e8af9f0ad..fb5d79a93 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -21,11 +21,12 @@ public ExtensiblePayload MakeChangeView(ChangeViewReason reason) }); } - public ExtensiblePayload MakeCommit() + public ExtensiblePayload MakeCommit(uint i) { - return CommitPayloads[MyIndex] ?? (CommitPayloads[MyIndex] = MakeSignedPayload(new Commit + return CommitPayloads[i][MyIndex] ?? (CommitPayloads[i][MyIndex] = MakeSignedPayload(new Commit { - Signature = EnsureHeader().Sign(keyPair, neoSystem.Settings.Network) + Signature = EnsureHeader().Sign(keyPair, neoSystem.Settings.Network), + Id = i })); } @@ -58,7 +59,7 @@ private void SignPayload(ExtensiblePayload payload) /// Prevent that block exceed the max size /// /// Ordered transactions - internal void EnsureMaxBlockLimitation(IEnumerable txs) + internal void EnsureMaxBlockLimitation(IEnumerable txs, uint i) { uint maxTransactionsPerBlock = neoSystem.Settings.MaxTransactionsPerBlock; @@ -66,8 +67,8 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs) txs = txs.Take((int)maxTransactionsPerBlock); List hashes = new List(); - Transactions = new Dictionary(); - VerificationContext = new TransactionVerificationContext(); + Transactions[i] = new Dictionary(); + VerificationContext[i] = new TransactionVerificationContext(); // Expected block size var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); @@ -85,25 +86,26 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs) if (blockSystemFee > dbftSettings.MaxBlockSystemFee) break; hashes.Add(tx.Hash); - Transactions.Add(tx.Hash, tx); - VerificationContext.AddTransaction(tx); + Transactions[i].Add(tx.Hash, tx); + VerificationContext[i].AddTransaction(tx); } - TransactionHashes = hashes.ToArray(); + TransactionHashes[i] = hashes.ToArray(); } - public ExtensiblePayload MakePrepareRequest() + public ExtensiblePayload MakePrepareRequest(uint i) { - EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions()); - Block.Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); - Block.Header.Nonce = GetNonce(); - return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest + EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions(), i); + Block[i].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); + Block[i].Header.Nonce = GetNonce(); + + return PreparationPayloads[i][MyIndex] = MakeSignedPayload(new PrepareRequest { - Version = Block.Version, - PrevHash = Block.PrevHash, - Timestamp = Block.Timestamp, - Nonce = Block.Nonce, - TransactionHashes = TransactionHashes + Version = Block[i].Version, + PrevHash = Block[i].PrevHash, + Timestamp = Block[i].Timestamp, + Nonce = Block[i].Nonce, + TransactionHashes = TransactionHashes[i] }); } @@ -144,11 +146,23 @@ public ExtensiblePayload MakeRecoveryMessage() }); } - public ExtensiblePayload MakePrepareResponse() + public ExtensiblePayload MakePrepareResponse(uint i) + { + return PreparationPayloads[i][MyIndex] = MakeSignedPayload(new PrepareResponse + { + PreparationHash = PreparationPayloads[i][Block[i].PrimaryIndex].Hash, + Id = i + }); + } + + + + public ExtensiblePayload MakePreCommit(uint i) { - return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareResponse + return PreCommitPayloads[MyIndex] = MakeSignedPayload(new PreCommit { - PreparationHash = PreparationPayloads[Block.PrimaryIndex].Hash + PreparationHash = PreparationPayloads[Block[i].PrimaryIndex].Hash, + Id = i }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 990b84961..f60a54075 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -22,14 +22,15 @@ public partial class ConsensusContext : IDisposable, ISerializable /// private static readonly byte[] ConsensusStateKey = { 0xf4 }; - public Block Block; + public Block[] Block; public byte ViewNumber; public ECPoint[] Validators; public int MyIndex; - public UInt256[] TransactionHashes; - public Dictionary Transactions; - public ExtensiblePayload[] PreparationPayloads; - public ExtensiblePayload[] CommitPayloads; + public UInt256[][] TransactionHashes; + public Dictionary[] Transactions; + public ExtensiblePayload[][] PreparationPayloads; + public ExtensiblePayload[][] PreCommitPayloads; + public ExtensiblePayload[][] CommitPayloads; public ExtensiblePayload[] ChangeViewPayloads; public ExtensiblePayload[] LastChangeViewPayloads; // LastSeenMessage array stores the height of the last seen message, for each validator. @@ -39,7 +40,7 @@ public partial class ConsensusContext : IDisposable, ISerializable /// /// Store all verified unsorted transactions' senders' fee currently in the consensus context. /// - public TransactionVerificationContext VerificationContext = new(); + public TransactionVerificationContext[] VerificationContext = new(); public SnapshotCache Snapshot { get; private set; } private KeyPair keyPair; @@ -52,8 +53,15 @@ public partial class ConsensusContext : IDisposable, ISerializable public int F => (Validators.Length - 1) / 3; public int M => Validators.Length - F; - public bool IsPrimary => MyIndex == Block.PrimaryIndex; - public bool IsBackup => MyIndex >= 0 && MyIndex != Block.PrimaryIndex; + + public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); + public bool IsFallbackPrimary => MyIndex == GetFallbackPrimaryIndex(ViewNumber); + + public bool IsAPrimary => IsPriorityPrimary !!IsFallbackPrimary; + +//Modify to be 1 or 4/3 + public float PrimaryTimerMultiplier => 1; + public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block.PrevHash); public int CountCommitted => CommitPayloads.Count(p => p != null); @@ -241,7 +249,7 @@ public void Reset(byte viewNumber) LastChangeViewPayloads[i] = null; } ViewNumber = viewNumber; - Block.Header.PrimaryIndex = GetPrimaryIndex(viewNumber); + Block.Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); Block.Header.MerkleRoot = null; Block.Header.Timestamp = 0; Block.Header.Nonce = 0; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index aa5878248..a0098570e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -9,13 +9,13 @@ namespace Neo.Consensus { partial class ConsensusService { - private bool CheckPrepareResponse() + private bool CheckPrepareResponse(uint i) { - if (context.TransactionHashes.Length == context.Transactions.Count) + if (context.TransactionHashes[i].Length == context.Transactions.Count) { // if we are the primary for this view, but acting as a backup because we recovered our own // previously sent prepare request, then we don't want to send a prepare response. - if (context.IsPrimary || context.WatchOnly) return true; + if (context.IsAPrimary || context.WatchOnly) return true; // Check maximum block size via Native Contract policy if (context.GetExpectedBlockSize() > dbftSettings.MaxBlockSize) @@ -37,21 +37,36 @@ private bool CheckPrepareResponse() ExtendTimerByFactor(2); Log($"Sending {nameof(PrepareResponse)}"); - localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareResponse() }); - CheckPreparations(); + localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareResponse(i) }); + CheckPreparations(i); } return true; } - private void CheckCommits() + private void CheckPreCommits(uint i, bool forced = false) { - if (context.CommitPayloads.Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) + if (forced || context.PreCommitPayloads[i].Count(p => p != null) >= context.M && context.TransactionHashes[i].All(p => context.Transactions.ContainsKey(p))) + { + ExtensiblePayload payload = context.MakeCommit(i); + Log($"Sending {nameof(Commit)} to pOrF={i}"); + context.Save(); + localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); + // Set timer, so we will resend the commit in case of a networking issue + ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); + CheckCommits(i); + } + } + + private void CheckCommits(uint i) + { + if (context.CommitPayloads[i].Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) { block_received_index = context.Block.Index; block_received_time = TimeProvider.Current.UtcNow; Block block = context.CreateBlock(); - Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length}"); + Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} to pOrF={i}"); blockchain.Tell(block); + return; } } @@ -74,17 +89,26 @@ private void CheckExpectedView(byte viewNumber) } } - private void CheckPreparations() + private void CheckPreparations(uint i) { - if (context.PreparationPayloads.Count(p => p != null) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) + int thresholdForPrep = context.F + 1; + if (i == 1) + thresholdForPrep = context.M; + + if (context.PreparationPayloads[i].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) { - ExtensiblePayload payload = context.MakeCommit(); - Log($"Sending {nameof(Commit)}"); + ExtensiblePayload payload = context.MakePreCommit(i); + Log($"Sending {nameof(PreCommit)} pOrF={i}"); context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); - CheckCommits(); + CheckPreCommits(i); + + // Speed-up path to also send commit + if (i == 0 && context.PreparationPayloads[0].Count(p => p != null) >= context.M) + CheckPreCommits(0, true); + return; } } } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 32d2cce06..e2357f872 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -70,17 +70,21 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; + // Add verification for Fallback if (message.ValidatorIndex != context.Block.PrimaryIndex || message.ViewNumber != context.ViewNumber) return; if (message.Version != context.Block.Version || message.PrevHash != context.Block.PrevHash) return; if (message.TransactionHashes.Length > neoSystem.Settings.MaxTransactionsPerBlock) return; - Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length}"); + uint pOrF = Convert.ToUInt32(message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)); + + + Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)} fallback={message.ValidatorIndex == context.GetFallbackPrimaryIndex(context.ViewNumber)}"); if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMilliseconds(8 * neoSystem.Settings.MillisecondsPerBlock).ToTimestampMS()) { Log($"Timestamp incorrect: {message.Timestamp}", LogLevel.Warning); return; } - if (message.TransactionHashes.Any(p => NativeContract.Ledger.ContainsTransaction(context.Snapshot, p))) + if (message.TransactionHashes[pOrF].Any(p => NativeContract.Ledger.ContainsTransaction(context.Snapshot, p))) { Log($"Invalid request: transaction already exists", LogLevel.Warning); return; @@ -90,33 +94,34 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); - context.Block.Header.Timestamp = message.Timestamp; - context.Block.Header.Nonce = message.Nonce; - context.TransactionHashes = message.TransactionHashes; + context.Block[pOrF].Header.Timestamp = message.Timestamp; + context.Block[pOrF].Header.Nonce = message.Nonce; + context.TransactionHashes[pOrF] = message.TransactionHashes; context.Transactions = new Dictionary(); context.VerificationContext = new TransactionVerificationContext(); - for (int i = 0; i < context.PreparationPayloads.Length; i++) - if (context.PreparationPayloads[i] != null) - if (!context.GetMessage(context.PreparationPayloads[i]).PreparationHash.Equals(payload.Hash)) - context.PreparationPayloads[i] = null; - context.PreparationPayloads[message.ValidatorIndex] = payload; + for (int i = 0; i < context.PreparationPayloads[pOrF].Length; i++) + if (context.PreparationPayloads[pOrF][i] != null) + if (!context.GetMessage(context.PreparationPayloads[pOrF][i]).PreparationHash.Equals(payload.Hash)) + context.PreparationPayloads[pOrF][i] = null; + context.PreparationPayloads[pOrF][message.ValidatorIndex] = payload; byte[] hashData = context.EnsureHeader().GetSignData(neoSystem.Settings.Network); - for (int i = 0; i < context.CommitPayloads.Length; i++) - if (context.GetMessage(context.CommitPayloads[i])?.ViewNumber == context.ViewNumber) - if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[i]).Signature, context.Validators[i])) - context.CommitPayloads[i] = null; + for (int i = 0; i < context.CommitPayloads[pOrF].Length; i++) + if (context.GetMessage(context.CommitPayloads[pOrF][i])?.ViewNumber == context.ViewNumber) + if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pOrF][i]).Signature, context.Validators[i])) + context.CommitPayloads[pOrF][i] = null; - if (context.TransactionHashes.Length == 0) + if (context.TransactionHashes[pOrF].Length == 0) { // There are no tx so we should act like if all the transactions were filled - CheckPrepareResponse(); + CheckPrepareResponse(pOrF); return; } Dictionary mempoolVerified = neoSystem.MemPool.GetVerifiedTransactions().ToDictionary(p => p.Hash); List unverified = new List(); - foreach (UInt256 hash in context.TransactionHashes) + //Cash previous asked TX Hashes + foreach (UInt256 hash in context.TransactionHashes[pOrF]) { if (mempoolVerified.TryGetValue(hash, out Transaction tx)) { @@ -132,9 +137,9 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest foreach (Transaction tx in unverified) if (!AddTransaction(tx, true)) return; - if (context.Transactions.Count < context.TransactionHashes.Length) + if (context.Transactions.Count < context.TransactionHashes[pOrF].Length) { - UInt256[] hashes = context.TransactionHashes.Where(i => !context.Transactions.ContainsKey(i)).ToArray(); + UInt256[] hashes = context.TransactionHashes[pOrF].Where(i => !context.Transactions.ContainsKey(i)).ToArray(); taskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index a6130c741..b7a2a67ae 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -72,15 +72,16 @@ private void InitializeConsensus(byte viewNumber) Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); Log($"Initialize: height={context.Block.Index} view={viewNumber} index={context.MyIndex} role={(context.IsPrimary ? "Primary" : context.WatchOnly ? "WatchOnly" : "Backup")}"); if (context.WatchOnly) return; - if (context.IsPrimary) + if (context.IsAPrimary) { if (isRecovering) { - ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock << (viewNumber + 1))); + ChangeTimer(TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * (neoSystem.Settings.MillisecondsPerBlock << (viewNumber + 1)))); } else { - TimeSpan span = neoSystem.Settings.TimePerBlock; + // If both Primaries already expired move to Zero or take the difference + TimeSpan span = TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * neoSystem.Settings.MillisecondsPerBlock); if (block_received_index + 1 == context.Block.Index) { var diff = TimeProvider.Current.UtcNow - block_received_time; @@ -156,11 +157,11 @@ private void OnTimer(Timer timer) { if (context.WatchOnly || context.BlockSent) return; if (timer.Height != context.Block.Index || timer.ViewNumber != context.ViewNumber) return; - if (context.IsPrimary && !context.RequestSentOrReceived) + if (context.IsAPrimary && !context.RequestSentOrReceived) { SendPrepareRequest(); } - else if ((context.IsPrimary && context.RequestSentOrReceived) || context.IsBackup) + else if ((context.IsAPrimary && context.RequestSentOrReceived) || context.IsBackup) { if (context.CommitSent) { @@ -185,7 +186,7 @@ private void OnTimer(Timer timer) private void SendPrepareRequest() { - Log($"Sending {nameof(PrepareRequest)}: height={context.Block.Index} view={context.ViewNumber}"); + Log($"Sending {nameof(PrepareRequest)}: height={context.Block.Index} view={context.ViewNumber} P1={context.IsPriorityPrimary} P2={context.IsFallbackPrimary}"); localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest() }); if (context.Validators.Length == 1) @@ -196,7 +197,13 @@ private void SendPrepareRequest() foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes)) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } - ChangeTimer(TimeSpan.FromMilliseconds((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0))); + //Multiplier for Primary P1 or FellBeck P2 + float multiplier = 1; + if (context.IsFallbackPrimary) + multiplier = 4 / 3; + // TODO Change to context.Multiplier + + ChangeTimer(TimeSpan.FromMilliseconds(multiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); } private void RequestRecovery() @@ -239,25 +246,32 @@ private void OnTransaction(Transaction transaction) if (!context.IsBackup || context.NotAcceptingPayloadsDueToViewChanging || !context.RequestSentOrReceived || context.ResponseSent || context.BlockSent) return; if (context.Transactions.ContainsKey(transaction.Hash)) return; - if (!context.TransactionHashes.Contains(transaction.Hash)) return; + if (!context.TransactionHashes[0].Contains(transaction.Hash) && !context.TransactionHashes[1].Contains(transaction.Hash)) return; AddTransaction(transaction, true); } private bool AddTransaction(Transaction tx, bool verify) { - if (verify) - { - VerifyResult result = tx.Verify(neoSystem.Settings, context.Snapshot, context.VerificationContext); - if (result != VerifyResult.Succeed) + bool returnValue = false; + for (uint i = 0; i <= 1; i++) + if (context.TransactionHashes[i].Contains(tx.Hash)) { - Log($"Rejected tx: {tx.Hash}, {result}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning); - RequestChangeView(result == VerifyResult.PolicyFail ? ChangeViewReason.TxRejectedByPolicy : ChangeViewReason.TxInvalid); - return false; + if (verify) + { + VerifyResult result = tx.Verify(neoSystem.Settings, context.Snapshot, context.VerificationContext[i]); + if (result != VerifyResult.Succeed) + { + Log($"Rejected tx: {tx.Hash}, {result}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning); + RequestChangeView(result == VerifyResult.PolicyFail ? ChangeViewReason.TxRejectedByPolicy : ChangeViewReason.TxInvalid); + return false; + } + } + + context.Transactions[i][tx.Hash] = tx; + context.VerificationContext[i].AddTransaction(tx); + returnValue = returnValue || CheckPrepareResponse(i); } - } - context.Transactions[tx.Hash] = tx; - context.VerificationContext.AddTransaction(tx); - return CheckPrepareResponse(); + return returnValue; } private void ChangeTimer(TimeSpan delay) diff --git a/src/DBFTPlugin/Messages/Commit.cs b/src/DBFTPlugin/Messages/Commit.cs index fce9b8caa..900ffdc8f 100644 --- a/src/DBFTPlugin/Messages/Commit.cs +++ b/src/DBFTPlugin/Messages/Commit.cs @@ -7,7 +7,10 @@ public class Commit : ConsensusMessage { public byte[] Signature; - public override int Size => base.Size + Signature.Length; + // priority or fallback + public uint Id; + + public override int Size => base.Size + Signature.Length + sizeof(uint); public Commit() : base(ConsensusMessageType.Commit) { } @@ -15,12 +18,14 @@ public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); Signature = reader.ReadFixedBytes(64); + Id = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(Signature); + writer.Write(Id); } } } diff --git a/src/DBFTPlugin/Messages/PreCommit.cs b/src/DBFTPlugin/Messages/PreCommit.cs new file mode 100644 index 000000000..0971f8c9c --- /dev/null +++ b/src/DBFTPlugin/Messages/PreCommit.cs @@ -0,0 +1,30 @@ +using Neo.IO; +using System.IO; + +namespace Neo.Consensus +{ + public class PreCommit : ConsensusMessage + { + public UInt256 PreparationHash; + + // priority or fallback + public uint Id; + public override int Size => base.Size + PreparationHash.Size; + + public PreCommit() : base(ConsensusMessageType.PreCommit) { } + + public override void Deserialize(BinaryReader reader) + { + base.Deserialize(reader); + PreparationHash = reader.ReadSerializable(); + Id = reader.ReadUInt32(); + } + + public override void Serialize(BinaryWriter writer) + { + base.Serialize(writer); + writer.Write(PreparationHash); + writer.Write(Id); + } + } +} diff --git a/src/DBFTPlugin/Messages/PrepareResponse.cs b/src/DBFTPlugin/Messages/PrepareResponse.cs index f52f67298..677d7a2d1 100644 --- a/src/DBFTPlugin/Messages/PrepareResponse.cs +++ b/src/DBFTPlugin/Messages/PrepareResponse.cs @@ -7,6 +7,8 @@ public class PrepareResponse : ConsensusMessage { public UInt256 PreparationHash; + // priority or fallback + public uint Id; public override int Size => base.Size + PreparationHash.Size; public PrepareResponse() : base(ConsensusMessageType.PrepareResponse) { } @@ -15,12 +17,14 @@ public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); PreparationHash = reader.ReadSerializable(); + Id = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(PreparationHash); + writer.Write(Id); } } } diff --git a/src/DBFTPlugin/Types/ConsensusMessageType.cs b/src/DBFTPlugin/Types/ConsensusMessageType.cs index a55846cf5..52b941146 100644 --- a/src/DBFTPlugin/Types/ConsensusMessageType.cs +++ b/src/DBFTPlugin/Types/ConsensusMessageType.cs @@ -7,6 +7,7 @@ public enum ConsensusMessageType : byte PrepareRequest = 0x20, PrepareResponse = 0x21, Commit = 0x30, + PreCommit = 0x31, RecoveryRequest = 0x40, RecoveryMessage = 0x41, From 0343f4a7d46f0f0aa7c79a035534d7c4acb775a4 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 13:53:42 -0300 Subject: [PATCH 02/43] Moving on --- .../Consensus/ConsensusContext.MakePayload.cs | 2 - src/DBFTPlugin/Consensus/ConsensusContext.cs | 135 +++++++++++------- 2 files changed, 83 insertions(+), 54 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index fb5d79a93..4707ff250 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -155,8 +155,6 @@ public ExtensiblePayload MakePrepareResponse(uint i) }); } - - public ExtensiblePayload MakePreCommit(uint i) { return PreCommitPayloads[MyIndex] = MakeSignedPayload(new PreCommit diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index f60a54075..86d72bdfd 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -54,10 +54,10 @@ public partial class ConsensusContext : IDisposable, ISerializable public int F => (Validators.Length - 1) / 3; public int M => Validators.Length - F; - public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); + public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); public bool IsFallbackPrimary => MyIndex == GetFallbackPrimaryIndex(ViewNumber); - public bool IsAPrimary => IsPriorityPrimary !!IsFallbackPrimary; + public bool IsAPrimary => IsPriorityPrimary!!IsFallbackPrimary; //Modify to be 1 or 4/3 public float PrimaryTimerMultiplier => 1; @@ -183,18 +183,23 @@ public void Reset(byte viewNumber) Snapshot?.Dispose(); Snapshot = neoSystem.GetSnapshot(); uint height = NativeContract.Ledger.CurrentIndex(Snapshot); - Block = new Block + for (uint i = 0; i <= 1; i++) { - Header = new Header + Block[i] = new Block { - PrevHash = NativeContract.Ledger.CurrentHash(Snapshot), - Index = height + 1, - NextConsensus = Contract.GetBFTAddress( - NeoToken.ShouldRefreshCommittee(height + 1, neoSystem.Settings.CommitteeMembersCount) ? - NativeContract.NEO.ComputeNextBlockValidators(Snapshot, neoSystem.Settings) : - NativeContract.NEO.GetNextBlockValidators(Snapshot, neoSystem.Settings.ValidatorsCount)) - } - }; + Header = new Header + { + PrevHash = NativeContract.Ledger.CurrentHash(Snapshot), + Index = height + 1, + NextConsensus = Contract.GetBFTAddress( + NeoToken.ShouldRefreshCommittee(height + 1, neoSystem.Settings.CommitteeMembersCount) ? + NativeContract.NEO.ComputeNextBlockValidators(Snapshot, neoSystem.Settings) : + NativeContract.NEO.GetNextBlockValidators(Snapshot, neoSystem.Settings.ValidatorsCount)) + } + }; + + CommitPayloads[i] = new ExtensiblePayload[Validators.Length]; + } var pv = Validators; Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot, neoSystem.Settings.ValidatorsCount); if (_witnessSize == 0 || (pv != null && pv.Length != Validators.Length)) @@ -216,7 +221,6 @@ public void Reset(byte viewNumber) MyIndex = -1; ChangeViewPayloads = new ExtensiblePayload[Validators.Length]; LastChangeViewPayloads = new ExtensiblePayload[Validators.Length]; - CommitPayloads = new ExtensiblePayload[Validators.Length]; if (ValidatorsChanged || LastSeenMessage is null) { var previous_last_seen_message = LastSeenMessage; @@ -249,14 +253,29 @@ public void Reset(byte viewNumber) LastChangeViewPayloads[i] = null; } ViewNumber = viewNumber; - Block.Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); - Block.Header.MerkleRoot = null; - Block.Header.Timestamp = 0; - Block.Header.Nonce = 0; - Block.Transactions = null; - TransactionHashes = null; - PreparationPayloads = new ExtensiblePayload[Validators.Length]; - if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block.Index; + for (uint i = 0; i <= 1; i++) + { + Block[i].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); + Block[i].Header.MerkleRoot = null; + Block[i].Header.Timestamp = 0; + Block[i].Header.Nonce = 0; + Block[i].Transactions = null; + TransactionHashes[i] = null; + PreparationPayloads[i] = new ExtensiblePayload[Validators.Length]; + if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[i].Index; + } + + // Disable Fallback if viewnumber > 1 + if (viewNumber > 0) + { + Block[1] = null; + TransactionHashes[1] = null; + Transactions[1] = null; + VerificationContext[1] = null; + PreparationPayloads[1] = null; + PreCommitPayloads[1] = null; + CommitPayloads[1] = null; + } } public void Save() @@ -267,45 +286,57 @@ public void Save() public void Deserialize(BinaryReader reader) { Reset(0); - if (reader.ReadUInt32() != Block.Version) throw new FormatException(); - if (reader.ReadUInt32() != Block.Index) throw new InvalidOperationException(); - Block.Header.Timestamp = reader.ReadUInt64(); - Block.Header.Nonce = reader.ReadUInt64(); - Block.Header.PrimaryIndex = reader.ReadByte(); - Block.Header.NextConsensus = reader.ReadSerializable(); - if (Block.NextConsensus.Equals(UInt160.Zero)) - Block.Header.NextConsensus = null; + for (uint i = 0; i <= 1; i++) + { + if (reader.ReadUInt32() != Block[i].Version) throw new FormatException(); + if (reader.ReadUInt32() != Block[i].Index) throw new InvalidOperationException(); + Block[i].Header.Timestamp = reader.ReadUInt64(); + Block[i].Header.Nonce = reader.ReadUInt64(); + Block[i].Header.PrimaryIndex = reader.ReadByte(); + Block[i].Header.NextConsensus = reader.ReadSerializable(); + if (Block[i].NextConsensus.Equals(UInt160.Zero)) + Block[i].Header.NextConsensus = null; + + TransactionHashes[i] = reader.ReadSerializableArray(ushort.MaxValue); + Transaction[] transactions = reader.ReadSerializableArray(ushort.MaxValue); + PreparationPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + PreCommitPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + CommitPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + + if (TransactionHashes[i].Length == 0 && !RequestSentOrReceived) + TransactionHashes[i] = null; + Transactions[i] = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); + VerificationContext[i] = new TransactionVerificationContext(); + if (Transactions[i] != null) + { + foreach (Transaction tx in Transactions.Values) + VerificationContext[i].AddTransaction(tx); + } + } + ViewNumber = reader.ReadByte(); - TransactionHashes = reader.ReadSerializableArray(ushort.MaxValue); - Transaction[] transactions = reader.ReadSerializableArray(ushort.MaxValue); - PreparationPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); - CommitPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); ChangeViewPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); LastChangeViewPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); - if (TransactionHashes.Length == 0 && !RequestSentOrReceived) - TransactionHashes = null; - Transactions = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); - VerificationContext = new TransactionVerificationContext(); - if (Transactions != null) - { - foreach (Transaction tx in Transactions.Values) - VerificationContext.AddTransaction(tx); - } + } public void Serialize(BinaryWriter writer) { - writer.Write(Block.Version); - writer.Write(Block.Index); - writer.Write(Block.Timestamp); - writer.Write(Block.Nonce); - writer.Write(Block.PrimaryIndex); - writer.Write(Block.NextConsensus ?? UInt160.Zero); + for (uint i = 0; i <= 1; i++) + { + writer.Write(Block[i].Version); + writer.Write(Block[i].Index); + writer.Write(Block[i].Timestamp); + writer.Write(Block[i].Nonce); + writer.Write(Block[i].PrimaryIndex); + writer.Write(Block[i].NextConsensus ?? UInt160.Zero); + writer.Write(TransactionHashes[i] ?? Array.Empty()); + writer.Write(Transactions[i]?.Values.ToArray() ?? Array.Empty()); + writer.WriteNullableArray(PreparationPayloads[i]); + writer.WriteNullableArray(PreCommitPayloads[i]); + writer.WriteNullableArray(CommitPayloads[i]); + } writer.Write(ViewNumber); - writer.Write(TransactionHashes ?? Array.Empty()); - writer.Write(Transactions?.Values.ToArray() ?? Array.Empty()); - writer.WriteNullableArray(PreparationPayloads); - writer.WriteNullableArray(CommitPayloads); writer.WriteNullableArray(ChangeViewPayloads); writer.WriteNullableArray(LastChangeViewPayloads); } From c432ffcacb7144977c510be61aae9d62303aeb44 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 14:11:01 -0300 Subject: [PATCH 03/43] Moving on --- .../Consensus/ConsensusContext.MakePayload.cs | 2 +- src/DBFTPlugin/Consensus/ConsensusContext.cs | 10 ++--- .../Consensus/ConsensusService.Check.cs | 4 +- .../Consensus/ConsensusService.OnMessage.cs | 37 ++++++++++++++----- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 4707ff250..2c34a072e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -25,7 +25,7 @@ public ExtensiblePayload MakeCommit(uint i) { return CommitPayloads[i][MyIndex] ?? (CommitPayloads[i][MyIndex] = MakeSignedPayload(new Commit { - Signature = EnsureHeader().Sign(keyPair, neoSystem.Settings.Network), + Signature = EnsureHeader(i).Sign(keyPair, neoSystem.Settings.Network), Id = i })); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 86d72bdfd..cda870674 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -110,9 +110,9 @@ public ConsensusContext(NeoSystem neoSystem, Settings settings, Wallet wallet) this.store = neoSystem.LoadStore(settings.RecoveryLogs); } - public Block CreateBlock() + public Block CreateBlock(uint i) { - EnsureHeader(); + EnsureHeader(i); Contract contract = Contract.CreateMultiSigContract(M, Validators); ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block.Header, dbftSettings.Network); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) @@ -150,10 +150,10 @@ public void Dispose() Snapshot?.Dispose(); } - public Block EnsureHeader() + public Block EnsureHeader(uint i) { - if (TransactionHashes == null) return null; - Block.Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes); + if (TransactionHashes[i] == null) return null; + Block[i].Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes); return Block; } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index a0098570e..5780abdf7 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -63,8 +63,8 @@ private void CheckCommits(uint i) { block_received_index = context.Block.Index; block_received_time = TimeProvider.Current.UtcNow; - Block block = context.CreateBlock(); - Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} to pOrF={i}"); + Block block = context.CreateBlock(i); + Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} Id={i}"); blockchain.Tell(block); return; } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index e2357f872..560b5fea7 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -55,6 +55,9 @@ private void OnConsensusPayload(ExtensiblePayload payload) case ChangeView view: OnChangeViewReceived(payload, view); break; + case PreCommit precommit: + OnPreCommitReceived(payload, precommit); + break; case Commit commit: OnCommitReceived(payload, commit); break; @@ -105,7 +108,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest if (!context.GetMessage(context.PreparationPayloads[pOrF][i]).PreparationHash.Equals(payload.Hash)) context.PreparationPayloads[pOrF][i] = null; context.PreparationPayloads[pOrF][message.ValidatorIndex] = payload; - byte[] hashData = context.EnsureHeader().GetSignData(neoSystem.Settings.Network); + byte[] hashData = context.EnsureHeader(pOrF).GetSignData(neoSystem.Settings.Network); for (int i = 0; i < context.CommitPayloads[pOrF].Length; i++) if (context.GetMessage(context.CommitPayloads[pOrF][i])?.ViewNumber == context.ViewNumber) if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pOrF][i]).Signature, context.Validators[i])) @@ -150,19 +153,33 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareResponse message) { if (message.ViewNumber != context.ViewNumber) return; - if (context.PreparationPayloads[message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; - if (context.PreparationPayloads[context.Block.PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[context.Block.PrimaryIndex].Hash)) + if (context.PreparationPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; + if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) return; // Timeout extension: prepare response has been received with success // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); - Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex}"); - context.PreparationPayloads[message.ValidatorIndex] = payload; + Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); + context.PreparationPayloads[message.Id][message.ValidatorIndex] = payload; if (context.WatchOnly || context.CommitSent) return; if (context.RequestSentOrReceived) - CheckPreparations(); + CheckPreparations(message.Id); + } + + private void OnPreCommitReceived(ExtensiblePayload payload, PreCommit message) + { + if (message.ViewNumber != context.ViewNumber) return; + if (context.PreparationPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; + if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + return; + + Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); + context.PreCommitPayloads[message.Id][message.ValidatorIndex] = payload; + if (context.WatchOnly || context.CommitSent) return; + if (context.RequestSentOrReceived) + CheckPreCommits(message.Id); } private void OnChangeViewReceived(ExtensiblePayload payload, ChangeView message) @@ -183,11 +200,11 @@ private void OnChangeViewReceived(ExtensiblePayload payload, ChangeView message) private void OnCommitReceived(ExtensiblePayload payload, Commit commit) { - ref ExtensiblePayload existingCommitPayload = ref context.CommitPayloads[commit.ValidatorIndex]; + ref ExtensiblePayload existingCommitPayload = ref context.CommitPayloads[commit.Id][commit.ValidatorIndex]; if (existingCommitPayload != null) { if (existingCommitPayload.Hash != payload.Hash) - Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber}", LogLevel.Warning); + Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber} id={commit.Id}", LogLevel.Warning); return; } @@ -199,7 +216,7 @@ private void OnCommitReceived(ExtensiblePayload payload, Commit commit) { Log($"{nameof(OnCommitReceived)}: height={commit.BlockIndex} view={commit.ViewNumber} index={commit.ValidatorIndex} nc={context.CountCommitted} nf={context.CountFailed}"); - byte[] hashData = context.EnsureHeader()?.GetSignData(neoSystem.Settings.Network); + byte[] hashData = context.EnsureHeader(commit.Id)?.GetSignData(neoSystem.Settings.Network); if (hashData == null) { existingCommitPayload = payload; @@ -207,7 +224,7 @@ private void OnCommitReceived(ExtensiblePayload payload, Commit commit) else if (Crypto.VerifySignature(hashData, commit.Signature, context.Validators[commit.ValidatorIndex])) { existingCommitPayload = payload; - CheckCommits(); + CheckCommits(commit.Id); } return; } From 970e4824718c162beab34c06a905f87a4ca515ef Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 14:13:32 -0300 Subject: [PATCH 04/43] format --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 560b5fea7..9742bbf41 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -57,7 +57,7 @@ private void OnConsensusPayload(ExtensiblePayload payload) break; case PreCommit precommit: OnPreCommitReceived(payload, precommit); - break; + break; case Commit commit: OnCommitReceived(payload, commit); break; From 01d033c939b2a883c1bf3d86fd2e2f3063b03ad7 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 14:23:08 -0300 Subject: [PATCH 05/43] moving on --- src/DBFTPlugin/Consensus/ConsensusService.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index b7a2a67ae..cb90ce121 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -69,8 +69,9 @@ private void InitializeConsensus(byte viewNumber) { context.Reset(viewNumber); if (viewNumber > 0) - Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); - Log($"Initialize: height={context.Block.Index} view={viewNumber} index={context.MyIndex} role={(context.IsPrimary ? "Primary" : context.WatchOnly ? "WatchOnly" : "Backup")}"); + Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPriorityPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); + uint blockCurrentIndex = context.Block[0].Index; + Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? "PrimaryP1" : context.IsFallbackPrimary ? "PrimaryP2" : context.WatchOnly ? "WatchOnly" : "Backup")}"); if (context.WatchOnly) return; if (context.IsAPrimary) { @@ -82,7 +83,7 @@ private void InitializeConsensus(byte viewNumber) { // If both Primaries already expired move to Zero or take the difference TimeSpan span = TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * neoSystem.Settings.MillisecondsPerBlock); - if (block_received_index + 1 == context.Block.Index) + if (block_received_index + 1 == blockCurrentIndex) { var diff = TimeProvider.Current.UtcNow - block_received_time; if (diff >= span) @@ -134,16 +135,18 @@ private void OnStart() started = true; if (!dbftSettings.IgnoreRecoveryLogs && context.Load()) { - if (context.Transactions != null) + // For Now, only checking Transactions for Priority + // Fallback works only for viewnumber 0 and this will not really make a difference + if (context.Transactions[0] != null) { blockchain.Ask(new Blockchain.FillMemoryPool { - Transactions = context.Transactions.Values + Transactions = context.Transactions[0].Values }).Wait(); } if (context.CommitSent) { - CheckPreparations(); + CheckPreparations(0); return; } } From 02fa0b7039c5063c69dc2f33dddb4cf351672764 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 14:35:48 -0300 Subject: [PATCH 06/43] format --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 4 ++-- src/DBFTPlugin/Consensus/ConsensusService.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index cda870674..1c9f48695 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -57,9 +57,9 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); public bool IsFallbackPrimary => MyIndex == GetFallbackPrimaryIndex(ViewNumber); - public bool IsAPrimary => IsPriorityPrimary!!IsFallbackPrimary; + public bool IsAPrimary => IsPriorityPrimary || IsFallbackPrimary; -//Modify to be 1 or 4/3 + //Modify to be 1 or 4/3 public float PrimaryTimerMultiplier => 1; public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index cb90ce121..57d7af5bf 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -70,8 +70,8 @@ private void InitializeConsensus(byte viewNumber) context.Reset(viewNumber); if (viewNumber > 0) Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPriorityPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); - uint blockCurrentIndex = context.Block[0].Index; - Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? "PrimaryP1" : context.IsFallbackPrimary ? "PrimaryP2" : context.WatchOnly ? "WatchOnly" : "Backup")}"); + uint blockCurrentIndex = context.Block[0].Index; + Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? "PrimaryP1" : context.IsFallbackPrimary ? "PrimaryP2" : context.WatchOnly ? "WatchOnly" : "Backup")}"); if (context.WatchOnly) return; if (context.IsAPrimary) { From 5523a31c2c18950ad8c9f431ed6478e9cda1528c Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 15:01:14 -0300 Subject: [PATCH 07/43] Adding new --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 14 +++++++------- .../Consensus/ConsensusService.OnMessage.cs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 1c9f48695..ae5006b72 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -22,15 +22,15 @@ public partial class ConsensusContext : IDisposable, ISerializable /// private static readonly byte[] ConsensusStateKey = { 0xf4 }; - public Block[] Block; + public Block[] Block = new Block[2]; public byte ViewNumber; public ECPoint[] Validators; public int MyIndex; - public UInt256[][] TransactionHashes; - public Dictionary[] Transactions; - public ExtensiblePayload[][] PreparationPayloads; - public ExtensiblePayload[][] PreCommitPayloads; - public ExtensiblePayload[][] CommitPayloads; + public UInt256[][] TransactionHashes = new UInt256[2][]; + public Dictionary[] Transactions = new Dictionary[2]; + public ExtensiblePayload[][] PreparationPayloads = new ExtensiblePayload[2][]; + public ExtensiblePayload[][] PreCommitPayloads = new ExtensiblePayload[2][]; + public ExtensiblePayload[][] CommitPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[] ChangeViewPayloads; public ExtensiblePayload[] LastChangeViewPayloads; // LastSeenMessage array stores the height of the last seen message, for each validator. @@ -40,7 +40,7 @@ public partial class ConsensusContext : IDisposable, ISerializable /// /// Store all verified unsorted transactions' senders' fee currently in the consensus context. /// - public TransactionVerificationContext[] VerificationContext = new(); + public TransactionVerificationContext[] VerificationContext = new TransactionVerificationContext[2]; public SnapshotCache Snapshot { get; private set; } private KeyPair keyPair; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 9742bbf41..ec801ef06 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -101,8 +101,8 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest context.Block[pOrF].Header.Nonce = message.Nonce; context.TransactionHashes[pOrF] = message.TransactionHashes; - context.Transactions = new Dictionary(); - context.VerificationContext = new TransactionVerificationContext(); + context.Transactions[pOrF] = new Dictionary(); + context.VerificationContext[pOrF] = new TransactionVerificationContext(); for (int i = 0; i < context.PreparationPayloads[pOrF].Length; i++) if (context.PreparationPayloads[pOrF][i] != null) if (!context.GetMessage(context.PreparationPayloads[pOrF][i]).PreparationHash.Equals(payload.Hash)) From bbb33ae0889cf9135d8a6e684902504c2521d83b Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 15:03:54 -0300 Subject: [PATCH 08/43] More fix --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index ae5006b72..aaa332440 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -110,19 +110,19 @@ public ConsensusContext(NeoSystem neoSystem, Settings settings, Wallet wallet) this.store = neoSystem.LoadStore(settings.RecoveryLogs); } - public Block CreateBlock(uint i) + public Block CreateBlock(uint pOrF) { - EnsureHeader(i); + EnsureHeader(pOrF); Contract contract = Contract.CreateMultiSigContract(M, Validators); - ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block.Header, dbftSettings.Network); + ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block[pOrF].Header, dbftSettings.Network); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { - if (GetMessage(CommitPayloads[i])?.ViewNumber != ViewNumber) continue; - sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[i]).Signature); + if (GetMessage(CommitPayloads[pOrF][i])?.ViewNumber != ViewNumber) continue; + sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[pOrF][i]).Signature); j++; } - Block.Header.Witness = sc.GetWitnesses()[0]; - Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); + Block[pOrF].Header.Witness = sc.GetWitnesses()[0]; + Block[pOrF].Transactions = TransactionHashes[pOrF].Select(p => Transactions[pOrF][p]).ToArray(); return Block; } From ab8eec25de9dc9fa5a2ff477595eabaddb98c222 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 15:06:52 -0300 Subject: [PATCH 09/43] Additional fix --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index ec801ef06..1956df996 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -33,11 +33,11 @@ private void OnConsensusPayload(ExtensiblePayload payload) return; } if (!message.Verify(neoSystem.Settings)) return; - if (message.BlockIndex != context.Block.Index) + if (message.BlockIndex != context.Block[0].Index) { if (context.Block.Index < message.BlockIndex) { - Log($"Chain is behind: expected={message.BlockIndex} current={context.Block.Index - 1}", LogLevel.Warning); + Log($"Chain is behind: expected={message.BlockIndex} current={context.Block[0].Index - 1}", LogLevel.Warning); } return; } From cad55623b2146d44dc693cc168602921d9142fde Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 15:37:50 -0300 Subject: [PATCH 10/43] General fixes --- .../Consensus/ConsensusContext.Get.cs | 14 ++++---- .../Consensus/ConsensusContext.MakePayload.cs | 24 ++++++------- src/DBFTPlugin/Consensus/ConsensusContext.cs | 34 +++++++++---------- .../Consensus/ConsensusService.Check.cs | 18 +++++----- .../Consensus/ConsensusService.OnMessage.cs | 24 +++++++------ src/DBFTPlugin/Consensus/ConsensusService.cs | 27 ++++++++------- .../RecoveryMessage/RecoveryMessage.cs | 6 ++-- 7 files changed, 75 insertions(+), 72 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 2e3b02940..77d7a1135 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -58,14 +58,14 @@ private PreparationPayloadCompact GetPreparationPayloadCompact(ExtensiblePayload [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte GetPriorityPrimaryIndex(byte viewNumber) { - int p = ((int)Block.Index - viewNumber) % Validators.Length; + int p = ((int)Block[0].Index - viewNumber) % Validators.Length; return p >= 0 ? (byte)p : (byte)(p + Validators.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public byte GetFallbackPrimaryIndex(byte viewNumber) { - int p = ((int)Block.Index - viewNumber + 1) % Validators.Length; + int p = ((int)Block[0].Index - viewNumber + 1) % Validators.Length; return p >= 0 ? (byte)p : (byte)(p + Validators.Length); } @@ -77,18 +77,18 @@ public UInt160 GetSender(int index) /// /// Return the expected block size /// - public int GetExpectedBlockSize() + public int GetExpectedBlockSize(uint i) { - return GetExpectedBlockSizeWithoutTransactions(Transactions.Count) + // Base size - Transactions.Values.Sum(u => u.Size); // Sum Txs + return GetExpectedBlockSizeWithoutTransactions(Transactions[i].Count) + // Base size + Transactions[i].Values.Sum(u => u.Size); // Sum Txs } /// /// Return the expected block system fee /// - public long GetExpectedBlockSystemFee() + public long GetExpectedBlockSystemFee(uint i) { - return Transactions.Values.Sum(u => u.SystemFee); // Sum Txs + return Transactions[i].Values.Sum(u => u.SystemFee); // Sum Txs } /// diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 2c34a072e..51a557bb5 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -32,7 +32,7 @@ public ExtensiblePayload MakeCommit(uint i) private ExtensiblePayload MakeSignedPayload(ConsensusMessage message) { - message.BlockIndex = Block.Index; + message.BlockIndex = Block[0].Index; message.ValidatorIndex = (byte)MyIndex; message.ViewNumber = ViewNumber; ExtensiblePayload payload = CreatePayload(message, null); @@ -124,13 +124,13 @@ public ExtensiblePayload MakeRecoveryMessage() { prepareRequestMessage = new PrepareRequest { - Version = Block.Version, - PrevHash = Block.PrevHash, + Version = Block[0].Version, + PrevHash = Block[0].PrevHash, ViewNumber = ViewNumber, - Timestamp = Block.Timestamp, - Nonce = Block.Nonce, - BlockIndex = Block.Index, - TransactionHashes = TransactionHashes + Timestamp = Block[0].Timestamp, + Nonce = Block[0].Nonce, + BlockIndex = Block[0].Index, + TransactionHashes = TransactionHashes[0] }; } return MakeSignedPayload(new RecoveryMessage @@ -138,10 +138,10 @@ public ExtensiblePayload MakeRecoveryMessage() ChangeViewMessages = LastChangeViewPayloads.Where(p => p != null).Select(p => GetChangeViewPayloadCompact(p)).Take(M).ToDictionary(p => p.ValidatorIndex), PrepareRequestMessage = prepareRequestMessage, // We only need a PreparationHash set if we don't have the PrepareRequest information. - PreparationHash = TransactionHashes == null ? PreparationPayloads.Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, - PreparationMessages = PreparationPayloads.Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), + PreparationHash = TransactionHashes[0] == null ? PreparationPayloads[0].Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, + PreparationMessages = PreparationPayloads[0].Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), CommitMessages = CommitSent - ? CommitPayloads.Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) + ? CommitPayloads[0].Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) : new Dictionary() }); } @@ -157,9 +157,9 @@ public ExtensiblePayload MakePrepareResponse(uint i) public ExtensiblePayload MakePreCommit(uint i) { - return PreCommitPayloads[MyIndex] = MakeSignedPayload(new PreCommit + return PreCommitPayloads[i][MyIndex] = MakeSignedPayload(new PreCommit { - PreparationHash = PreparationPayloads[Block[i].PrimaryIndex].Hash, + PreparationHash = PreCommitPayloads[i][Block[i].PrimaryIndex].Hash, Id = i }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index aaa332440..947c9ef4b 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -63,14 +63,14 @@ public partial class ConsensusContext : IDisposable, ISerializable public float PrimaryTimerMultiplier => 1; public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; - public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block.PrevHash); + public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); public int CountCommitted => CommitPayloads.Count(p => p != null); public int CountFailed { get { if (LastSeenMessage == null) return 0; - return Validators.Count(p => !LastSeenMessage.TryGetValue(p, out var value) || value < (Block.Index - 1)); + return Validators.Count(p => !LastSeenMessage.TryGetValue(p, out var value) || value < (Block[0].Index - 1)); } } public bool ValidatorsChanged @@ -86,10 +86,10 @@ public bool ValidatorsChanged } #region Consensus States - public bool RequestSentOrReceived => PreparationPayloads[Block.PrimaryIndex] != null; - public bool ResponseSent => !WatchOnly && PreparationPayloads[MyIndex] != null; - public bool CommitSent => !WatchOnly && CommitPayloads[MyIndex] != null; - public bool BlockSent => Block.Transactions != null; + public bool RequestSentOrReceived => (PreparationPayloads[0][Block[0].PrimaryIndex] != null || PreparationPayloads[1][Block[0].PrimaryIndex] != null); + public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || PreparationPayloads[1][MyIndex] != null); + public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || CommitPayloads[1][MyIndex] != null); + public bool BlockSent => (Block[0].Transactions != null || Block[1].Transactions != null); public bool ViewChanging => !WatchOnly && GetMessage(ChangeViewPayloads[MyIndex])?.NewViewNumber > ViewNumber; public bool NotAcceptingPayloadsDueToViewChanging => ViewChanging && !MoreThanFNodesCommittedOrLost; // A possible attack can happen if the last node to commit is malicious and either sends change view after his @@ -110,20 +110,20 @@ public ConsensusContext(NeoSystem neoSystem, Settings settings, Wallet wallet) this.store = neoSystem.LoadStore(settings.RecoveryLogs); } - public Block CreateBlock(uint pOrF) + public Block CreateBlock(uint ii) { - EnsureHeader(pOrF); + EnsureHeader(ii); Contract contract = Contract.CreateMultiSigContract(M, Validators); - ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block[pOrF].Header, dbftSettings.Network); + ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block[ii].Header, dbftSettings.Network); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { - if (GetMessage(CommitPayloads[pOrF][i])?.ViewNumber != ViewNumber) continue; - sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[pOrF][i]).Signature); + if (GetMessage(CommitPayloads[ii][i])?.ViewNumber != ViewNumber) continue; + sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[ii][i]).Signature); j++; } - Block[pOrF].Header.Witness = sc.GetWitnesses()[0]; - Block[pOrF].Transactions = TransactionHashes[pOrF].Select(p => Transactions[pOrF][p]).ToArray(); - return Block; + Block[ii].Header.Witness = sc.GetWitnesses()[0]; + Block[ii].Transactions = TransactionHashes[ii].Select(p => Transactions[ii][p]).ToArray(); + return Block[ii]; } public ExtensiblePayload CreatePayload(ConsensusMessage message, byte[] invocationScript = null) @@ -153,8 +153,8 @@ public void Dispose() public Block EnsureHeader(uint i) { if (TransactionHashes[i] == null) return null; - Block[i].Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes); - return Block; + Block[i].Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes[i]); + return Block[i]; } public bool Load() @@ -309,7 +309,7 @@ public void Deserialize(BinaryReader reader) VerificationContext[i] = new TransactionVerificationContext(); if (Transactions[i] != null) { - foreach (Transaction tx in Transactions.Values) + foreach (Transaction tx in Transactions[i].Values) VerificationContext[i].AddTransaction(tx); } } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index 5780abdf7..db0e0b23c 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -11,23 +11,23 @@ partial class ConsensusService { private bool CheckPrepareResponse(uint i) { - if (context.TransactionHashes[i].Length == context.Transactions.Count) + if (context.TransactionHashes[i].Length == context.Transactions[i].Count) { // if we are the primary for this view, but acting as a backup because we recovered our own // previously sent prepare request, then we don't want to send a prepare response. if (context.IsAPrimary || context.WatchOnly) return true; // Check maximum block size via Native Contract policy - if (context.GetExpectedBlockSize() > dbftSettings.MaxBlockSize) + if (context.GetExpectedBlockSize(i) > dbftSettings.MaxBlockSize) { - Log($"Rejected block: {context.Block.Index} The size exceed the policy", LogLevel.Warning); + Log($"Rejected block: {context.Block[i].Index} The size exceed the policy", LogLevel.Warning); RequestChangeView(ChangeViewReason.BlockRejectedByPolicy); return false; } // Check maximum block system fee via Native Contract policy - if (context.GetExpectedBlockSystemFee() > dbftSettings.MaxBlockSystemFee) + if (context.GetExpectedBlockSystemFee(i) > dbftSettings.MaxBlockSystemFee) { - Log($"Rejected block: {context.Block.Index} The system fee exceed the policy", LogLevel.Warning); + Log($"Rejected block: {context.Block[i].Index} The system fee exceed the policy", LogLevel.Warning); RequestChangeView(ChangeViewReason.BlockRejectedByPolicy); return false; } @@ -45,7 +45,7 @@ private bool CheckPrepareResponse(uint i) private void CheckPreCommits(uint i, bool forced = false) { - if (forced || context.PreCommitPayloads[i].Count(p => p != null) >= context.M && context.TransactionHashes[i].All(p => context.Transactions.ContainsKey(p))) + if (forced || context.PreCommitPayloads[i].Count(p => p != null) >= context.M && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) { ExtensiblePayload payload = context.MakeCommit(i); Log($"Sending {nameof(Commit)} to pOrF={i}"); @@ -59,9 +59,9 @@ private void CheckPreCommits(uint i, bool forced = false) private void CheckCommits(uint i) { - if (context.CommitPayloads[i].Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) + if (context.CommitPayloads[i].Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) { - block_received_index = context.Block.Index; + block_received_index = context.Block[i].Index; block_received_time = TimeProvider.Current.UtcNow; Block block = context.CreateBlock(i); Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} Id={i}"); @@ -95,7 +95,7 @@ private void CheckPreparations(uint i) if (i == 1) thresholdForPrep = context.M; - if (context.PreparationPayloads[i].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes.All(p => context.Transactions.ContainsKey(p))) + if (context.PreparationPayloads[i].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) { ExtensiblePayload payload = context.MakePreCommit(i); Log($"Sending {nameof(PreCommit)} pOrF={i}"); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 1956df996..ab06cca4d 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -35,7 +35,7 @@ private void OnConsensusPayload(ExtensiblePayload payload) if (!message.Verify(neoSystem.Settings)) return; if (message.BlockIndex != context.Block[0].Index) { - if (context.Block.Index < message.BlockIndex) + if (context.Block[0].Index < message.BlockIndex) { Log($"Chain is behind: expected={message.BlockIndex} current={context.Block[0].Index - 1}", LogLevel.Warning); } @@ -73,13 +73,12 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; + uint pOrF = Convert.ToUInt32(message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)); // Add verification for Fallback - if (message.ValidatorIndex != context.Block.PrimaryIndex || message.ViewNumber != context.ViewNumber) return; - if (message.Version != context.Block.Version || message.PrevHash != context.Block.PrevHash) return; + if (message.ValidatorIndex != context.Block[pOrF].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; + if (message.Version != context.Block[pOrF].Version || message.PrevHash != context.Block[pOrF].PrevHash) return; if (message.TransactionHashes.Length > neoSystem.Settings.MaxTransactionsPerBlock) return; - uint pOrF = Convert.ToUInt32(message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)); - - + Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)} fallback={message.ValidatorIndex == context.GetFallbackPrimaryIndex(context.ViewNumber)}"); if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMilliseconds(8 * neoSystem.Settings.MillisecondsPerBlock).ToTimestampMS()) { @@ -87,7 +86,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest return; } - if (message.TransactionHashes[pOrF].Any(p => NativeContract.Ledger.ContainsTransaction(context.Snapshot, p))) + if (message.TransactionHashes.Any(p => NativeContract.Ledger.ContainsTransaction(context.Snapshot, p))) { Log($"Invalid request: transaction already exists", LogLevel.Warning); return; @@ -140,9 +139,9 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest foreach (Transaction tx in unverified) if (!AddTransaction(tx, true)) return; - if (context.Transactions.Count < context.TransactionHashes[pOrF].Length) + if (context.Transactions[pOrF].Count < context.TransactionHashes[pOrF].Length) { - UInt256[] hashes = context.TransactionHashes[pOrF].Where(i => !context.Transactions.ContainsKey(i)).ToArray(); + UInt256[] hashes = context.TransactionHashes[pOrF].Where(i => !context.Transactions[pOrF].ContainsKey(i)).ToArray(); taskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) @@ -263,8 +262,11 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) totalPrepReq = 1; if (ReverifyAndProcessPayload(prepareRequestPayload)) validPrepReq++; } - else if (context.IsPrimary) - SendPrepareRequest(); + else if (context.IsPriorityPrimary || (context.IsFallbackPrimary && message.ViewNumber == 0)) + { + uint pOrF = Convert.ToUInt32(context.IsPriorityPrimary); + SendPrepareRequest(pOrF); + } } ExtensiblePayload[] prepareResponsePayloads = message.GetPrepareResponsePayloads(context); totalPrepResponses = prepareResponsePayloads.Length; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 57d7af5bf..8dd50e328 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -158,11 +158,12 @@ private void OnStart() private void OnTimer(Timer timer) { + uint pOrF = Convert.ToUInt32(context.IsPriorityPrimary); if (context.WatchOnly || context.BlockSent) return; - if (timer.Height != context.Block.Index || timer.ViewNumber != context.ViewNumber) return; + if (timer.Height != context.Block[pOrF].Index || timer.ViewNumber != context.ViewNumber) return; if (context.IsAPrimary && !context.RequestSentOrReceived) { - SendPrepareRequest(); + SendPrepareRequest(pOrF); } else if ((context.IsAPrimary && context.RequestSentOrReceived) || context.IsBackup) { @@ -177,7 +178,7 @@ private void OnTimer(Timer timer) { var reason = ChangeViewReason.Timeout; - if (context.Block != null && context.TransactionHashes?.Length > context.Transactions?.Count) + if (context.Block[pOrF] != null && context.TransactionHashes[pOrF]?.Length > context.Transactions[pOrF]?.Count) { reason = ChangeViewReason.TxNotFound; } @@ -187,17 +188,17 @@ private void OnTimer(Timer timer) } } - private void SendPrepareRequest() + private void SendPrepareRequest(uint i) { - Log($"Sending {nameof(PrepareRequest)}: height={context.Block.Index} view={context.ViewNumber} P1={context.IsPriorityPrimary} P2={context.IsFallbackPrimary}"); - localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest() }); + Log($"Sending {nameof(PrepareRequest)}: height={context.Block[i].Index} view={context.ViewNumber} Id={i}"); + localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest(i) }); if (context.Validators.Length == 1) - CheckPreparations(); + CheckPreparations(i); - if (context.TransactionHashes.Length > 0) + if (context.TransactionHashes[i].Length > 0) { - foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes)) + foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[i])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } //Multiplier for Primary P1 or FellBeck P2 @@ -211,7 +212,7 @@ private void SendPrepareRequest() private void RequestRecovery() { - Log($"Sending {nameof(RecoveryRequest)}: height={context.Block.Index} view={context.ViewNumber} nc={context.CountCommitted} nf={context.CountFailed}"); + Log($"Sending {nameof(RecoveryRequest)}: height={context.Block[0].Index} view={context.ViewNumber} nc={context.CountCommitted} nf={context.CountFailed}"); localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeRecoveryRequest() }); } @@ -230,7 +231,7 @@ private void RequestChangeView(ChangeViewReason reason) } else { - Log($"Sending {nameof(ChangeView)}: height={context.Block.Index} view={context.ViewNumber} nv={expectedView} nc={context.CountCommitted} nf={context.CountFailed} reason={reason}"); + Log($"Sending {nameof(ChangeView)}: height={context.Block[0].Index} view={context.ViewNumber} nv={expectedView} nc={context.CountCommitted} nf={context.CountFailed} reason={reason}"); localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView(reason) }); CheckExpectedView(expectedView); } @@ -248,7 +249,7 @@ private void OnTransaction(Transaction transaction) { if (!context.IsBackup || context.NotAcceptingPayloadsDueToViewChanging || !context.RequestSentOrReceived || context.ResponseSent || context.BlockSent) return; - if (context.Transactions.ContainsKey(transaction.Hash)) return; + if (context.Transactions[0].ContainsKey(transaction.Hash) || context.Transactions[1].ContainsKey(transaction.Hash)) return; if (!context.TransactionHashes[0].Contains(transaction.Hash) && !context.TransactionHashes[1].Contains(transaction.Hash)) return; AddTransaction(transaction, true); } @@ -284,7 +285,7 @@ private void ChangeTimer(TimeSpan delay) timer_token.CancelIfNotNull(); timer_token = Context.System.Scheduler.ScheduleTellOnceCancelable(delay, Self, new Timer { - Height = context.Block.Index, + Height = context.Block[0].Index, ViewNumber = context.ViewNumber }, ActorRefs.NoSender); } diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index 046fae5e3..e7906a8d1 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -79,16 +79,16 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte internal ExtensiblePayload GetPrepareRequestPayload(ConsensusContext context) { if (PrepareRequestMessage == null) return null; - if (!PreparationMessages.TryGetValue(context.Block.PrimaryIndex, out PreparationPayloadCompact compact)) + if (!PreparationMessages.TryGetValue(context.Block[0].PrimaryIndex, out PreparationPayloadCompact compact)) return null; return context.CreatePayload(PrepareRequestMessage, compact.InvocationScript); } internal ExtensiblePayload[] GetPrepareResponsePayloads(ConsensusContext context) { - UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[context.Block.PrimaryIndex]?.Hash; + UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[0][context.Block[0].PrimaryIndex]?.Hash; if (preparationHash is null) return Array.Empty(); - return PreparationMessages.Values.Where(p => p.ValidatorIndex != context.Block.PrimaryIndex).Select(p => context.CreatePayload(new PrepareResponse + return PreparationMessages.Values.Where(p => p.ValidatorIndex != context.Block[0].PrimaryIndex).Select(p => context.CreatePayload(new PrepareResponse { BlockIndex = BlockIndex, ValidatorIndex = p.ValidatorIndex, From 43166ec8c6237169d2a75be9aab03d33d33237f5 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 15:43:03 -0300 Subject: [PATCH 11/43] format --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index ab06cca4d..1a7e84f58 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -78,7 +78,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest if (message.ValidatorIndex != context.Block[pOrF].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; if (message.Version != context.Block[pOrF].Version || message.PrevHash != context.Block[pOrF].PrevHash) return; if (message.TransactionHashes.Length > neoSystem.Settings.MaxTransactionsPerBlock) return; - + Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)} fallback={message.ValidatorIndex == context.GetFallbackPrimaryIndex(context.ViewNumber)}"); if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMilliseconds(8 * neoSystem.Settings.MillisecondsPerBlock).ToTimestampMS()) { From 94e42b401f71b24e51cfb9afa21002c4ea15ca80 Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 17:15:41 -0300 Subject: [PATCH 12/43] Minor fix --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 947c9ef4b..2cb24059e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -27,7 +27,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public ECPoint[] Validators; public int MyIndex; public UInt256[][] TransactionHashes = new UInt256[2][]; - public Dictionary[] Transactions = new Dictionary[2]; + public Dictionary[] Transactions = new ExtensiblePayload[2][]; public ExtensiblePayload[][] PreparationPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] PreCommitPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] CommitPayloads = new ExtensiblePayload[2][]; @@ -197,8 +197,6 @@ public void Reset(byte viewNumber) NativeContract.NEO.GetNextBlockValidators(Snapshot, neoSystem.Settings.ValidatorsCount)) } }; - - CommitPayloads[i] = new ExtensiblePayload[Validators.Length]; } var pv = Validators; Validators = NativeContract.NEO.GetNextBlockValidators(Snapshot, neoSystem.Settings.ValidatorsCount); @@ -219,6 +217,8 @@ public void Reset(byte viewNumber) } } MyIndex = -1; + for (uint i = 0; i <= 1; i++) + CommitPayloads[i] = new ExtensiblePayload[Validators.Length]; ChangeViewPayloads = new ExtensiblePayload[Validators.Length]; LastChangeViewPayloads = new ExtensiblePayload[Validators.Length]; if (ValidatorsChanged || LastSeenMessage is null) @@ -252,6 +252,7 @@ public void Reset(byte viewNumber) else LastChangeViewPayloads[i] = null; } + ViewNumber = viewNumber; for (uint i = 0; i <= 1; i++) { @@ -340,5 +341,10 @@ public void Serialize(BinaryWriter writer) writer.WriteNullableArray(ChangeViewPayloads); writer.WriteNullableArray(LastChangeViewPayloads); } + + private static void Log(string message, LogLevel level = LogLevel.Info) + { + Utility.Log(nameof(ConsensusService), level, message); + } } } From 6d5939c126b481331d663bf9c587bd04ae84a47f Mon Sep 17 00:00:00 2001 From: Vitor Date: Fri, 17 Dec 2021 17:16:27 -0300 Subject: [PATCH 13/43] Minor fix fixed --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 2cb24059e..7c269b7de 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -27,7 +27,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public ECPoint[] Validators; public int MyIndex; public UInt256[][] TransactionHashes = new UInt256[2][]; - public Dictionary[] Transactions = new ExtensiblePayload[2][]; + public Dictionary[] Transactions = new Dictionary[2];; public ExtensiblePayload[][] PreparationPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] PreCommitPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] CommitPayloads = new ExtensiblePayload[2][]; From 4489d37ea679db1fa0dd6fd432075fe927ebc123 Mon Sep 17 00:00:00 2001 From: Vitor Date: Mon, 17 Jan 2022 14:14:14 -0300 Subject: [PATCH 14/43] Fixing conditions and other fixed variables --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 6 ++++-- .../Consensus/ConsensusService.OnMessage.cs | 4 ++-- src/DBFTPlugin/Consensus/ConsensusService.cs | 19 ++++++++----------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 7c269b7de..b20cb6b07 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -27,7 +27,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public ECPoint[] Validators; public int MyIndex; public UInt256[][] TransactionHashes = new UInt256[2][]; - public Dictionary[] Transactions = new Dictionary[2];; + public Dictionary[] Transactions = new Dictionary[2]; public ExtensiblePayload[][] PreparationPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] PreCommitPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[][] CommitPayloads = new ExtensiblePayload[2][]; @@ -60,7 +60,9 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsAPrimary => IsPriorityPrimary || IsFallbackPrimary; //Modify to be 1 or 4/3 - public float PrimaryTimerMultiplier => 1; + public float PrimaryTimerPriorityMultiplier => 1; + public float PrimaryTimerFallBackMultiplier => 4/3; + public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 1a7e84f58..9f95e40a0 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -264,8 +264,8 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) } else if (context.IsPriorityPrimary || (context.IsFallbackPrimary && message.ViewNumber == 0)) { - uint pOrF = Convert.ToUInt32(context.IsPriorityPrimary); - SendPrepareRequest(pOrF); + uint pID = Convert.ToUInt32(!context.IsPriorityPrimary); + SendPrepareRequest(pID); } } ExtensiblePayload[] prepareResponsePayloads = message.GetPrepareResponsePayloads(context); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 8dd50e328..25337896e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -158,12 +158,12 @@ private void OnStart() private void OnTimer(Timer timer) { - uint pOrF = Convert.ToUInt32(context.IsPriorityPrimary); + uint pID = Convert.ToUInt32(!context.IsPriorityPrimary); if (context.WatchOnly || context.BlockSent) return; - if (timer.Height != context.Block[pOrF].Index || timer.ViewNumber != context.ViewNumber) return; + if (timer.Height != context.Block[pID].Index || timer.ViewNumber != context.ViewNumber) return; if (context.IsAPrimary && !context.RequestSentOrReceived) { - SendPrepareRequest(pOrF); + SendPrepareRequest(pID); } else if ((context.IsAPrimary && context.RequestSentOrReceived) || context.IsBackup) { @@ -178,7 +178,7 @@ private void OnTimer(Timer timer) { var reason = ChangeViewReason.Timeout; - if (context.Block[pOrF] != null && context.TransactionHashes[pOrF]?.Length > context.Transactions[pOrF]?.Count) + if (context.Block[pID] != null && context.TransactionHashes[pID]?.Length > context.Transactions[pID]?.Count) { reason = ChangeViewReason.TxNotFound; } @@ -196,18 +196,15 @@ private void SendPrepareRequest(uint i) if (context.Validators.Length == 1) CheckPreparations(i); + Log($"SendPrepareRequest I",LogLevel.Debug); + if (context.TransactionHashes[i].Length > 0) { foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[i])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } - //Multiplier for Primary P1 or FellBeck P2 - float multiplier = 1; - if (context.IsFallbackPrimary) - multiplier = 4 / 3; - // TODO Change to context.Multiplier - - ChangeTimer(TimeSpan.FromMilliseconds(multiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); + Log($"SendPrepareRequest II",LogLevel.Debug); + ChangeTimer(TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); } private void RequestRecovery() From bedb125090acb601e1b55c6bccc921ab71dd98e4 Mon Sep 17 00:00:00 2001 From: Vitor Date: Mon, 17 Jan 2022 14:17:23 -0300 Subject: [PATCH 15/43] Format --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 2 +- src/DBFTPlugin/Consensus/ConsensusService.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index b20cb6b07..c026ff7f0 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -61,7 +61,7 @@ public partial class ConsensusContext : IDisposable, ISerializable //Modify to be 1 or 4/3 public float PrimaryTimerPriorityMultiplier => 1; - public float PrimaryTimerFallBackMultiplier => 4/3; + public float PrimaryTimerFallBackMultiplier => 4 / 3; public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 25337896e..348abdfd6 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -196,14 +196,14 @@ private void SendPrepareRequest(uint i) if (context.Validators.Length == 1) CheckPreparations(i); - Log($"SendPrepareRequest I",LogLevel.Debug); + Log($"SendPrepareRequest I", LogLevel.Debug); if (context.TransactionHashes[i].Length > 0) { foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[i])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } - Log($"SendPrepareRequest II",LogLevel.Debug); + Log($"SendPrepareRequest II", LogLevel.Debug); ChangeTimer(TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); } From 73626acdf36fc8fcb1c4825d54100f21c5d146e1 Mon Sep 17 00:00:00 2001 From: Vitor Date: Mon, 17 Jan 2022 14:34:15 -0300 Subject: [PATCH 16/43] Fixing state --- .../Consensus/ConsensusContext.MakePayload.cs | 33 +++---- src/DBFTPlugin/Consensus/ConsensusContext.cs | 86 ++++++++++--------- .../Consensus/ConsensusService.Check.cs | 19 ++-- src/DBFTPlugin/Consensus/ConsensusService.cs | 12 +-- 4 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 51a557bb5..0adcc67bf 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -59,7 +59,7 @@ private void SignPayload(ExtensiblePayload payload) /// Prevent that block exceed the max size /// /// Ordered transactions - internal void EnsureMaxBlockLimitation(IEnumerable txs, uint i) + internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pID) { uint maxTransactionsPerBlock = neoSystem.Settings.MaxTransactionsPerBlock; @@ -67,8 +67,8 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs, uint i) txs = txs.Take((int)maxTransactionsPerBlock); List hashes = new List(); - Transactions[i] = new Dictionary(); - VerificationContext[i] = new TransactionVerificationContext(); + Transactions[pID] = new Dictionary(); + VerificationContext[pID] = new TransactionVerificationContext(); // Expected block size var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); @@ -86,26 +86,27 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs, uint i) if (blockSystemFee > dbftSettings.MaxBlockSystemFee) break; hashes.Add(tx.Hash); - Transactions[i].Add(tx.Hash, tx); - VerificationContext[i].AddTransaction(tx); + Transactions[pID].Add(tx.Hash, tx); + VerificationContext[pID].AddTransaction(tx); } - TransactionHashes[i] = hashes.ToArray(); + TransactionHashes[pID] = hashes.ToArray(); } - public ExtensiblePayload MakePrepareRequest(uint i) + public ExtensiblePayload MakePrepareRequest(uint pID) { - EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions(), i); - Block[i].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); - Block[i].Header.Nonce = GetNonce(); + Log($"MakePrepareRequest I", LogLevel.Debug); + EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions(), pID); + Block[pID].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); + Block[pID].Header.Nonce = GetNonce(); - return PreparationPayloads[i][MyIndex] = MakeSignedPayload(new PrepareRequest + return PreparationPayloads[pID][MyIndex] = MakeSignedPayload(new PrepareRequest { - Version = Block[i].Version, - PrevHash = Block[i].PrevHash, - Timestamp = Block[i].Timestamp, - Nonce = Block[i].Nonce, - TransactionHashes = TransactionHashes[i] + Version = Block[pID].Version, + PrevHash = Block[pID].PrevHash, + Timestamp = Block[pID].Timestamp, + Nonce = Block[pID].Nonce, + TransactionHashes = TransactionHashes[pID] }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index c026ff7f0..4fcffce44 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -88,7 +88,7 @@ public bool ValidatorsChanged } #region Consensus States - public bool RequestSentOrReceived => (PreparationPayloads[0][Block[0].PrimaryIndex] != null || PreparationPayloads[1][Block[0].PrimaryIndex] != null); + public bool RequestSentOrReceived => (PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || PreparationPayloads[1][GetFallbackPrimaryIndex(ViewNumber)] != null); public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || PreparationPayloads[1][MyIndex] != null); public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || CommitPayloads[1][MyIndex] != null); public bool BlockSent => (Block[0].Transactions != null || Block[1].Transactions != null); @@ -112,20 +112,20 @@ public ConsensusContext(NeoSystem neoSystem, Settings settings, Wallet wallet) this.store = neoSystem.LoadStore(settings.RecoveryLogs); } - public Block CreateBlock(uint ii) + public Block CreateBlock(uint pID) { - EnsureHeader(ii); + EnsureHeader(pID); Contract contract = Contract.CreateMultiSigContract(M, Validators); - ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block[ii].Header, dbftSettings.Network); + ContractParametersContext sc = new ContractParametersContext(neoSystem.StoreView, Block[pID].Header, dbftSettings.Network); for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { - if (GetMessage(CommitPayloads[ii][i])?.ViewNumber != ViewNumber) continue; - sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[ii][i]).Signature); + if (GetMessage(CommitPayloads[pID][i])?.ViewNumber != ViewNumber) continue; + sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[pID][i]).Signature); j++; } - Block[ii].Header.Witness = sc.GetWitnesses()[0]; - Block[ii].Transactions = TransactionHashes[ii].Select(p => Transactions[ii][p]).ToArray(); - return Block[ii]; + Block[pID].Header.Witness = sc.GetWitnesses()[0]; + Block[pID].Transactions = TransactionHashes[pID].Select(p => Transactions[pID][p]).ToArray(); + return Block[pID]; } public ExtensiblePayload CreatePayload(ConsensusMessage message, byte[] invocationScript = null) @@ -152,11 +152,11 @@ public void Dispose() Snapshot?.Dispose(); } - public Block EnsureHeader(uint i) + public Block EnsureHeader(uint pID) { - if (TransactionHashes[i] == null) return null; - Block[i].Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes[i]); - return Block[i]; + if (TransactionHashes[pID] == null) return null; + Block[pID].Header.MerkleRoot ??= MerkleTree.ComputeRoot(TransactionHashes[pID]); + return Block[pID]; } public bool Load() @@ -256,18 +256,19 @@ public void Reset(byte viewNumber) } ViewNumber = viewNumber; - for (uint i = 0; i <= 1; i++) + for (uint pID = 0; pID <= 1; pID++) { - Block[i].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); - Block[i].Header.MerkleRoot = null; - Block[i].Header.Timestamp = 0; - Block[i].Header.Nonce = 0; - Block[i].Transactions = null; - TransactionHashes[i] = null; - PreparationPayloads[i] = new ExtensiblePayload[Validators.Length]; - if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[i].Index; + Block[pID].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); + Block[pID].Header.MerkleRoot = null; + Block[pID].Header.Timestamp = 0; + Block[pID].Header.Nonce = 0; + Block[pID].Transactions = null; + TransactionHashes[pID] = null; + PreparationPayloads[pID] = new ExtensiblePayload[Validators.Length]; + if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; } + //========================================= // Disable Fallback if viewnumber > 1 if (viewNumber > 0) { @@ -279,6 +280,7 @@ public void Reset(byte viewNumber) PreCommitPayloads[1] = null; CommitPayloads[1] = null; } + //========================================= } public void Save() @@ -289,31 +291,31 @@ public void Save() public void Deserialize(BinaryReader reader) { Reset(0); - for (uint i = 0; i <= 1; i++) + for (uint pID = 0; pID <= 1; pID++) { - if (reader.ReadUInt32() != Block[i].Version) throw new FormatException(); - if (reader.ReadUInt32() != Block[i].Index) throw new InvalidOperationException(); - Block[i].Header.Timestamp = reader.ReadUInt64(); - Block[i].Header.Nonce = reader.ReadUInt64(); - Block[i].Header.PrimaryIndex = reader.ReadByte(); - Block[i].Header.NextConsensus = reader.ReadSerializable(); - if (Block[i].NextConsensus.Equals(UInt160.Zero)) - Block[i].Header.NextConsensus = null; + if (reader.ReadUInt32() != Block[pID].Version) throw new FormatException(); + if (reader.ReadUInt32() != Block[pID].Index) throw new InvalidOperationException(); + Block[pID].Header.Timestamp = reader.ReadUInt64(); + Block[pID].Header.Nonce = reader.ReadUInt64(); + Block[pID].Header.PrimaryIndex = reader.ReadByte(); + Block[pID].Header.NextConsensus = reader.ReadSerializable(); + if (Block[pID].NextConsensus.Equals(UInt160.Zero)) + Block[pID].Header.NextConsensus = null; - TransactionHashes[i] = reader.ReadSerializableArray(ushort.MaxValue); + TransactionHashes[pID] = reader.ReadSerializableArray(ushort.MaxValue); Transaction[] transactions = reader.ReadSerializableArray(ushort.MaxValue); - PreparationPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); - PreCommitPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); - CommitPayloads[i] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + PreparationPayloads[pID] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + PreCommitPayloads[pID] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); + CommitPayloads[pID] = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); - if (TransactionHashes[i].Length == 0 && !RequestSentOrReceived) - TransactionHashes[i] = null; - Transactions[i] = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); - VerificationContext[i] = new TransactionVerificationContext(); - if (Transactions[i] != null) + if (TransactionHashes[pID].Length == 0 && !RequestSentOrReceived) + TransactionHashes[pID] = null; + Transactions[pID] = transactions.Length == 0 && !RequestSentOrReceived ? null : transactions.ToDictionary(p => p.Hash); + VerificationContext[pID] = new TransactionVerificationContext(); + if (Transactions[pID] != null) { - foreach (Transaction tx in Transactions[i].Values) - VerificationContext[i].AddTransaction(tx); + foreach (Transaction tx in Transactions[pID].Values) + VerificationContext[pID].AddTransaction(tx); } } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index db0e0b23c..d5c775f1a 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -89,25 +89,26 @@ private void CheckExpectedView(byte viewNumber) } } - private void CheckPreparations(uint i) + private void CheckPreparations(uint pID) { - int thresholdForPrep = context.F + 1; - if (i == 1) - thresholdForPrep = context.M; + int thresholdForPrep = pID == 0 ? context.F + 1 : context.M; - if (context.PreparationPayloads[i].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) + if (context.PreparationPayloads[pID].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes[pID].All(p => context.Transactions[pID].ContainsKey(p))) { - ExtensiblePayload payload = context.MakePreCommit(i); - Log($"Sending {nameof(PreCommit)} pOrF={i}"); + ExtensiblePayload payload = context.MakePreCommit(pID); + Log($"Sending {nameof(PreCommit)} pOrF={pID}"); context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); - CheckPreCommits(i); + CheckPreCommits(pID); + // ============================================== // Speed-up path to also send commit - if (i == 0 && context.PreparationPayloads[0].Count(p => p != null) >= context.M) + if (pID == 0 && context.PreparationPayloads[0].Count(p => p != null) >= context.M) CheckPreCommits(0, true); + // ============================================== + return; } } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 348abdfd6..da12f56dc 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -188,19 +188,19 @@ private void OnTimer(Timer timer) } } - private void SendPrepareRequest(uint i) + private void SendPrepareRequest(uint pID) { - Log($"Sending {nameof(PrepareRequest)}: height={context.Block[i].Index} view={context.ViewNumber} Id={i}"); - localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest(i) }); + Log($"Sending {nameof(PrepareRequest)}: height={context.Block[pID].Index} view={context.ViewNumber} Id={pID}"); + localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest(pID) }); if (context.Validators.Length == 1) - CheckPreparations(i); + CheckPreparations(pID); Log($"SendPrepareRequest I", LogLevel.Debug); - if (context.TransactionHashes[i].Length > 0) + if (context.TransactionHashes[pID].Length > 0) { - foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[i])) + foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[pID])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } Log($"SendPrepareRequest II", LogLevel.Debug); From 29e267bdf9a912bd85d2ac414ed7599de6fd53e2 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 8 Jun 2022 11:17:09 +0800 Subject: [PATCH 17/43] fix build error --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 2 +- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- src/DBFTPlugin/Messages/Commit.cs | 6 +++--- src/DBFTPlugin/Messages/PreCommit.cs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 59d2c7c5b..b8a687a47 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -130,7 +130,7 @@ public Block CreateBlock(uint pID) for (int i = 0, j = 0; i < Validators.Length && j < M; i++) { if (GetMessage(CommitPayloads[pID][i])?.ViewNumber != ViewNumber) continue; - sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[pID][i]).Signature); + sc.AddSignature(contract, Validators[i], GetMessage(CommitPayloads[pID][i]).Signature.ToArray()); j++; } Block[pID].Header.Witness = sc.GetWitnesses()[0]; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index fef4bf30d..bdefba06a 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -117,7 +117,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest byte[] hashData = context.EnsureHeader(pOrF).GetSignData(neoSystem.Settings.Network); for (int i = 0; i < context.CommitPayloads[pOrF].Length; i++) if (context.GetMessage(context.CommitPayloads[pOrF][i])?.ViewNumber == context.ViewNumber) - if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pOrF][i]).Signature, context.Validators[i])) + if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pOrF][i]).Signature.Span, context.Validators[i])) context.CommitPayloads[pOrF][i] = null; if (context.TransactionHashes[pOrF].Length == 0) diff --git a/src/DBFTPlugin/Messages/Commit.cs b/src/DBFTPlugin/Messages/Commit.cs index ecca390e8..8ab9270a4 100644 --- a/src/DBFTPlugin/Messages/Commit.cs +++ b/src/DBFTPlugin/Messages/Commit.cs @@ -27,15 +27,15 @@ public Commit() : base(ConsensusMessageType.Commit) { } public override void Deserialize(ref MemoryReader reader) { - base.Deserialize(reader); - Signature = reader.ReadFixedBytes(64); + base.Deserialize(ref reader); + Signature = reader.ReadMemory(64); Id = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); - writer.Write(Signature); + writer.Write(Signature.Span); writer.Write(Id); } } diff --git a/src/DBFTPlugin/Messages/PreCommit.cs b/src/DBFTPlugin/Messages/PreCommit.cs index 0971f8c9c..578b2e121 100644 --- a/src/DBFTPlugin/Messages/PreCommit.cs +++ b/src/DBFTPlugin/Messages/PreCommit.cs @@ -13,9 +13,9 @@ public class PreCommit : ConsensusMessage public PreCommit() : base(ConsensusMessageType.PreCommit) { } - public override void Deserialize(BinaryReader reader) + public override void Deserialize(ref MemoryReader reader) { - base.Deserialize(reader); + base.Deserialize(ref reader); PreparationHash = reader.ReadSerializable(); Id = reader.ReadUInt32(); } From d0b1c75261271f659077bfccba70235440e1d790 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 8 Jun 2022 10:57:47 +0800 Subject: [PATCH 18/43] optimize --- .../Consensus/ConsensusContext.MakePayload.cs | 5 +-- src/DBFTPlugin/Consensus/ConsensusContext.cs | 31 ++++++++------ .../Consensus/ConsensusService.Check.cs | 41 +++++++++++-------- .../Consensus/ConsensusService.OnMessage.cs | 16 +++++--- src/DBFTPlugin/Consensus/ConsensusService.cs | 7 +--- 5 files changed, 56 insertions(+), 44 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 628db97cc..a332c1155 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -106,7 +106,6 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pID) public ExtensiblePayload MakePrepareRequest(uint pID) { - Log($"MakePrepareRequest I", LogLevel.Debug); EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions(), pID); Block[pID].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); Block[pID].Header.Nonce = GetNonce(); @@ -132,7 +131,7 @@ public ExtensiblePayload MakeRecoveryRequest() public ExtensiblePayload MakeRecoveryMessage() { PrepareRequest prepareRequestMessage = null; - if (TransactionHashes != null) + if (TransactionHashes[0] != null) { prepareRequestMessage = new PrepareRequest { @@ -171,7 +170,7 @@ public ExtensiblePayload MakePreCommit(uint i) { return PreCommitPayloads[i][MyIndex] = MakeSignedPayload(new PreCommit { - PreparationHash = PreCommitPayloads[i][Block[i].PrimaryIndex].Hash, + PreparationHash = PreparationPayloads[i][Block[i].PrimaryIndex].Hash, Id = i }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index b8a687a47..80d1b6d7d 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -67,16 +67,16 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); public bool IsFallbackPrimary => MyIndex == GetFallbackPrimaryIndex(ViewNumber); - public bool IsAPrimary => IsPriorityPrimary || IsFallbackPrimary; + public bool IsAPrimary => IsPriorityPrimary || (ViewNumber == 0 && IsFallbackPrimary); //Modify to be 1 or 4/3 public float PrimaryTimerPriorityMultiplier => 1; - public float PrimaryTimerFallBackMultiplier => 4 / 3; + public float PrimaryTimerFallBackMultiplier => (float)4 / 3; public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; - public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && IsFallbackPrimary; + public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); - public int CountCommitted => CommitPayloads.Count(p => p != null); + public int CountCommitted => CommitPayloads[0].Count(p => p != null); public int CountFailed { get @@ -98,10 +98,11 @@ public bool ValidatorsChanged } #region Consensus States - public bool RequestSentOrReceived => (PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || PreparationPayloads[1][GetFallbackPrimaryIndex(ViewNumber)] != null); - public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || PreparationPayloads[1][MyIndex] != null); - public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || CommitPayloads[1][MyIndex] != null); - public bool BlockSent => (Block[0].Transactions != null || Block[1].Transactions != null); + public bool RequestSentOrReceived => PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || (ViewNumber == 0 && PreparationPayloads[1][GetFallbackPrimaryIndex(ViewNumber)] != null); + public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreparationPayloads[1][MyIndex] != null)); + public bool PreCommitSent => !WatchOnly && (PreCommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreCommitPayloads[1][MyIndex] != null)); + public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && CommitPayloads[1][MyIndex] != null)); + public bool BlockSent => Block[0].Transactions != null || (ViewNumber == 0 && Block[1]?.Transactions != null); public bool ViewChanging => !WatchOnly && GetMessage(ChangeViewPayloads[MyIndex])?.NewViewNumber > ViewNumber; public bool NotAcceptingPayloadsDueToViewChanging => ViewChanging && !MoreThanFNodesCommittedOrLost; // A possible attack can happen if the last node to commit is malicious and either sends change view after his @@ -228,7 +229,10 @@ public void Reset(byte viewNumber) } MyIndex = -1; for (uint i = 0; i <= 1; i++) + { + PreCommitPayloads[i] = new ExtensiblePayload[Validators.Length]; CommitPayloads[i] = new ExtensiblePayload[Validators.Length]; + } ChangeViewPayloads = new ExtensiblePayload[Validators.Length]; LastChangeViewPayloads = new ExtensiblePayload[Validators.Length]; if (ValidatorsChanged || LastSeenMessage is null) @@ -266,7 +270,6 @@ public void Reset(byte viewNumber) ViewNumber = viewNumber; for (uint pID = 0; pID <= 1; pID++) { - Block[pID].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); Block[pID].Header.MerkleRoot = null; Block[pID].Header.Timestamp = 0; Block[pID].Header.Nonce = 0; @@ -275,7 +278,8 @@ public void Reset(byte viewNumber) PreparationPayloads[pID] = new ExtensiblePayload[Validators.Length]; if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; } - + Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); + Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber); //========================================= // Disable Fallback if viewnumber > 1 if (viewNumber > 0) @@ -299,8 +303,10 @@ public void Save() public void Deserialize(ref MemoryReader reader) { Reset(0); + ViewNumber = reader.ReadByte(); for (uint pID = 0; pID <= 1; pID++) { + if (ViewNumber > 0 && pID > 0) break; if (reader.ReadUInt32() != Block[pID].Version) throw new FormatException(); if (reader.ReadUInt32() != Block[pID].Index) throw new InvalidOperationException(); Block[pID].Header.Timestamp = reader.ReadUInt64(); @@ -326,8 +332,6 @@ public void Deserialize(ref MemoryReader reader) VerificationContext[pID].AddTransaction(tx); } } - - ViewNumber = reader.ReadByte(); ChangeViewPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); LastChangeViewPayloads = reader.ReadNullableArray(neoSystem.Settings.ValidatorsCount); @@ -335,8 +339,10 @@ public void Deserialize(ref MemoryReader reader) public void Serialize(BinaryWriter writer) { + writer.Write(ViewNumber); for (uint i = 0; i <= 1; i++) { + if (ViewNumber > 0 && i > 0) break; writer.Write(Block[i].Version); writer.Write(Block[i].Index); writer.Write(Block[i].Timestamp); @@ -349,7 +355,6 @@ public void Serialize(BinaryWriter writer) writer.WriteNullableArray(PreCommitPayloads[i]); writer.WriteNullableArray(CommitPayloads[i]); } - writer.Write(ViewNumber); writer.WriteNullableArray(ChangeViewPayloads); writer.WriteNullableArray(LastChangeViewPayloads); } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index 8b9496eca..8d97cf36c 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -25,7 +25,7 @@ private bool CheckPrepareResponse(uint i) { // if we are the primary for this view, but acting as a backup because we recovered our own // previously sent prepare request, then we don't want to send a prepare response. - if (context.IsAPrimary || context.WatchOnly) return true; + if ((i == 0 && context.IsPriorityPrimary) || (i == 1 && context.IsFallbackPrimary) || context.WatchOnly) return true; // Check maximum block size via Native Contract policy if (context.GetExpectedBlockSize(i) > dbftSettings.MaxBlockSize) @@ -101,25 +101,30 @@ private void CheckExpectedView(byte viewNumber) private void CheckPreparations(uint pID) { - int thresholdForPrep = pID == 0 ? context.F + 1 : context.M; - - if (context.PreparationPayloads[pID].Count(p => p != null) >= thresholdForPrep && context.TransactionHashes[pID].All(p => context.Transactions[pID].ContainsKey(p))) + if (context.TransactionHashes[pID].All(p => context.Transactions[pID].ContainsKey(p))) { - ExtensiblePayload payload = context.MakePreCommit(pID); - Log($"Sending {nameof(PreCommit)} pOrF={pID}"); - context.Save(); - localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); - // Set timer, so we will resend the commit in case of a networking issue - ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); - CheckPreCommits(pID); - - // ============================================== - // Speed-up path to also send commit - if (pID == 0 && context.PreparationPayloads[0].Count(p => p != null) >= context.M) + var preparationsCount = context.PreparationPayloads[pID].Count(p => p != null); + if (context.ViewNumber > 0) + { + if (preparationsCount >= context.M) + CheckPreCommits(0, true); + return; + } + if (!context.PreCommitSent + && ((pID == 0 && preparationsCount >= context.F + 1) + || (pID == 1 && preparationsCount >= context.M))) + { + ExtensiblePayload payload = context.MakePreCommit(pID); + Log($"Sending {nameof(PreCommit)} pOrF={pID}"); + context.Save(); + localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); + // Set timer, so we will resend the commit in case of a networking issue + ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); + } + if (context.ViewNumber == 0 && pID == 0 && preparationsCount >= context.M) + { CheckPreCommits(0, true); - // ============================================== - - return; + } } } } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index bdefba06a..ddf0839b6 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -80,7 +80,7 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; - uint pOrF = Convert.ToUInt32(message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)); + uint pOrF = message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber) || context.ViewNumber > 0 ? 0u : 1u; // Add verification for Fallback if (message.ValidatorIndex != context.Block[pOrF].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; if (message.Version != context.Block[pOrF].Version || message.PrevHash != context.Block[pOrF].PrevHash) return; @@ -160,8 +160,14 @@ private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareRespons { if (message.ViewNumber != context.ViewNumber) return; if (context.PreparationPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; - if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) - return; + if (context.RequestSentOrReceived) + { + // Check if we have joined another consensus process + if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] == null) return; + if (!message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + return; + } + // Timeout extension: prepare response has been received with success // around 2*15/M=30.0/5 ~ 40% block time (for M=5) @@ -177,8 +183,8 @@ private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareRespons private void OnPreCommitReceived(ExtensiblePayload payload, PreCommit message) { if (message.ViewNumber != context.ViewNumber) return; - if (context.PreparationPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; - if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + if (context.PreCommitPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; + if (context.PreCommitPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) return; Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 81d8c6fa3..ac84f8ba6 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -81,7 +81,7 @@ private void InitializeConsensus(byte viewNumber) if (viewNumber > 0) Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPriorityPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); uint blockCurrentIndex = context.Block[0].Index; - Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? "PrimaryP1" : context.IsFallbackPrimary ? "PrimaryP2" : context.WatchOnly ? "WatchOnly" : "Backup")}"); + Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? (viewNumber > 0 ? "Primary" : "PrimaryP1") : (context.IsFallbackPrimary && viewNumber == 0 ? "PrimaryP2" : (context.WatchOnly ? "WatchOnly" : "Backup")))}"); if (context.WatchOnly) return; if (context.IsAPrimary) { @@ -168,7 +168,7 @@ private void OnStart() private void OnTimer(Timer timer) { - uint pID = Convert.ToUInt32(!context.IsPriorityPrimary); + uint pID = Convert.ToUInt32(!(context.IsPriorityPrimary || context.ViewNumber > 0)); if (context.WatchOnly || context.BlockSent) return; if (timer.Height != context.Block[pID].Index || timer.ViewNumber != context.ViewNumber) return; if (context.IsAPrimary && !context.RequestSentOrReceived) @@ -206,14 +206,11 @@ private void SendPrepareRequest(uint pID) if (context.Validators.Length == 1) CheckPreparations(pID); - Log($"SendPrepareRequest I", LogLevel.Debug); - if (context.TransactionHashes[pID].Length > 0) { foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[pID])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } - Log($"SendPrepareRequest II", LogLevel.Debug); ChangeTimer(TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); } From d06424fc39c0e21913722ef36c7bb45d95c47817 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 8 Jun 2022 16:14:16 +0800 Subject: [PATCH 19/43] fix commitedcount --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 80d1b6d7d..42d61296e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -76,7 +76,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); - public int CountCommitted => CommitPayloads[0].Count(p => p != null); + public int CountCommitted => ViewNumber == 0 ? Math.Max(CommitPayloads[0].Count(p => p != null), CommitPayloads[1].Count(p => p != null)) : CommitPayloads[0].Count(p => p != null); public int CountFailed { get @@ -102,7 +102,7 @@ public bool ValidatorsChanged public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreparationPayloads[1][MyIndex] != null)); public bool PreCommitSent => !WatchOnly && (PreCommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreCommitPayloads[1][MyIndex] != null)); public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && CommitPayloads[1][MyIndex] != null)); - public bool BlockSent => Block[0].Transactions != null || (ViewNumber == 0 && Block[1]?.Transactions != null); + public bool BlockSent => Block[0].Transactions != null || Block[1]?.Transactions != null; public bool ViewChanging => !WatchOnly && GetMessage(ChangeViewPayloads[MyIndex])?.NewViewNumber > ViewNumber; public bool NotAcceptingPayloadsDueToViewChanging => ViewChanging && !MoreThanFNodesCommittedOrLost; // A possible attack can happen if the last node to commit is malicious and either sends change view after his From 482d0559c81d4bb1424e2e70074b29c893ba9596 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Thu, 9 Jun 2022 16:46:06 +0800 Subject: [PATCH 20/43] recovery contains PreCommit and P2 messages --- .../Consensus/ConsensusContext.Get.cs | 12 +++++ .../Consensus/ConsensusContext.MakePayload.cs | 24 +++++---- src/DBFTPlugin/Consensus/ConsensusContext.cs | 47 +++++++++-------- .../Consensus/ConsensusService.Check.cs | 1 + .../Consensus/ConsensusService.OnMessage.cs | 17 +++++-- ...RecoveryMessage.PreCommitPayloadCompact.cs | 50 +++++++++++++++++++ .../RecoveryMessage/RecoveryMessage.cs | 26 ++++++++-- 7 files changed, 139 insertions(+), 38 deletions(-) create mode 100644 src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 41e404f9b..fbb426c5d 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -44,6 +44,18 @@ private ChangeViewPayloadCompact GetChangeViewPayloadCompact(ExtensiblePayload p }; } + private PreCommitPayloadCompact GetPreCommitPayloadCompact(ExtensiblePayload payload) + { + PreCommit preCommit = GetMessage(payload); + return new PreCommitPayloadCompact + { + ViewNumber = preCommit.ViewNumber, + ValidatorIndex = preCommit.ValidatorIndex, + PreparationHash = preCommit.PreparationHash, + InvocationScript = payload.Witness.InvocationScript, + }; + } + private CommitPayloadCompact GetCommitPayloadCompact(ExtensiblePayload payload) { Commit message = GetMessage(payload); diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index a332c1155..8fba17d9e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -8,6 +8,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Microsoft.EntityFrameworkCore; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; @@ -131,28 +132,31 @@ public ExtensiblePayload MakeRecoveryRequest() public ExtensiblePayload MakeRecoveryMessage() { PrepareRequest prepareRequestMessage = null; - if (TransactionHashes[0] != null) + uint pID = TransactionHashes[0] != null ? 0u : (TransactionHashes[1] != null ? 1u : 0u); + if (TransactionHashes[pID] != null) { prepareRequestMessage = new PrepareRequest { - Version = Block[0].Version, - PrevHash = Block[0].PrevHash, + Version = Block[pID].Version, + PrevHash = Block[pID].PrevHash, ViewNumber = ViewNumber, - Timestamp = Block[0].Timestamp, - Nonce = Block[0].Nonce, - BlockIndex = Block[0].Index, - TransactionHashes = TransactionHashes[0] + Timestamp = Block[pID].Timestamp, + Nonce = Block[pID].Nonce, + BlockIndex = Block[pID].Index, + TransactionHashes = TransactionHashes[pID] }; } return MakeSignedPayload(new RecoveryMessage { + Id = pID, ChangeViewMessages = LastChangeViewPayloads.Where(p => p != null).Select(p => GetChangeViewPayloadCompact(p)).Take(M).ToDictionary(p => p.ValidatorIndex), PrepareRequestMessage = prepareRequestMessage, // We only need a PreparationHash set if we don't have the PrepareRequest information. - PreparationHash = TransactionHashes[0] == null ? PreparationPayloads[0].Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, - PreparationMessages = PreparationPayloads[0].Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), + PreparationHash = TransactionHashes[pID] == null ? PreparationPayloads[pID].Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, + PreparationMessages = PreparationPayloads[pID].Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), + PreCommitMessages = PreCommitPayloads[pID].Where(p => p != null).Select(p => GetPreCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), CommitMessages = CommitSent - ? CommitPayloads[0].Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) + ? CommitPayloads[pID].Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) : new Dictionary() }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 42d61296e..8521ef774 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -70,8 +70,8 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsAPrimary => IsPriorityPrimary || (ViewNumber == 0 && IsFallbackPrimary); //Modify to be 1 or 4/3 - public float PrimaryTimerPriorityMultiplier => 1; - public float PrimaryTimerFallBackMultiplier => (float)4 / 3; + public static float PrimaryTimerPriorityMultiplier => 1; + public static float PrimaryTimerFallBackMultiplier => (float)4 / 3; public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; @@ -98,7 +98,7 @@ public bool ValidatorsChanged } #region Consensus States - public bool RequestSentOrReceived => PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || (ViewNumber == 0 && PreparationPayloads[1][GetFallbackPrimaryIndex(ViewNumber)] != null); + public bool RequestSentOrReceived => PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || (ViewNumber == 0 && PreparationPayloads[1][GetFallbackPrimaryIndex(0)] != null); public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreparationPayloads[1][MyIndex] != null)); public bool PreCommitSent => !WatchOnly && (PreCommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreCommitPayloads[1][MyIndex] != null)); public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && CommitPayloads[1][MyIndex] != null)); @@ -257,6 +257,18 @@ public void Reset(byte viewNumber) break; } cachedMessages = new Dictionary(); + for (uint pID = 0; pID <= 1; pID++) + { + Block[pID].Header.MerkleRoot = null; + Block[pID].Header.Timestamp = 0; + Block[pID].Header.Nonce = 0; + Block[pID].Transactions = null; + TransactionHashes[pID] = null; + PreparationPayloads[pID] = new ExtensiblePayload[Validators.Length]; + if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; + } + Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); + Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber); } else { @@ -265,25 +277,16 @@ public void Reset(byte viewNumber) LastChangeViewPayloads[i] = ChangeViewPayloads[i]; else LastChangeViewPayloads[i] = null; - } - ViewNumber = viewNumber; - for (uint pID = 0; pID <= 1; pID++) - { - Block[pID].Header.MerkleRoot = null; - Block[pID].Header.Timestamp = 0; - Block[pID].Header.Nonce = 0; - Block[pID].Transactions = null; - TransactionHashes[pID] = null; - PreparationPayloads[pID] = new ExtensiblePayload[Validators.Length]; - if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; - } - Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); - Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber); - //========================================= - // Disable Fallback if viewnumber > 1 - if (viewNumber > 0) - { + Block[0].Header.MerkleRoot = null; + Block[0].Header.Timestamp = 0; + Block[0].Header.Nonce = 0; + Block[0].Transactions = null; + TransactionHashes[0] = null; + PreparationPayloads[0] = new ExtensiblePayload[Validators.Length]; + if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[0].Index; + Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); + Block[1] = null; TransactionHashes[1] = null; Transactions[1] = null; @@ -292,7 +295,7 @@ public void Reset(byte viewNumber) PreCommitPayloads[1] = null; CommitPayloads[1] = null; } - //========================================= + ViewNumber = viewNumber; } public void Save() diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index 8d97cf36c..1f6fed157 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -120,6 +120,7 @@ private void CheckPreparations(uint pID) localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); + CheckPreCommits(pID); } if (context.ViewNumber == 0 && pID == 0 && preparationsCount >= context.M) { diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index ddf0839b6..d13642212 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -9,6 +9,7 @@ // modifications are permitted. using Akka.Actor; +using Akka.Util.Internal; using Neo.Cryptography; using Neo.IO; using Neo.Ledger; @@ -184,8 +185,13 @@ private void OnPreCommitReceived(ExtensiblePayload payload, PreCommit message) { if (message.ViewNumber != context.ViewNumber) return; if (context.PreCommitPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; - if (context.PreCommitPayloads[message.Id][context.Block[message.Id].PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) - return; + if (context.RequestSentOrReceived) + { + // Check if we have joined another consensus process + if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] == null) return; + if (!message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + return; + } Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); context.PreCommitPayloads[message.Id][message.ValidatorIndex] = payload; @@ -253,6 +259,7 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) isRecovering = true; int validChangeViews = 0, totalChangeViews = 0, validPrepReq = 0, totalPrepReq = 0; int validPrepResponses = 0, totalPrepResponses = 0, validCommits = 0, totalCommits = 0; + int validPreCommits = 0, totalPreCommits = 0; Log($"{nameof(OnRecoveryMessageReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex}"); try @@ -285,6 +292,10 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) totalPrepResponses = prepareResponsePayloads.Length; foreach (ExtensiblePayload prepareResponsePayload in prepareResponsePayloads) if (ReverifyAndProcessPayload(prepareResponsePayload)) validPrepResponses++; + ExtensiblePayload[] preCommitPayloads = message.GetPreCommitPayloads(context); + totalPreCommits = preCommitPayloads.Length; + foreach (ExtensiblePayload preCommitPayload in preCommitPayloads) + if (ReverifyAndProcessPayload(preCommitPayload)) validPreCommits++; } if (message.ViewNumber <= context.ViewNumber) { @@ -297,7 +308,7 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) } finally { - Log($"Recovery finished: (valid/total) ChgView: {validChangeViews}/{totalChangeViews} PrepReq: {validPrepReq}/{totalPrepReq} PrepResp: {validPrepResponses}/{totalPrepResponses} Commits: {validCommits}/{totalCommits}"); + Log($"Recovery finished: (valid/total) ChgView: {validChangeViews}/{totalChangeViews} PrepReq: {validPrepReq}/{totalPrepReq} PrepResp: {validPrepResponses}/{totalPrepResponses} PreCommits: {validPreCommits}/{totalPreCommits} Commits: {validCommits}/{totalCommits}"); isRecovering = false; } } diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs new file mode 100644 index 000000000..a909cfedf --- /dev/null +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs @@ -0,0 +1,50 @@ +// Copyright (C) 2015-2022 The Neo Project. +// +// The Neo.Consensus.DBFT is free software distributed under the MIT software license, +// see the accompanying file LICENSE in the main directory of the +// project or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Neo.IO; +using System; +using System.IO; + +namespace Neo.Consensus +{ + partial class RecoveryMessage + { + public class PreCommitPayloadCompact : ISerializable + { + public byte ViewNumber; + public byte ValidatorIndex; + public UInt256 PreparationHash; + public ReadOnlyMemory InvocationScript; + + int ISerializable.Size => + sizeof(byte) + //ViewNumber + sizeof(byte) + //ValidatorIndex + UInt256.Length + //PreparationHash + sizeof(uint) + //Id + InvocationScript.GetVarSize(); //InvocationScript + + void ISerializable.Deserialize(ref MemoryReader reader) + { + ViewNumber = reader.ReadByte(); + ValidatorIndex = reader.ReadByte(); + PreparationHash = reader.ReadSerializable(); + InvocationScript = reader.ReadVarMemory(1024); + } + + void ISerializable.Serialize(BinaryWriter writer) + { + writer.Write(ViewNumber); + writer.Write(ValidatorIndex); + writer.Write(PreparationHash); + writer.WriteVarBytes(InvocationScript.Span); + } + } + } +} diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index 66d220791..edf32ee9b 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -19,12 +19,14 @@ namespace Neo.Consensus { public partial class RecoveryMessage : ConsensusMessage { + public uint Id; public Dictionary ChangeViewMessages; public PrepareRequest PrepareRequestMessage; /// The PreparationHash in case the PrepareRequest hasn't been received yet. /// This can be null if the PrepareRequest information is present, since it can be derived in that case. public UInt256 PreparationHash; public Dictionary PreparationMessages; + public Dictionary PreCommitMessages; public Dictionary CommitMessages; public override int Size => base.Size @@ -39,6 +41,7 @@ public RecoveryMessage() : base(ConsensusMessageType.RecoveryMessage) { } public override void Deserialize(ref MemoryReader reader) { base.Deserialize(ref reader); + Id = reader.ReadUInt32(); ChangeViewMessages = reader.ReadSerializableArray(byte.MaxValue).ToDictionary(p => p.ValidatorIndex); if (reader.ReadBoolean()) { @@ -52,6 +55,7 @@ public override void Deserialize(ref MemoryReader reader) } PreparationMessages = reader.ReadSerializableArray(byte.MaxValue).ToDictionary(p => p.ValidatorIndex); + PreCommitMessages = reader.ReadSerializableArray(byte.MaxValue).ToDictionary(p => p.ValidatorIndex); CommitMessages = reader.ReadSerializableArray(byte.MaxValue).ToDictionary(p => p.ValidatorIndex); } @@ -82,6 +86,7 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte BlockIndex = BlockIndex, ValidatorIndex = p.ValidatorIndex, ViewNumber = p.ViewNumber, + Id = Id, Signature = p.Signature }, p.InvocationScript)).ToArray(); } @@ -89,27 +94,41 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte internal ExtensiblePayload GetPrepareRequestPayload(ConsensusContext context) { if (PrepareRequestMessage == null) return null; - if (!PreparationMessages.TryGetValue(context.Block[0].PrimaryIndex, out PreparationPayloadCompact compact)) + if (PreparationMessages.TryGetValue(context.Block[Id].PrimaryIndex, out PreparationPayloadCompact compact)) return null; return context.CreatePayload(PrepareRequestMessage, compact.InvocationScript); } internal ExtensiblePayload[] GetPrepareResponsePayloads(ConsensusContext context) { - UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[0][context.Block[0].PrimaryIndex]?.Hash; + UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[Id][context.Block[Id].PrimaryIndex]?.Hash; if (preparationHash is null) return Array.Empty(); return PreparationMessages.Values.Where(p => p.ValidatorIndex != context.Block[0].PrimaryIndex).Select(p => context.CreatePayload(new PrepareResponse { BlockIndex = BlockIndex, ValidatorIndex = p.ValidatorIndex, ViewNumber = ViewNumber, - PreparationHash = preparationHash + Id = Id, + PreparationHash = preparationHash, + }, p.InvocationScript)).ToArray(); + } + + internal ExtensiblePayload[] GetPreCommitPayloads(ConsensusContext context) + { + return PreCommitMessages.Values.Select(p => context.CreatePayload(new PreCommit + { + BlockIndex = BlockIndex, + ViewNumber = p.ViewNumber, + ValidatorIndex = p.ValidatorIndex, + PreparationHash = p.PreparationHash, + Id = Id, }, p.InvocationScript)).ToArray(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); + writer.Write(Id); writer.Write(ChangeViewMessages.Values.ToArray()); bool hasPrepareRequestMessage = PrepareRequestMessage != null; writer.Write(hasPrepareRequestMessage); @@ -124,6 +143,7 @@ public override void Serialize(BinaryWriter writer) } writer.Write(PreparationMessages.Values.ToArray()); + writer.Write(PreCommitMessages.Values.ToArray()); writer.Write(CommitMessages.Values.ToArray()); } } From d7f452ac10ffd9887afefef85ea18e9cf93df23f Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Fri, 10 Jun 2022 11:45:39 +0800 Subject: [PATCH 21/43] fix OnStart and message sizes --- src/DBFTPlugin/Consensus/ConsensusService.cs | 11 +++++++---- src/DBFTPlugin/Messages/PreCommit.cs | 2 +- src/DBFTPlugin/Messages/PrepareResponse.cs | 3 ++- .../RecoveryMessage.PreCommitPayloadCompact.cs | 1 - 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index ac84f8ba6..acc2b0611 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -145,18 +145,21 @@ private void OnStart() started = true; if (!dbftSettings.IgnoreRecoveryLogs && context.Load()) { - // For Now, only checking Transactions for Priority + // For Now, only checking Transactions for Priority // Fallback works only for viewnumber 0 and this will not really make a difference - if (context.Transactions[0] != null) + var pId = context.RequestSentOrReceived + ? (context.PreparationPayloads[0][context.Block[0].PrimaryIndex] != null ? 0u : 1u) + : 0u; + if (context.Transactions[pId] != null) { blockchain.Ask(new Blockchain.FillMemoryPool { - Transactions = context.Transactions[0].Values + Transactions = context.Transactions[pId].Values }).Wait(); } if (context.CommitSent) { - CheckPreparations(0); + CheckPreparations(pId); return; } } diff --git a/src/DBFTPlugin/Messages/PreCommit.cs b/src/DBFTPlugin/Messages/PreCommit.cs index 578b2e121..48f04c477 100644 --- a/src/DBFTPlugin/Messages/PreCommit.cs +++ b/src/DBFTPlugin/Messages/PreCommit.cs @@ -9,7 +9,7 @@ public class PreCommit : ConsensusMessage // priority or fallback public uint Id; - public override int Size => base.Size + PreparationHash.Size; + public override int Size => base.Size + PreparationHash.Size + sizeof(uint); public PreCommit() : base(ConsensusMessageType.PreCommit) { } diff --git a/src/DBFTPlugin/Messages/PrepareResponse.cs b/src/DBFTPlugin/Messages/PrepareResponse.cs index 78f6de62e..2f561487e 100644 --- a/src/DBFTPlugin/Messages/PrepareResponse.cs +++ b/src/DBFTPlugin/Messages/PrepareResponse.cs @@ -9,6 +9,7 @@ // modifications are permitted. using Neo.IO; +using System; using System.IO; namespace Neo.Consensus @@ -19,7 +20,7 @@ public class PrepareResponse : ConsensusMessage // priority or fallback public uint Id; - public override int Size => base.Size + PreparationHash.Size; + public override int Size => base.Size + PreparationHash.Size + sizeof(uint); public PrepareResponse() : base(ConsensusMessageType.PrepareResponse) { } diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs index a909cfedf..e5b596178 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs @@ -27,7 +27,6 @@ public class PreCommitPayloadCompact : ISerializable sizeof(byte) + //ViewNumber sizeof(byte) + //ValidatorIndex UInt256.Length + //PreparationHash - sizeof(uint) + //Id InvocationScript.GetVarSize(); //InvocationScript void ISerializable.Deserialize(ref MemoryReader reader) From ffc57719762f1bdc6b395f41419fd4ccf237ddaa Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Fri, 10 Jun 2022 16:25:59 +0800 Subject: [PATCH 22/43] optimize --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 13 ++++++------- src/DBFTPlugin/Consensus/ConsensusService.cs | 17 +++++++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 8521ef774..3afd6132d 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -73,7 +73,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public static float PrimaryTimerPriorityMultiplier => 1; public static float PrimaryTimerFallBackMultiplier => (float)4 / 3; public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; - public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; + public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && (ViewNumber > 0 || !IsFallbackPrimary); public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); public int CountCommitted => ViewNumber == 0 ? Math.Max(CommitPayloads[0].Count(p => p != null), CommitPayloads[1].Count(p => p != null)) : CommitPayloads[0].Count(p => p != null); @@ -98,7 +98,7 @@ public bool ValidatorsChanged } #region Consensus States - public bool RequestSentOrReceived => PreparationPayloads[0][GetPriorityPrimaryIndex(ViewNumber)] != null || (ViewNumber == 0 && PreparationPayloads[1][GetFallbackPrimaryIndex(0)] != null); + public bool RequestSentOrReceived => PreparationPayloads[0][Block[0].PrimaryIndex] != null || (ViewNumber == 0 && PreparationPayloads[1][Block[1].PrimaryIndex] != null); public bool ResponseSent => !WatchOnly && (PreparationPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreparationPayloads[1][MyIndex] != null)); public bool PreCommitSent => !WatchOnly && (PreCommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && PreCommitPayloads[1][MyIndex] != null)); public bool CommitSent => !WatchOnly && (CommitPayloads[0][MyIndex] != null || (ViewNumber == 0 && CommitPayloads[1][MyIndex] != null)); @@ -228,11 +228,6 @@ public void Reset(byte viewNumber) } } MyIndex = -1; - for (uint i = 0; i <= 1; i++) - { - PreCommitPayloads[i] = new ExtensiblePayload[Validators.Length]; - CommitPayloads[i] = new ExtensiblePayload[Validators.Length]; - } ChangeViewPayloads = new ExtensiblePayload[Validators.Length]; LastChangeViewPayloads = new ExtensiblePayload[Validators.Length]; if (ValidatorsChanged || LastSeenMessage is null) @@ -265,6 +260,8 @@ public void Reset(byte viewNumber) Block[pID].Transactions = null; TransactionHashes[pID] = null; PreparationPayloads[pID] = new ExtensiblePayload[Validators.Length]; + PreCommitPayloads[pID] = new ExtensiblePayload[Validators.Length]; + CommitPayloads[pID] = new ExtensiblePayload[Validators.Length]; if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; } Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); @@ -284,6 +281,8 @@ public void Reset(byte viewNumber) Block[0].Transactions = null; TransactionHashes[0] = null; PreparationPayloads[0] = new ExtensiblePayload[Validators.Length]; + PreCommitPayloads[0] = new ExtensiblePayload[Validators.Length]; + CommitPayloads[0] = new ExtensiblePayload[Validators.Length]; if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[0].Index; Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index acc2b0611..73c428c98 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -171,12 +171,14 @@ private void OnStart() private void OnTimer(Timer timer) { - uint pID = Convert.ToUInt32(!(context.IsPriorityPrimary || context.ViewNumber > 0)); if (context.WatchOnly || context.BlockSent) return; - if (timer.Height != context.Block[pID].Index || timer.ViewNumber != context.ViewNumber) return; + if (timer.Height != context.Block[0].Index || timer.ViewNumber != context.ViewNumber) return; if (context.IsAPrimary && !context.RequestSentOrReceived) { - SendPrepareRequest(pID); + if (context.IsPriorityPrimary) + SendPrepareRequest(0); + else + SendPrepareRequest(1); } else if ((context.IsAPrimary && context.RequestSentOrReceived) || context.IsBackup) { @@ -190,10 +192,13 @@ private void OnTimer(Timer timer) else { var reason = ChangeViewReason.Timeout; - - if (context.Block[pID] != null && context.TransactionHashes[pID]?.Length > context.Transactions[pID]?.Count) + if (context.RequestSentOrReceived) { - reason = ChangeViewReason.TxNotFound; + var pId = context.PreparationPayloads[0][context.Block[0].PrimaryIndex] != null ? 0u : 1u; + if (context.Block[pId] != null && context.TransactionHashes[pId]?.Length > context.Transactions[pId]?.Count) + { + reason = ChangeViewReason.TxNotFound; + } } RequestChangeView(reason); From 52f06590aa786f72bb6a69566030b4dc2889cfb0 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Fri, 10 Jun 2022 17:22:47 +0800 Subject: [PATCH 23/43] optimize primary check --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index d13642212..3409b8a23 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -282,7 +282,7 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) totalPrepReq = 1; if (ReverifyAndProcessPayload(prepareRequestPayload)) validPrepReq++; } - else if (context.IsPriorityPrimary || (context.IsFallbackPrimary && message.ViewNumber == 0)) + else if (context.IsAPrimary) { uint pID = Convert.ToUInt32(!context.IsPriorityPrimary); SendPrepareRequest(pID); From 40348e1ea83ec703693a09f3799f7ba2d4c49819 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Fri, 10 Jun 2022 18:21:42 +0800 Subject: [PATCH 24/43] Round-Robin strategy 2 --- src/DBFTPlugin/Consensus/ConsensusContext.Get.cs | 8 +++++--- src/DBFTPlugin/Consensus/ConsensusContext.cs | 6 +++--- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index fbb426c5d..2f267446a 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -85,10 +85,12 @@ public byte GetPriorityPrimaryIndex(byte viewNumber) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte GetFallbackPrimaryIndex(byte viewNumber) + public byte GetFallbackPrimaryIndex(byte viewNumber, byte priorityPrimaryIndex) { - int p = ((int)Block[0].Index - viewNumber + 1) % Validators.Length; - return p >= 0 ? (byte)p : (byte)(p + Validators.Length); + if (Validators.Length <= 1) return priorityPrimaryIndex; + int p = ((int)Block[0].Index - viewNumber + 1) % (Validators.Length - 1); + p = p >= 0 ? (byte)p : (byte)(p + Validators.Length); + return p < priorityPrimaryIndex ? (byte)p : (byte)(p + 1); } public UInt160 GetSender(int index) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 3afd6132d..897c42070 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -64,8 +64,8 @@ public partial class ConsensusContext : IDisposable, ISerializable public int F => (Validators.Length - 1) / 3; public int M => Validators.Length - F; - public bool IsPriorityPrimary => MyIndex == GetPriorityPrimaryIndex(ViewNumber); - public bool IsFallbackPrimary => MyIndex == GetFallbackPrimaryIndex(ViewNumber); + public bool IsPriorityPrimary => MyIndex == Block[0].PrimaryIndex; + public bool IsFallbackPrimary => ViewNumber == 0 && MyIndex == Block[1].PrimaryIndex; public bool IsAPrimary => IsPriorityPrimary || (ViewNumber == 0 && IsFallbackPrimary); @@ -265,7 +265,7 @@ public void Reset(byte viewNumber) if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; } Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); - Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber); + Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber, Block[0].Header.PrimaryIndex); } else { diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 3409b8a23..dfce488da 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -87,7 +87,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest if (message.Version != context.Block[pOrF].Version || message.PrevHash != context.Block[pOrF].PrevHash) return; if (message.TransactionHashes.Length > neoSystem.Settings.MaxTransactionsPerBlock) return; - Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber)} fallback={message.ValidatorIndex == context.GetFallbackPrimaryIndex(context.ViewNumber)}"); + Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.Block[0].PrimaryIndex} fallback={context.ViewNumber == 0 && message.ValidatorIndex == context.Block[1].PrimaryIndex}"); if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMilliseconds(8 * neoSystem.Settings.MillisecondsPerBlock).ToTimestampMS()) { Log($"Timestamp incorrect: {message.Timestamp}", LogLevel.Warning); From 7a43c5cddac2e5ac7e57dae9852bca019bc1c696 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Fri, 10 Jun 2022 19:37:34 +0800 Subject: [PATCH 25/43] rm comment --- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 73c428c98..a1e7b087c 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -145,8 +145,6 @@ private void OnStart() started = true; if (!dbftSettings.IgnoreRecoveryLogs && context.Load()) { - // For Now, only checking Transactions for Priority - // Fallback works only for viewnumber 0 and this will not really make a difference var pId = context.RequestSentOrReceived ? (context.PreparationPayloads[0][context.Block[0].PrimaryIndex] != null ? 0u : 1u) : 0u; From 11a774733a7817f584ce1936bc1a6ef39e5489f0 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Mon, 13 Jun 2022 17:08:41 +0800 Subject: [PATCH 26/43] clean --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 4 ++-- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 897c42070..37f32e4ef 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -67,13 +67,13 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsPriorityPrimary => MyIndex == Block[0].PrimaryIndex; public bool IsFallbackPrimary => ViewNumber == 0 && MyIndex == Block[1].PrimaryIndex; - public bool IsAPrimary => IsPriorityPrimary || (ViewNumber == 0 && IsFallbackPrimary); + public bool IsAPrimary => IsPriorityPrimary || IsFallbackPrimary; //Modify to be 1 or 4/3 public static float PrimaryTimerPriorityMultiplier => 1; public static float PrimaryTimerFallBackMultiplier => (float)4 / 3; public float PrimaryTimerMultiplier => IsPriorityPrimary ? PrimaryTimerPriorityMultiplier : PrimaryTimerFallBackMultiplier; - public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && (ViewNumber > 0 || !IsFallbackPrimary); + public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); public int CountCommitted => ViewNumber == 0 ? Math.Max(CommitPayloads[0].Count(p => p != null), CommitPayloads[1].Count(p => p != null)) : CommitPayloads[0].Count(p => p != null); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index a1e7b087c..ff37cac8f 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -81,7 +81,7 @@ private void InitializeConsensus(byte viewNumber) if (viewNumber > 0) Log($"View changed: view={viewNumber} primary={context.Validators[context.GetPriorityPrimaryIndex((byte)(viewNumber - 1u))]}", LogLevel.Warning); uint blockCurrentIndex = context.Block[0].Index; - Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? (viewNumber > 0 ? "Primary" : "PrimaryP1") : (context.IsFallbackPrimary && viewNumber == 0 ? "PrimaryP2" : (context.WatchOnly ? "WatchOnly" : "Backup")))}"); + Log($"Initialize: height={blockCurrentIndex} view={viewNumber} index={context.MyIndex} role={(context.IsPriorityPrimary ? (viewNumber > 0 ? "Primary" : "PrimaryP1") : (context.IsFallbackPrimary ? "PrimaryP2" : (context.WatchOnly ? "WatchOnly" : "Backup")))}"); if (context.WatchOnly) return; if (context.IsAPrimary) { From e2ad61e06cc562db062440f9592aae7601e22416 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Tue, 14 Jun 2022 10:28:12 +0800 Subject: [PATCH 27/43] apply https://github.com/neo-project/neo/issues/2058 --- .../Consensus/ConsensusContext.MakePayload.cs | 14 +++++++++++++- src/DBFTPlugin/Consensus/ConsensusContext.cs | 3 +++ .../Consensus/ConsensusService.OnMessage.cs | 3 ++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 8fba17d9e..390545ec1 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -105,9 +105,21 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pID) TransactionHashes[pID] = hashes.ToArray(); } + internal IEnumerable PickTransactions() + { + var verifiedTxes = neoSystem.MemPool.GetSortedVerifiedTransactions(); + if (ViewNumber > 0 && LastProposal.Length > 0) + { + var txes = verifiedTxes.Where(p => LastProposal.Contains(p.Hash)); + if (txes.Count() > LastProposal.Length / 2) + return txes; + } + return verifiedTxes; + } + public ExtensiblePayload MakePrepareRequest(uint pID) { - EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions(), pID); + EnsureMaxBlockLimitation(PickTransactions(), pID); Block[pID].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); Block[pID].Header.Nonce = GetNonce(); diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 37f32e4ef..aec03cadd 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -43,6 +43,8 @@ public partial class ConsensusContext : IDisposable, ISerializable public ExtensiblePayload[][] CommitPayloads = new ExtensiblePayload[2][]; public ExtensiblePayload[] ChangeViewPayloads; public ExtensiblePayload[] LastChangeViewPayloads; + public UInt256[] LastProposal; + // LastSeenMessage array stores the height of the last seen message, for each validator. // if this node never heard from validator i, LastSeenMessage[i] will be -1. public Dictionary LastSeenMessage { get; private set; } @@ -252,6 +254,7 @@ public void Reset(byte viewNumber) break; } cachedMessages = new Dictionary(); + LastProposal = Array.Empty(); for (uint pID = 0; pID <= 1; pID++) { Block[pID].Header.MerkleRoot = null; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index dfce488da..0c1f368bb 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -107,7 +107,8 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest context.Block[pOrF].Header.Timestamp = message.Timestamp; context.Block[pOrF].Header.Nonce = message.Nonce; context.TransactionHashes[pOrF] = message.TransactionHashes; - + context.LastProposal = message.TransactionHashes; + context.Transactions[pOrF] = new Dictionary(); context.VerificationContext[pOrF] = new TransactionVerificationContext(); for (int i = 0; i < context.PreparationPayloads[pOrF].Length; i++) From 6772a4611c0ecc5403ebec3dbfcc76ae6f4e3a55 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Tue, 14 Jun 2022 11:45:09 +0800 Subject: [PATCH 28/43] format --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 0c1f368bb..9ca6ae8bc 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -108,7 +108,7 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest context.Block[pOrF].Header.Nonce = message.Nonce; context.TransactionHashes[pOrF] = message.TransactionHashes; context.LastProposal = message.TransactionHashes; - + context.Transactions[pOrF] = new Dictionary(); context.VerificationContext[pOrF] = new TransactionVerificationContext(); for (int i = 0; i < context.PreparationPayloads[pOrF].Length; i++) From e86de2a7376e54981dc64d50bc9b3a192814e30e Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Thu, 1 Sep 2022 11:10:26 +0800 Subject: [PATCH 29/43] fix tx dump --- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index ff37cac8f..18006bd9e 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -268,7 +268,7 @@ private bool AddTransaction(Transaction tx, bool verify) { bool returnValue = false; for (uint i = 0; i <= 1; i++) - if (context.TransactionHashes[i].Contains(tx.Hash)) + if (context.TransactionHashes[i] is not null && context.TransactionHashes[i].Contains(tx.Hash)) { if (verify) { From c2f0b02071a65fc56352f1506f558dfab9f555ff Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Tue, 13 Sep 2022 09:44:49 +0800 Subject: [PATCH 30/43] fix --- src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index edf32ee9b..4dd1a23d7 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -94,7 +94,7 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte internal ExtensiblePayload GetPrepareRequestPayload(ConsensusContext context) { if (PrepareRequestMessage == null) return null; - if (PreparationMessages.TryGetValue(context.Block[Id].PrimaryIndex, out PreparationPayloadCompact compact)) + if (!PreparationMessages.TryGetValue(context.Block[Id].PrimaryIndex, out PreparationPayloadCompact compact)) return null; return context.CreatePayload(PrepareRequestMessage, compact.InvocationScript); } From 19d281013b33384b45ea2b7ae1ac6476add6298e Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Tue, 13 Sep 2022 09:48:41 +0800 Subject: [PATCH 31/43] clean --- src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs | 1 - src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 390545ec1..51577e621 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -8,7 +8,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Microsoft.EntityFrameworkCore; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 52e6afa6c..60a2e4fb6 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -9,7 +9,6 @@ // modifications are permitted. using Akka.Actor; -using Akka.Util.Internal; using Neo.Cryptography; using Neo.IO; using Neo.Ledger; From d524245a0dce6c5947848bbdd0dae9c6ce8d3dbe Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Fri, 16 Sep 2022 09:00:11 -0300 Subject: [PATCH 32/43] Initial fix on countcommitted and fix cleaning CommitPayloads after change view --- src/DBFTPlugin/Consensus/ConsensusContext.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 06c54d65f..61f08c0eb 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -78,7 +78,7 @@ public partial class ConsensusContext : IDisposable, ISerializable public bool IsBackup => MyIndex >= 0 && !IsPriorityPrimary && !IsFallbackPrimary; public bool WatchOnly => MyIndex < 0; public Header PrevHeader => NativeContract.Ledger.GetHeader(Snapshot, Block[0].PrevHash); - public int CountCommitted => ViewNumber == 0 ? Math.Max(CommitPayloads[0].Count(p => p != null), CommitPayloads[1].Count(p => p != null)) : CommitPayloads[0].Count(p => p != null); + public int CountCommitted => CommitPayloads[0].Count(p => p != null) + CommitPayloads[1].Count(p => p != null); public int CountFailed { get @@ -289,7 +289,6 @@ public void Reset(byte viewNumber) TransactionHashes[0] = null; PreparationPayloads[0] = new ExtensiblePayload[Validators.Length]; PreCommitPayloads[0] = new ExtensiblePayload[Validators.Length]; - CommitPayloads[0] = new ExtensiblePayload[Validators.Length]; if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[0].Index; Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); @@ -299,7 +298,6 @@ public void Reset(byte viewNumber) VerificationContext[1] = null; PreparationPayloads[1] = null; PreCommitPayloads[1] = null; - CommitPayloads[1] = null; } ViewNumber = viewNumber; } From 76f4253f96ce0d55975b05a7642924ef1cc17a1a Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 21 Sep 2022 10:01:27 +0800 Subject: [PATCH 33/43] pId --- .../Consensus/ConsensusContext.Get.cs | 14 +-- .../Consensus/ConsensusContext.MakePayload.cs | 92 +++++++++---------- .../Consensus/ConsensusService.Check.cs | 60 ++++++------ .../Consensus/ConsensusService.OnMessage.cs | 56 +++++------ src/DBFTPlugin/Consensus/ConsensusService.cs | 18 ++-- 5 files changed, 120 insertions(+), 120 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 2f267446a..3203850f4 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -8,11 +8,11 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System.Linq; +using System.Runtime.CompilerServices; using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.Wallets; -using System.Linq; -using System.Runtime.CompilerServices; using static Neo.Consensus.RecoveryMessage; namespace Neo.Consensus @@ -101,18 +101,18 @@ public UInt160 GetSender(int index) /// /// Return the expected block size /// - public int GetExpectedBlockSize(uint i) + public int GetExpectedBlockSize(uint pId) { - return GetExpectedBlockSizeWithoutTransactions(Transactions[i].Count) + // Base size - Transactions[i].Values.Sum(u => u.Size); // Sum Txs + return GetExpectedBlockSizeWithoutTransactions(Transactions[pId].Count) + // Base size + Transactions[pId].Values.Sum(u => u.Size); // Sum Txs } /// /// Return the expected block system fee /// - public long GetExpectedBlockSystemFee(uint i) + public long GetExpectedBlockSystemFee(uint pId) { - return Transactions[i].Values.Sum(u => u.SystemFee); // Sum Txs + return Transactions[pId].Values.Sum(u => u.SystemFee); // Sum Txs } /// diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 51577e621..f182a28b5 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -8,14 +8,14 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.Ledger; -using Neo.Network.P2P.Payloads; -using Neo.SmartContract; -using Neo.Wallets; using System; using System.Buffers.Binary; using System.Collections.Generic; using System.Linq; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.Wallets; using static Neo.Consensus.RecoveryMessage; namespace Neo.Consensus @@ -31,12 +31,12 @@ public ExtensiblePayload MakeChangeView(ChangeViewReason reason) }); } - public ExtensiblePayload MakeCommit(uint i) + public ExtensiblePayload MakeCommit(uint pId) { - return CommitPayloads[i][MyIndex] ?? (CommitPayloads[i][MyIndex] = MakeSignedPayload(new Commit + return CommitPayloads[pId][MyIndex] ?? (CommitPayloads[pId][MyIndex] = MakeSignedPayload(new Commit { - Signature = EnsureHeader(i).Sign(keyPair, neoSystem.Settings.Network), - Id = i + Signature = EnsureHeader(pId).Sign(keyPair, neoSystem.Settings.Network), + Id = pId })); } @@ -70,16 +70,16 @@ private void SignPayload(ExtensiblePayload payload) /// Prevent that block exceed the max size /// /// Ordered transactions - internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pID) + internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pId) { uint maxTransactionsPerBlock = neoSystem.Settings.MaxTransactionsPerBlock; // Limit Speaker proposal to the limit `MaxTransactionsPerBlock` or all available transactions of the mempool txs = txs.Take((int)maxTransactionsPerBlock); - List hashes = new List(); - Transactions[pID] = new Dictionary(); - VerificationContext[pID] = new TransactionVerificationContext(); + List hashes = new(); + Transactions[pId] = new Dictionary(); + VerificationContext[pId] = new TransactionVerificationContext(); // Expected block size var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Count()); @@ -97,11 +97,11 @@ internal void EnsureMaxBlockLimitation(IEnumerable txs, uint pID) if (blockSystemFee > dbftSettings.MaxBlockSystemFee) break; hashes.Add(tx.Hash); - Transactions[pID].Add(tx.Hash, tx); - VerificationContext[pID].AddTransaction(tx); + Transactions[pId].Add(tx.Hash, tx); + VerificationContext[pId].AddTransaction(tx); } - TransactionHashes[pID] = hashes.ToArray(); + TransactionHashes[pId] = hashes.ToArray(); } internal IEnumerable PickTransactions() @@ -116,19 +116,19 @@ internal IEnumerable PickTransactions() return verifiedTxes; } - public ExtensiblePayload MakePrepareRequest(uint pID) + public ExtensiblePayload MakePrepareRequest(uint pId) { - EnsureMaxBlockLimitation(PickTransactions(), pID); - Block[pID].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); - Block[pID].Header.Nonce = GetNonce(); + EnsureMaxBlockLimitation(PickTransactions(), pId); + Block[pId].Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1); + Block[pId].Header.Nonce = GetNonce(); - return PreparationPayloads[pID][MyIndex] = MakeSignedPayload(new PrepareRequest + return PreparationPayloads[pId][MyIndex] = MakeSignedPayload(new PrepareRequest { - Version = Block[pID].Version, - PrevHash = Block[pID].PrevHash, - Timestamp = Block[pID].Timestamp, - Nonce = Block[pID].Nonce, - TransactionHashes = TransactionHashes[pID] + Version = Block[pId].Version, + PrevHash = Block[pId].PrevHash, + Timestamp = Block[pId].Timestamp, + Nonce = Block[pId].Nonce, + TransactionHashes = TransactionHashes[pId] }); } @@ -143,50 +143,50 @@ public ExtensiblePayload MakeRecoveryRequest() public ExtensiblePayload MakeRecoveryMessage() { PrepareRequest prepareRequestMessage = null; - uint pID = TransactionHashes[0] != null ? 0u : (TransactionHashes[1] != null ? 1u : 0u); - if (TransactionHashes[pID] != null) + uint pId = TransactionHashes[0] != null ? 0u : (TransactionHashes[1] != null ? 1u : 0u); + if (TransactionHashes[pId] != null) { prepareRequestMessage = new PrepareRequest { - Version = Block[pID].Version, - PrevHash = Block[pID].PrevHash, + Version = Block[pId].Version, + PrevHash = Block[pId].PrevHash, ViewNumber = ViewNumber, - Timestamp = Block[pID].Timestamp, - Nonce = Block[pID].Nonce, - BlockIndex = Block[pID].Index, - TransactionHashes = TransactionHashes[pID] + Timestamp = Block[pId].Timestamp, + Nonce = Block[pId].Nonce, + BlockIndex = Block[pId].Index, + TransactionHashes = TransactionHashes[pId] }; } return MakeSignedPayload(new RecoveryMessage { - Id = pID, + Id = pId, ChangeViewMessages = LastChangeViewPayloads.Where(p => p != null).Select(p => GetChangeViewPayloadCompact(p)).Take(M).ToDictionary(p => p.ValidatorIndex), PrepareRequestMessage = prepareRequestMessage, // We only need a PreparationHash set if we don't have the PrepareRequest information. - PreparationHash = TransactionHashes[pID] == null ? PreparationPayloads[pID].Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, - PreparationMessages = PreparationPayloads[pID].Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), - PreCommitMessages = PreCommitPayloads[pID].Where(p => p != null).Select(p => GetPreCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), + PreparationHash = TransactionHashes[pId] == null ? PreparationPayloads[pId].Where(p => p != null).GroupBy(p => GetMessage(p).PreparationHash, (k, g) => new { Hash = k, Count = g.Count() }).OrderByDescending(p => p.Count).Select(p => p.Hash).FirstOrDefault() : null, + PreparationMessages = PreparationPayloads[pId].Where(p => p != null).Select(p => GetPreparationPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), + PreCommitMessages = PreCommitPayloads[pId].Where(p => p != null).Select(p => GetPreCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex), CommitMessages = CommitSent - ? CommitPayloads[pID].Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) + ? CommitPayloads[pId].Where(p => p != null).Select(p => GetCommitPayloadCompact(p)).ToDictionary(p => p.ValidatorIndex) : new Dictionary() }); } - public ExtensiblePayload MakePrepareResponse(uint i) + public ExtensiblePayload MakePrepareResponse(uint pId) { - return PreparationPayloads[i][MyIndex] = MakeSignedPayload(new PrepareResponse + return PreparationPayloads[pId][MyIndex] = MakeSignedPayload(new PrepareResponse { - PreparationHash = PreparationPayloads[i][Block[i].PrimaryIndex].Hash, - Id = i + PreparationHash = PreparationPayloads[pId][Block[pId].PrimaryIndex].Hash, + Id = pId }); } - public ExtensiblePayload MakePreCommit(uint i) + public ExtensiblePayload MakePreCommit(uint pId) { - return PreCommitPayloads[i][MyIndex] = MakeSignedPayload(new PreCommit + return PreCommitPayloads[pId][MyIndex] = MakeSignedPayload(new PreCommit { - PreparationHash = PreparationPayloads[i][Block[i].PrimaryIndex].Hash, - Id = i + PreparationHash = PreparationPayloads[pId][Block[pId].PrimaryIndex].Hash, + Id = pId }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index 1f6fed157..a1cd34827 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -8,36 +8,36 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System; +using System.Linq; using Akka.Actor; using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; -using System; -using System.Linq; namespace Neo.Consensus { partial class ConsensusService { - private bool CheckPrepareResponse(uint i) + private bool CheckPrepareResponse(uint pId) { - if (context.TransactionHashes[i].Length == context.Transactions[i].Count) + if (context.TransactionHashes[pId].Length == context.Transactions[pId].Count) { // if we are the primary for this view, but acting as a backup because we recovered our own // previously sent prepare request, then we don't want to send a prepare response. - if ((i == 0 && context.IsPriorityPrimary) || (i == 1 && context.IsFallbackPrimary) || context.WatchOnly) return true; + if ((pId == 0 && context.IsPriorityPrimary) || (pId == 1 && context.IsFallbackPrimary) || context.WatchOnly) return true; // Check maximum block size via Native Contract policy - if (context.GetExpectedBlockSize(i) > dbftSettings.MaxBlockSize) + if (context.GetExpectedBlockSize(pId) > dbftSettings.MaxBlockSize) { - Log($"Rejected block: {context.Block[i].Index} The size exceed the policy", LogLevel.Warning); + Log($"Rejected block: {context.Block[pId].Index} The size exceed the policy", LogLevel.Warning); RequestChangeView(ChangeViewReason.BlockRejectedByPolicy); return false; } // Check maximum block system fee via Native Contract policy - if (context.GetExpectedBlockSystemFee(i) > dbftSettings.MaxBlockSystemFee) + if (context.GetExpectedBlockSystemFee(pId) > dbftSettings.MaxBlockSystemFee) { - Log($"Rejected block: {context.Block[i].Index} The system fee exceed the policy", LogLevel.Warning); + Log($"Rejected block: {context.Block[pId].Index} The system fee exceed the policy", LogLevel.Warning); RequestChangeView(ChangeViewReason.BlockRejectedByPolicy); return false; } @@ -47,34 +47,34 @@ private bool CheckPrepareResponse(uint i) ExtendTimerByFactor(2); Log($"Sending {nameof(PrepareResponse)}"); - localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareResponse(i) }); - CheckPreparations(i); + localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareResponse(pId) }); + CheckPreparations(pId); } return true; } - private void CheckPreCommits(uint i, bool forced = false) + private void CheckPreCommits(uint pId, bool forced = false) { - if (forced || context.PreCommitPayloads[i].Count(p => p != null) >= context.M && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) + if (forced || context.PreCommitPayloads[pId].Count(p => p != null) >= context.M && context.TransactionHashes[pId].All(p => context.Transactions[pId].ContainsKey(p))) { - ExtensiblePayload payload = context.MakeCommit(i); - Log($"Sending {nameof(Commit)} to pOrF={i}"); + ExtensiblePayload payload = context.MakeCommit(pId); + Log($"Sending {nameof(Commit)} to pId={pId}"); context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); - CheckCommits(i); + CheckCommits(pId); } } - private void CheckCommits(uint i) + private void CheckCommits(uint pId) { - if (context.CommitPayloads[i].Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes[i].All(p => context.Transactions[i].ContainsKey(p))) + if (context.CommitPayloads[pId].Count(p => context.GetMessage(p)?.ViewNumber == context.ViewNumber) >= context.M && context.TransactionHashes[pId].All(p => context.Transactions[pId].ContainsKey(p))) { - block_received_index = context.Block[i].Index; + block_received_index = context.Block[pId].Index; block_received_time = TimeProvider.Current.UtcNow; - Block block = context.CreateBlock(i); - Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} Id={i}"); + Block block = context.CreateBlock(pId); + Log($"Sending {nameof(Block)}: height={block.Index} hash={block.Hash} tx={block.Transactions.Length} Id={pId}"); blockchain.Tell(block); return; } @@ -99,11 +99,11 @@ private void CheckExpectedView(byte viewNumber) } } - private void CheckPreparations(uint pID) + private void CheckPreparations(uint pId) { - if (context.TransactionHashes[pID].All(p => context.Transactions[pID].ContainsKey(p))) + if (context.TransactionHashes[pId].All(p => context.Transactions[pId].ContainsKey(p))) { - var preparationsCount = context.PreparationPayloads[pID].Count(p => p != null); + var preparationsCount = context.PreparationPayloads[pId].Count(p => p != null); if (context.ViewNumber > 0) { if (preparationsCount >= context.M) @@ -111,18 +111,18 @@ private void CheckPreparations(uint pID) return; } if (!context.PreCommitSent - && ((pID == 0 && preparationsCount >= context.F + 1) - || (pID == 1 && preparationsCount >= context.M))) + && ((pId == 0 && preparationsCount >= context.F + 1) + || (pId == 1 && preparationsCount >= context.M))) { - ExtensiblePayload payload = context.MakePreCommit(pID); - Log($"Sending {nameof(PreCommit)} pOrF={pID}"); + ExtensiblePayload payload = context.MakePreCommit(pId); + Log($"Sending {nameof(PreCommit)} pId={pId}"); context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(neoSystem.Settings.MillisecondsPerBlock)); - CheckPreCommits(pID); + CheckPreCommits(pId); } - if (context.ViewNumber == 0 && pID == 0 && preparationsCount >= context.M) + if (context.ViewNumber == 0 && pId == 0 && preparationsCount >= context.M) { CheckPreCommits(0, true); } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 60a2e4fb6..3386d9e71 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -8,6 +8,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System; +using System.Collections.Generic; +using System.Linq; using Akka.Actor; using Neo.Cryptography; using Neo.IO; @@ -17,9 +20,6 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.Wallets; -using System; -using System.Collections.Generic; -using System.Linq; namespace Neo.Consensus { @@ -80,10 +80,10 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; - uint pOrF = message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber) || context.ViewNumber > 0 ? 0u : 1u; + uint pId = message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber) || context.ViewNumber > 0 ? 0u : 1u; // Add verification for Fallback - if (message.ValidatorIndex != context.Block[pOrF].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; - if (message.Version != context.Block[pOrF].Version || message.PrevHash != context.Block[pOrF].PrevHash) return; + if (message.ValidatorIndex != context.Block[pId].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; + if (message.Version != context.Block[pId].Version || message.PrevHash != context.Block[pId].PrevHash) return; if (message.TransactionHashes.Length > neoSystem.Settings.MaxTransactionsPerBlock) return; Log($"{nameof(OnPrepareRequestReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} tx={message.TransactionHashes.Length} priority={message.ValidatorIndex == context.Block[0].PrimaryIndex} fallback={context.ViewNumber == 0 && message.ValidatorIndex == context.Block[1].PrimaryIndex}"); @@ -103,35 +103,35 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); - context.Block[pOrF].Header.Timestamp = message.Timestamp; - context.Block[pOrF].Header.Nonce = message.Nonce; - context.TransactionHashes[pOrF] = message.TransactionHashes; + context.Block[pId].Header.Timestamp = message.Timestamp; + context.Block[pId].Header.Nonce = message.Nonce; + context.TransactionHashes[pId] = message.TransactionHashes; context.LastProposal = message.TransactionHashes; - context.Transactions[pOrF] = new Dictionary(); - context.VerificationContext[pOrF] = new TransactionVerificationContext(); - for (int i = 0; i < context.PreparationPayloads[pOrF].Length; i++) - if (context.PreparationPayloads[pOrF][i] != null) - if (!context.GetMessage(context.PreparationPayloads[pOrF][i]).PreparationHash.Equals(payload.Hash)) - context.PreparationPayloads[pOrF][i] = null; - context.PreparationPayloads[pOrF][message.ValidatorIndex] = payload; - byte[] hashData = context.EnsureHeader(pOrF).GetSignData(neoSystem.Settings.Network); - for (int i = 0; i < context.CommitPayloads[pOrF].Length; i++) - if (context.GetMessage(context.CommitPayloads[pOrF][i])?.ViewNumber == context.ViewNumber) - if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pOrF][i]).Signature.Span, context.Validators[i])) - context.CommitPayloads[pOrF][i] = null; + context.Transactions[pId] = new Dictionary(); + context.VerificationContext[pId] = new TransactionVerificationContext(); + for (int i = 0; i < context.PreparationPayloads[pId].Length; i++) + if (context.PreparationPayloads[pId][i] != null) + if (!context.GetMessage(context.PreparationPayloads[pId][i]).PreparationHash.Equals(payload.Hash)) + context.PreparationPayloads[pId][i] = null; + context.PreparationPayloads[pId][message.ValidatorIndex] = payload; + byte[] hashData = context.EnsureHeader(pId).GetSignData(neoSystem.Settings.Network); + for (int i = 0; i < context.CommitPayloads[pId].Length; i++) + if (context.GetMessage(context.CommitPayloads[pId][i])?.ViewNumber == context.ViewNumber) + if (!Crypto.VerifySignature(hashData, context.GetMessage(context.CommitPayloads[pId][i]).Signature.Span, context.Validators[i])) + context.CommitPayloads[pId][i] = null; - if (context.TransactionHashes[pOrF].Length == 0) + if (context.TransactionHashes[pId].Length == 0) { // There are no tx so we should act like if all the transactions were filled - CheckPrepareResponse(pOrF); + CheckPrepareResponse(pId); return; } Dictionary mempoolVerified = neoSystem.MemPool.GetVerifiedTransactions().ToDictionary(p => p.Hash); List unverified = new List(); //Cash previous asked TX Hashes - foreach (UInt256 hash in context.TransactionHashes[pOrF]) + foreach (UInt256 hash in context.TransactionHashes[pId]) { if (mempoolVerified.TryGetValue(hash, out Transaction tx)) { @@ -147,9 +147,9 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest foreach (Transaction tx in unverified) if (!AddTransaction(tx, true)) return; - if (context.Transactions[pOrF].Count < context.TransactionHashes[pOrF].Length) + if (context.Transactions[pId].Count < context.TransactionHashes[pId].Length) { - UInt256[] hashes = context.TransactionHashes[pOrF].Where(i => !context.Transactions[pOrF].ContainsKey(i)).ToArray(); + UInt256[] hashes = context.TransactionHashes[pId].Where(i => !context.Transactions[pId].ContainsKey(i)).ToArray(); taskManager.Tell(new TaskManager.RestartTasks { Payload = InvPayload.Create(InventoryType.TX, hashes) @@ -284,8 +284,8 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) } else if (context.IsAPrimary) { - uint pID = Convert.ToUInt32(!context.IsPriorityPrimary); - SendPrepareRequest(pID); + uint pId = Convert.ToUInt32(!context.IsPriorityPrimary); + SendPrepareRequest(pId); } } ExtensiblePayload[] prepareResponsePayloads = message.GetPrepareResponsePayloads(context); diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 18006bd9e..c9cfc9839 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -8,15 +8,15 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System; +using System.Collections.Generic; +using System.Linq; using Akka.Actor; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.Wallets; -using System; -using System.Collections.Generic; -using System.Linq; using static Neo.Ledger.Blockchain; namespace Neo.Consensus @@ -204,17 +204,17 @@ private void OnTimer(Timer timer) } } - private void SendPrepareRequest(uint pID) + private void SendPrepareRequest(uint pId) { - Log($"Sending {nameof(PrepareRequest)}: height={context.Block[pID].Index} view={context.ViewNumber} Id={pID}"); - localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest(pID) }); + Log($"Sending {nameof(PrepareRequest)}: height={context.Block[pId].Index} view={context.ViewNumber} Id={pId}"); + localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakePrepareRequest(pId) }); if (context.Validators.Length == 1) - CheckPreparations(pID); + CheckPreparations(pId); - if (context.TransactionHashes[pID].Length > 0) + if (context.TransactionHashes[pId].Length > 0) { - foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[pID])) + foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes[pId])) localNode.Tell(Message.Create(MessageCommand.Inv, payload)); } ChangeTimer(TimeSpan.FromMilliseconds(context.PrimaryTimerMultiplier * ((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)))); From 7009fa867314b0980ef585dd143c557eb6a63a27 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 21 Sep 2022 10:16:04 +0800 Subject: [PATCH 34/43] log --- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 3386d9e71..7b732d733 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -174,7 +174,7 @@ private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareRespons // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); - Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); + Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); context.PreparationPayloads[message.Id][message.ValidatorIndex] = payload; if (context.WatchOnly || context.CommitSent) return; if (context.RequestSentOrReceived) @@ -193,7 +193,7 @@ private void OnPreCommitReceived(ExtensiblePayload payload, PreCommit message) return; } - Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} Id={message.Id}"); + Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); context.PreCommitPayloads[message.Id][message.ValidatorIndex] = payload; if (context.WatchOnly || context.CommitSent) return; if (context.RequestSentOrReceived) @@ -222,7 +222,7 @@ private void OnCommitReceived(ExtensiblePayload payload, Commit commit) if (existingCommitPayload != null) { if (existingCommitPayload.Hash != payload.Hash) - Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber} id={commit.Id}", LogLevel.Warning); + Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber} pId={commit.Id}", LogLevel.Warning); return; } @@ -261,7 +261,7 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) int validPrepResponses = 0, totalPrepResponses = 0, validCommits = 0, totalCommits = 0; int validPreCommits = 0, totalPreCommits = 0; - Log($"{nameof(OnRecoveryMessageReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex}"); + Log($"{nameof(OnRecoveryMessageReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); try { if (message.ViewNumber > context.ViewNumber) From 6e59214080b85f98b9cde2c82aed18e602f816b1 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 21 Sep 2022 11:45:53 +0800 Subject: [PATCH 35/43] ValidatorIndex in PrepareRequest of RecoveryMessage --- src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs | 1 + src/DBFTPlugin/Consensus/ConsensusService.Check.cs | 2 +- src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs | 2 +- src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index f182a28b5..29bd2fd29 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -154,6 +154,7 @@ public ExtensiblePayload MakeRecoveryMessage() Timestamp = Block[pId].Timestamp, Nonce = Block[pId].Nonce, BlockIndex = Block[pId].Index, + ValidatorIndex = Block[pId].PrimaryIndex, TransactionHashes = TransactionHashes[pId] }; } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index a1cd34827..b73a49d1b 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -115,7 +115,7 @@ private void CheckPreparations(uint pId) || (pId == 1 && preparationsCount >= context.M))) { ExtensiblePayload payload = context.MakePreCommit(pId); - Log($"Sending {nameof(PreCommit)} pId={pId}"); + Log($"Sending {nameof(PreCommit)} to pId={pId}"); context.Save(); localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 7b732d733..98b506c40 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -80,7 +80,7 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; - uint pId = message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber) || context.ViewNumber > 0 ? 0u : 1u; + uint pId = context.ViewNumber > 0 || message.ValidatorIndex == context.GetPriorityPrimaryIndex(context.ViewNumber) ? 0u : 1u; // Add verification for Fallback if (message.ValidatorIndex != context.Block[pId].PrimaryIndex || message.ViewNumber != context.ViewNumber) return; if (message.Version != context.Block[pId].Version || message.PrevHash != context.Block[pId].PrevHash) return; diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index 4dd1a23d7..4ac9ba280 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -8,12 +8,12 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; -using Neo.Network.P2P.Payloads; using System; using System.Collections.Generic; using System.IO; using System.Linq; +using Neo.IO; +using Neo.Network.P2P.Payloads; namespace Neo.Consensus { From f9f0465b142203e66cb079a6537e1b808c11a862 Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Wed, 21 Sep 2022 09:20:58 -0300 Subject: [PATCH 36/43] Comment --- src/DBFTPlugin/Consensus/ConsensusService.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index c9cfc9839..450a61731 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -145,6 +145,7 @@ private void OnStart() started = true; if (!dbftSettings.IgnoreRecoveryLogs && context.Load()) { + // Check if any preparation was obtained and extract the primary ID var pId = context.RequestSentOrReceived ? (context.PreparationPayloads[0][context.Block[0].PrimaryIndex] != null ? 0u : 1u) : 0u; From 932489999fe2e6dff4cd78adba0f151e0a334b62 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Wed, 21 Sep 2022 20:40:16 +0800 Subject: [PATCH 37/43] name --- .../Consensus/ConsensusContext.MakePayload.cs | 8 ++--- .../Consensus/ConsensusService.OnMessage.cs | 34 +++++++++---------- src/DBFTPlugin/Messages/Commit.cs | 8 ++--- src/DBFTPlugin/Messages/PreCommit.cs | 8 ++--- src/DBFTPlugin/Messages/PrepareResponse.cs | 8 ++--- .../RecoveryMessage/RecoveryMessage.cs | 16 ++++----- 6 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index 29bd2fd29..2470b856a 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -36,7 +36,7 @@ public ExtensiblePayload MakeCommit(uint pId) return CommitPayloads[pId][MyIndex] ?? (CommitPayloads[pId][MyIndex] = MakeSignedPayload(new Commit { Signature = EnsureHeader(pId).Sign(keyPair, neoSystem.Settings.Network), - Id = pId + PId = pId })); } @@ -160,7 +160,7 @@ public ExtensiblePayload MakeRecoveryMessage() } return MakeSignedPayload(new RecoveryMessage { - Id = pId, + PId = pId, ChangeViewMessages = LastChangeViewPayloads.Where(p => p != null).Select(p => GetChangeViewPayloadCompact(p)).Take(M).ToDictionary(p => p.ValidatorIndex), PrepareRequestMessage = prepareRequestMessage, // We only need a PreparationHash set if we don't have the PrepareRequest information. @@ -178,7 +178,7 @@ public ExtensiblePayload MakePrepareResponse(uint pId) return PreparationPayloads[pId][MyIndex] = MakeSignedPayload(new PrepareResponse { PreparationHash = PreparationPayloads[pId][Block[pId].PrimaryIndex].Hash, - Id = pId + PId = pId }); } @@ -187,7 +187,7 @@ public ExtensiblePayload MakePreCommit(uint pId) return PreCommitPayloads[pId][MyIndex] = MakeSignedPayload(new PreCommit { PreparationHash = PreparationPayloads[pId][Block[pId].PrimaryIndex].Hash, - Id = pId + PId = pId }); } diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index 98b506c40..43cd3defc 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -160,12 +160,12 @@ private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareResponse message) { if (message.ViewNumber != context.ViewNumber) return; - if (context.PreparationPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; + if (context.PreparationPayloads[message.PId][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; if (context.RequestSentOrReceived) { // Check if we have joined another consensus process - if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] == null) return; - if (!message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + if (context.PreparationPayloads[message.PId][context.Block[message.PId].PrimaryIndex] == null) return; + if (!message.PreparationHash.Equals(context.PreparationPayloads[message.PId][context.Block[message.PId].PrimaryIndex].Hash)) return; } @@ -174,30 +174,30 @@ private void OnPrepareResponseReceived(ExtensiblePayload payload, PrepareRespons // around 2*15/M=30.0/5 ~ 40% block time (for M=5) ExtendTimerByFactor(2); - Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); - context.PreparationPayloads[message.Id][message.ValidatorIndex] = payload; + Log($"{nameof(OnPrepareResponseReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.PId}"); + context.PreparationPayloads[message.PId][message.ValidatorIndex] = payload; if (context.WatchOnly || context.CommitSent) return; if (context.RequestSentOrReceived) - CheckPreparations(message.Id); + CheckPreparations(message.PId); } private void OnPreCommitReceived(ExtensiblePayload payload, PreCommit message) { if (message.ViewNumber != context.ViewNumber) return; - if (context.PreCommitPayloads[message.Id][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; + if (context.PreCommitPayloads[message.PId][message.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; if (context.RequestSentOrReceived) { // Check if we have joined another consensus process - if (context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex] == null) return; - if (!message.PreparationHash.Equals(context.PreparationPayloads[message.Id][context.Block[message.Id].PrimaryIndex].Hash)) + if (context.PreparationPayloads[message.PId][context.Block[message.PId].PrimaryIndex] == null) return; + if (!message.PreparationHash.Equals(context.PreparationPayloads[message.PId][context.Block[message.PId].PrimaryIndex].Hash)) return; } - Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); - context.PreCommitPayloads[message.Id][message.ValidatorIndex] = payload; + Log($"{nameof(OnPreCommitReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.PId}"); + context.PreCommitPayloads[message.PId][message.ValidatorIndex] = payload; if (context.WatchOnly || context.CommitSent) return; if (context.RequestSentOrReceived) - CheckPreCommits(message.Id); + CheckPreCommits(message.PId); } private void OnChangeViewReceived(ExtensiblePayload payload, ChangeView message) @@ -218,11 +218,11 @@ private void OnChangeViewReceived(ExtensiblePayload payload, ChangeView message) private void OnCommitReceived(ExtensiblePayload payload, Commit commit) { - ref ExtensiblePayload existingCommitPayload = ref context.CommitPayloads[commit.Id][commit.ValidatorIndex]; + ref ExtensiblePayload existingCommitPayload = ref context.CommitPayloads[commit.PId][commit.ValidatorIndex]; if (existingCommitPayload != null) { if (existingCommitPayload.Hash != payload.Hash) - Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber} pId={commit.Id}", LogLevel.Warning); + Log($"Rejected {nameof(Commit)}: height={commit.BlockIndex} index={commit.ValidatorIndex} view={commit.ViewNumber} existingView={context.GetMessage(existingCommitPayload).ViewNumber} pId={commit.PId}", LogLevel.Warning); return; } @@ -234,7 +234,7 @@ private void OnCommitReceived(ExtensiblePayload payload, Commit commit) { Log($"{nameof(OnCommitReceived)}: height={commit.BlockIndex} view={commit.ViewNumber} index={commit.ValidatorIndex} nc={context.CountCommitted} nf={context.CountFailed}"); - byte[] hashData = context.EnsureHeader(commit.Id)?.GetSignData(neoSystem.Settings.Network); + byte[] hashData = context.EnsureHeader(commit.PId)?.GetSignData(neoSystem.Settings.Network); if (hashData == null) { existingCommitPayload = payload; @@ -242,7 +242,7 @@ private void OnCommitReceived(ExtensiblePayload payload, Commit commit) else if (Crypto.VerifySignature(hashData, commit.Signature.Span, context.Validators[commit.ValidatorIndex])) { existingCommitPayload = payload; - CheckCommits(commit.Id); + CheckCommits(commit.PId); } return; } @@ -261,7 +261,7 @@ private void OnRecoveryMessageReceived(RecoveryMessage message) int validPrepResponses = 0, totalPrepResponses = 0, validCommits = 0, totalCommits = 0; int validPreCommits = 0, totalPreCommits = 0; - Log($"{nameof(OnRecoveryMessageReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.Id}"); + Log($"{nameof(OnRecoveryMessageReceived)}: height={message.BlockIndex} view={message.ViewNumber} index={message.ValidatorIndex} pId={message.PId}"); try { if (message.ViewNumber > context.ViewNumber) diff --git a/src/DBFTPlugin/Messages/Commit.cs b/src/DBFTPlugin/Messages/Commit.cs index 8ab9270a4..62d3027db 100644 --- a/src/DBFTPlugin/Messages/Commit.cs +++ b/src/DBFTPlugin/Messages/Commit.cs @@ -8,9 +8,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using System; using System.IO; +using Neo.IO; namespace Neo.Consensus { @@ -19,7 +19,7 @@ public class Commit : ConsensusMessage public ReadOnlyMemory Signature; // priority or fallback - public uint Id; + public uint PId; public override int Size => base.Size + Signature.Length + sizeof(uint); @@ -29,14 +29,14 @@ public override void Deserialize(ref MemoryReader reader) { base.Deserialize(ref reader); Signature = reader.ReadMemory(64); - Id = reader.ReadUInt32(); + PId = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(Signature.Span); - writer.Write(Id); + writer.Write(PId); } } } diff --git a/src/DBFTPlugin/Messages/PreCommit.cs b/src/DBFTPlugin/Messages/PreCommit.cs index 48f04c477..8fbc118fe 100644 --- a/src/DBFTPlugin/Messages/PreCommit.cs +++ b/src/DBFTPlugin/Messages/PreCommit.cs @@ -1,5 +1,5 @@ -using Neo.IO; using System.IO; +using Neo.IO; namespace Neo.Consensus { @@ -8,7 +8,7 @@ public class PreCommit : ConsensusMessage public UInt256 PreparationHash; // priority or fallback - public uint Id; + public uint PId; public override int Size => base.Size + PreparationHash.Size + sizeof(uint); public PreCommit() : base(ConsensusMessageType.PreCommit) { } @@ -17,14 +17,14 @@ public override void Deserialize(ref MemoryReader reader) { base.Deserialize(ref reader); PreparationHash = reader.ReadSerializable(); - Id = reader.ReadUInt32(); + PId = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(PreparationHash); - writer.Write(Id); + writer.Write(PId); } } } diff --git a/src/DBFTPlugin/Messages/PrepareResponse.cs b/src/DBFTPlugin/Messages/PrepareResponse.cs index 2f561487e..edad3483a 100644 --- a/src/DBFTPlugin/Messages/PrepareResponse.cs +++ b/src/DBFTPlugin/Messages/PrepareResponse.cs @@ -8,9 +8,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using Neo.IO; using System; using System.IO; +using Neo.IO; namespace Neo.Consensus { @@ -19,7 +19,7 @@ public class PrepareResponse : ConsensusMessage public UInt256 PreparationHash; // priority or fallback - public uint Id; + public uint PId; public override int Size => base.Size + PreparationHash.Size + sizeof(uint); public PrepareResponse() : base(ConsensusMessageType.PrepareResponse) { } @@ -28,14 +28,14 @@ public override void Deserialize(ref MemoryReader reader) { base.Deserialize(ref reader); PreparationHash = reader.ReadSerializable(); - Id = reader.ReadUInt32(); + PId = reader.ReadUInt32(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(PreparationHash); - writer.Write(Id); + writer.Write(PId); } } } diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index 4ac9ba280..7ab162439 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -19,7 +19,7 @@ namespace Neo.Consensus { public partial class RecoveryMessage : ConsensusMessage { - public uint Id; + public uint PId; public Dictionary ChangeViewMessages; public PrepareRequest PrepareRequestMessage; /// The PreparationHash in case the PrepareRequest hasn't been received yet. @@ -41,7 +41,7 @@ public RecoveryMessage() : base(ConsensusMessageType.RecoveryMessage) { } public override void Deserialize(ref MemoryReader reader) { base.Deserialize(ref reader); - Id = reader.ReadUInt32(); + PId = reader.ReadUInt32(); ChangeViewMessages = reader.ReadSerializableArray(byte.MaxValue).ToDictionary(p => p.ValidatorIndex); if (reader.ReadBoolean()) { @@ -86,7 +86,7 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte BlockIndex = BlockIndex, ValidatorIndex = p.ValidatorIndex, ViewNumber = p.ViewNumber, - Id = Id, + PId = PId, Signature = p.Signature }, p.InvocationScript)).ToArray(); } @@ -94,21 +94,21 @@ internal ExtensiblePayload[] GetCommitPayloadsFromRecoveryMessage(ConsensusConte internal ExtensiblePayload GetPrepareRequestPayload(ConsensusContext context) { if (PrepareRequestMessage == null) return null; - if (!PreparationMessages.TryGetValue(context.Block[Id].PrimaryIndex, out PreparationPayloadCompact compact)) + if (!PreparationMessages.TryGetValue(context.Block[PId].PrimaryIndex, out PreparationPayloadCompact compact)) return null; return context.CreatePayload(PrepareRequestMessage, compact.InvocationScript); } internal ExtensiblePayload[] GetPrepareResponsePayloads(ConsensusContext context) { - UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[Id][context.Block[Id].PrimaryIndex]?.Hash; + UInt256 preparationHash = PreparationHash ?? context.PreparationPayloads[PId][context.Block[PId].PrimaryIndex]?.Hash; if (preparationHash is null) return Array.Empty(); return PreparationMessages.Values.Where(p => p.ValidatorIndex != context.Block[0].PrimaryIndex).Select(p => context.CreatePayload(new PrepareResponse { BlockIndex = BlockIndex, ValidatorIndex = p.ValidatorIndex, ViewNumber = ViewNumber, - Id = Id, + PId = PId, PreparationHash = preparationHash, }, p.InvocationScript)).ToArray(); } @@ -121,14 +121,14 @@ internal ExtensiblePayload[] GetPreCommitPayloads(ConsensusContext context) ViewNumber = p.ViewNumber, ValidatorIndex = p.ValidatorIndex, PreparationHash = p.PreparationHash, - Id = Id, + PId = PId, }, p.InvocationScript)).ToArray(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); - writer.Write(Id); + writer.Write(PId); writer.Write(ChangeViewMessages.Values.ToArray()); bool hasPrepareRequestMessage = PrepareRequestMessage != null; writer.Write(hasPrepareRequestMessage); From a91dd6339cc6593a2e841d92ed149f8e52f850a9 Mon Sep 17 00:00:00 2001 From: ZhangTao1596 Date: Sat, 8 Oct 2022 17:36:35 +0800 Subject: [PATCH 38/43] fix fallback primary index --- src/DBFTPlugin/Consensus/ConsensusContext.Get.cs | 4 ++-- src/DBFTPlugin/Consensus/ConsensusContext.cs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 3203850f4..a56355699 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -85,10 +85,10 @@ public byte GetPriorityPrimaryIndex(byte viewNumber) } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public byte GetFallbackPrimaryIndex(byte viewNumber, byte priorityPrimaryIndex) + public byte GetFallbackPrimaryIndex(byte priorityPrimaryIndex) { if (Validators.Length <= 1) return priorityPrimaryIndex; - int p = ((int)Block[0].Index - viewNumber + 1) % (Validators.Length - 1); + int p = ((int)Block[0].Index + 1) % (Validators.Length - 1); p = p >= 0 ? (byte)p : (byte)(p + Validators.Length); return p < priorityPrimaryIndex ? (byte)p : (byte)(p + 1); } diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index 61f08c0eb..047d51dbe 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -8,6 +8,10 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; @@ -18,10 +22,6 @@ using Neo.SmartContract.Native; using Neo.VM; using Neo.Wallets; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; namespace Neo.Consensus { @@ -272,7 +272,7 @@ public void Reset(byte viewNumber) if (MyIndex >= 0) LastSeenMessage[Validators[MyIndex]] = Block[pID].Index; } Block[0].Header.PrimaryIndex = GetPriorityPrimaryIndex(viewNumber); - Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(viewNumber, Block[0].Header.PrimaryIndex); + Block[1].Header.PrimaryIndex = GetFallbackPrimaryIndex(Block[0].Header.PrimaryIndex); } else { From 0c7b5eba7b0a806ad9f723d6c47f8d5c201205d8 Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Wed, 14 Dec 2022 08:24:12 -0300 Subject: [PATCH 39/43] Fix Null with basic logic following Owen finding --- src/DBFTPlugin/Consensus/ConsensusService.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 5d2fc8f11..6c8525b7a 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -260,8 +260,16 @@ private void OnTransaction(Transaction transaction) { if (!context.IsBackup || context.NotAcceptingPayloadsDueToViewChanging || !context.RequestSentOrReceived || context.ResponseSent || context.BlockSent) return; - if (context.Transactions[0].ContainsKey(transaction.Hash) || context.Transactions[1].ContainsKey(transaction.Hash)) return; - if (!context.TransactionHashes[0].Contains(transaction.Hash) && !context.TransactionHashes[1].Contains(transaction.Hash)) return; + + for (uint i = 0; i <= 1; i++) + if (context.Transactions[i] is not null && context.Transactions[i].ContainsKey(transaction.Hash)) + return; + + bool hashNotRequestedByPrimary = context.TransactionHashes[0] is not null && !context.TransactionHashes[0].Contains(transaction.Hash); + bool hashNotRequestedByBackup = context.TransactionHashes[1] is not null && !context.TransactionHashes[1].Contains(transaction.Hash); + + if (hashNotRequestedByPrimary && hashNotRequestedByBackup) return; + AddTransaction(transaction, true); } From a2df166c0680734e26d52972f4f94977b9616380 Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Wed, 14 Dec 2022 08:42:39 -0300 Subject: [PATCH 40/43] Format --- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 6c8525b7a..b88b223a3 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -260,7 +260,7 @@ private void OnTransaction(Transaction transaction) { if (!context.IsBackup || context.NotAcceptingPayloadsDueToViewChanging || !context.RequestSentOrReceived || context.ResponseSent || context.BlockSent) return; - + for (uint i = 0; i <= 1; i++) if (context.Transactions[i] is not null && context.Transactions[i].ContainsKey(transaction.Hash)) return; From 44c5d7c17e2505b41b36e560330c36b1927cb83f Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Tue, 10 Oct 2023 09:04:56 -0300 Subject: [PATCH 41/43] format --- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index e8fd9f7e4..2c061dcce 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -272,7 +272,7 @@ private void OnTransaction(Transaction transaction) AddTransaction(transaction, true); } - + private bool AddTransaction(Transaction tx, bool verify) { bool returnValue = false; From b13b6c469e9dd5f44313d2794557604de1de63af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?= Date: Thu, 19 Oct 2023 08:35:23 -0300 Subject: [PATCH 42/43] Update ConsensusService.cs --- src/DBFTPlugin/Consensus/ConsensusService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 2c061dcce..970ca234f 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -312,7 +312,7 @@ private bool AddTransaction(Transaction tx, bool verify) // We've ensured that there's no conlicting transactions in the context, thus, can safely provide an empty conflicting list // for futher verification. var conflictingTxs = new List(); - result = tx.Verify(neoSystem.Settings, context.Snapshot, context.VerificationContext, conflictingTxs); + result = tx.Verify(neoSystem.Settings, context.Snapshot, context.VerificationContext[i], conflictingTxs); if (result != VerifyResult.Succeed) { Log($"Rejected tx: {tx.Hash}, {result}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning); From 8b493f2dd21981510a49dfaea15a6f0f2de12c29 Mon Sep 17 00:00:00 2001 From: Vitor Nazario Coelho Date: Tue, 12 Mar 2024 11:50:27 -0300 Subject: [PATCH 43/43] dotnet format --- src/DBFTPlugin/Consensus/ConsensusContext.Get.cs | 4 ++-- .../Consensus/ConsensusContext.MakePayload.cs | 8 ++++---- src/DBFTPlugin/Consensus/ConsensusContext.cs | 8 ++++---- src/DBFTPlugin/Consensus/ConsensusService.Check.cs | 4 ++-- .../Consensus/ConsensusService.OnMessage.cs | 6 +++--- src/DBFTPlugin/Consensus/ConsensusService.cs | 6 +++--- src/DBFTPlugin/Messages/Commit.cs | 2 +- src/DBFTPlugin/Messages/PreCommit.cs | 13 ++++++++++++- src/DBFTPlugin/Messages/PrepareResponse.cs | 2 +- .../RecoveryMessage.PreCommitPayloadCompact.cs | 9 +++++---- .../Messages/RecoveryMessage/RecoveryMessage.cs | 4 ++-- 11 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs index 4fe1be89d..ef3e96f13 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.Get.cs @@ -9,11 +9,11 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System.Linq; -using System.Runtime.CompilerServices; using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.Wallets; +using System.Linq; +using System.Runtime.CompilerServices; using static Neo.Consensus.RecoveryMessage; namespace Neo.Consensus diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs index e02628fa5..442084310 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs @@ -9,14 +9,14 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System; -using System.Buffers.Binary; -using System.Collections.Generic; -using System.Linq; using Neo.Ledger; using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.Wallets; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Linq; using static Neo.Consensus.RecoveryMessage; namespace Neo.Consensus diff --git a/src/DBFTPlugin/Consensus/ConsensusContext.cs b/src/DBFTPlugin/Consensus/ConsensusContext.cs index e34588f3c..167b007d7 100644 --- a/src/DBFTPlugin/Consensus/ConsensusContext.cs +++ b/src/DBFTPlugin/Consensus/ConsensusContext.cs @@ -9,10 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using Neo.Cryptography; using Neo.Cryptography.ECC; using Neo.IO; @@ -23,6 +19,10 @@ using Neo.SmartContract.Native; using Neo.VM; using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs index 17b2c8956..29bc97919 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.Check.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.Check.cs @@ -9,12 +9,12 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System; -using System.Linq; using Akka.Actor; using Neo.IO; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using System; +using System.Linq; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index f5a33ec5f..d19b44e45 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -9,9 +9,6 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System; -using System.Collections.Generic; -using System.Linq; using Akka.Actor; using Neo.Cryptography; using Neo.IO; @@ -21,6 +18,9 @@ using Neo.SmartContract; using Neo.SmartContract.Native; using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Consensus/ConsensusService.cs b/src/DBFTPlugin/Consensus/ConsensusService.cs index 733e9f1a0..d5f7e72c2 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.cs @@ -9,15 +9,15 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. -using System; -using System.Collections.Generic; -using System.Linq; using Akka.Actor; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.Wallets; +using System; +using System.Collections.Generic; +using System.Linq; using static Neo.Ledger.Blockchain; namespace Neo.Consensus diff --git a/src/DBFTPlugin/Messages/Commit.cs b/src/DBFTPlugin/Messages/Commit.cs index 850546aa9..a0104f4ad 100644 --- a/src/DBFTPlugin/Messages/Commit.cs +++ b/src/DBFTPlugin/Messages/Commit.cs @@ -9,9 +9,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using System; using System.IO; -using Neo.IO; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Messages/PreCommit.cs b/src/DBFTPlugin/Messages/PreCommit.cs index 8fbc118fe..190c123d8 100644 --- a/src/DBFTPlugin/Messages/PreCommit.cs +++ b/src/DBFTPlugin/Messages/PreCommit.cs @@ -1,5 +1,16 @@ -using System.IO; +// Copyright (C) 2015-2024 The Neo Project. +// +// PreCommit.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + using Neo.IO; +using System.IO; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Messages/PrepareResponse.cs b/src/DBFTPlugin/Messages/PrepareResponse.cs index 1cce8d308..a7410d8e7 100644 --- a/src/DBFTPlugin/Messages/PrepareResponse.cs +++ b/src/DBFTPlugin/Messages/PrepareResponse.cs @@ -9,9 +9,9 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; using System; using System.IO; -using Neo.IO; namespace Neo.Consensus { diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs index e5b596178..65b90d61f 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.PreCommitPayloadCompact.cs @@ -1,8 +1,9 @@ -// Copyright (C) 2015-2022 The Neo Project. +// Copyright (C) 2015-2024 The Neo Project. // -// The Neo.Consensus.DBFT is free software distributed under the MIT software license, -// see the accompanying file LICENSE in the main directory of the -// project or http://www.opensource.org/licenses/mit-license.php +// RecoveryMessage.PreCommitPayloadCompact.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php // for more details. // // Redistribution and use in source and binary forms with or without diff --git a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs index 3013173fb..0c75866f8 100644 --- a/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs +++ b/src/DBFTPlugin/Messages/RecoveryMessage/RecoveryMessage.cs @@ -9,12 +9,12 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Neo.IO; +using Neo.Network.P2P.Payloads; using System; using System.Collections.Generic; using System.IO; using System.Linq; -using Neo.IO; -using Neo.Network.P2P.Payloads; namespace Neo.Consensus {