diff --git a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs index cac84a8d4..82f9d7514 100644 --- a/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs +++ b/src/DBFTPlugin/Consensus/ConsensusService.OnMessage.cs @@ -10,15 +10,14 @@ using Akka.Actor; using Neo.Cryptography; -using Neo.IO; using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.SmartContract; using Neo.SmartContract.Native; -using Neo.Wallets; using System; using System.Collections.Generic; +using System.IO; using System.Linq; namespace Neo.Consensus @@ -76,6 +75,12 @@ private void OnConsensusPayload(ExtensiblePayload payload) private void OnPrepareRequestReceived(ExtensiblePayload payload, PrepareRequest message) { + if (!File.Exists("prestatehash") || File.ReadAllText("prestatehash") != message.PreStateHash.ToString()) + { + Log($"Invalid request: previous state hash does not match", LogLevel.Warning); + return; + } + if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return; if (message.ValidatorIndex != context.Block.PrimaryIndex || message.ViewNumber != context.ViewNumber) return; if (message.Version != context.Block.Version || message.PrevHash != context.Block.PrevHash) return; diff --git a/src/DBFTPlugin/DBFTPlugin.cs b/src/DBFTPlugin/DBFTPlugin.cs index 1a332fb9b..2a99b0e59 100644 --- a/src/DBFTPlugin/DBFTPlugin.cs +++ b/src/DBFTPlugin/DBFTPlugin.cs @@ -8,10 +8,17 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using System.Collections.Generic; +using System; +using System.IO; +using System.Security.Cryptography; using Akka.Actor; using Neo.ConsoleService; +using System.Text.Json; +using Neo.Ledger; using Neo.Network.P2P; using Neo.Network.P2P.Payloads; +using Neo.Persistence; using Neo.Plugins; using Neo.Wallets; @@ -30,6 +37,7 @@ public class DBFTPlugin : Plugin public DBFTPlugin() { RemoteNode.MessageReceived += RemoteNode_MessageReceived; + Blockchain.Committing += OnCommitting; } public DBFTPlugin(Settings settings) : this() @@ -96,5 +104,18 @@ private bool RemoteNode_MessageReceived(NeoSystem system, Message message) } return true; } + + private static void OnCommitting(NeoSystem system, Block block, DataCache snapshot, IReadOnlyList applicationExecutedList) + { + var serializedData = JsonSerializer.SerializeToUtf8Bytes(applicationExecutedList); + var hash = ComputeSha256Hash(serializedData); + File.WriteAllText("prestatehash", hash); + } + + private static string ComputeSha256Hash(byte[] rawData) + { + var bytes = SHA256.HashData(rawData); + return BitConverter.ToString(bytes).Replace("-", "").ToLower(); + } } } diff --git a/src/DBFTPlugin/Messages/PrepareRequest.cs b/src/DBFTPlugin/Messages/PrepareRequest.cs index 2a5516465..248cd31e0 100644 --- a/src/DBFTPlugin/Messages/PrepareRequest.cs +++ b/src/DBFTPlugin/Messages/PrepareRequest.cs @@ -19,6 +19,9 @@ public class PrepareRequest : ConsensusMessage { public uint Version; public UInt256 PrevHash; + // The execution result hash of the previous block transactions + // since we do not need to update it or search it, no merkel tree is needed + public UInt256 PreStateHash; public ulong Timestamp; public ulong Nonce; public UInt256[] TransactionHashes; @@ -26,6 +29,7 @@ public class PrepareRequest : ConsensusMessage public override int Size => base.Size + sizeof(uint) //Version + UInt256.Length //PrevHash + + UInt256.Length //PreStateHash + sizeof(ulong) //Timestamp + sizeof(ulong) // Nonce + TransactionHashes.GetVarSize(); //TransactionHashes @@ -37,6 +41,7 @@ public override void Deserialize(ref MemoryReader reader) base.Deserialize(ref reader); Version = reader.ReadUInt32(); PrevHash = reader.ReadSerializable(); + PreStateHash = reader.ReadSerializable(); Timestamp = reader.ReadUInt64(); Nonce = reader.ReadUInt64(); TransactionHashes = reader.ReadSerializableArray(ushort.MaxValue); @@ -55,6 +60,7 @@ public override void Serialize(BinaryWriter writer) base.Serialize(writer); writer.Write(Version); writer.Write(PrevHash); + writer.Write(PreStateHash); writer.Write(Timestamp); writer.Write(Nonce); writer.Write(TransactionHashes);