From 76703430f2a1e3f9b75fda46d23362b46da7d1b6 Mon Sep 17 00:00:00 2001 From: ZhangTao Date: Mon, 13 Jul 2020 18:49:50 +0800 Subject: [PATCH] [neox] consensus (#1719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * don't use snapshot directly in plugin * recover * consensus state root * fix build error * rename * remerge * rm GetMessage * rename * throw exception when no script hash in state root * Clean double enter * Clean big line * format * put root sig into request and response * update consensus ut * Check Json.Serialize map keys (#1705) * don't use snapshot directly in plugin * recover * consensus state root * fix build error * rename * remerge * rm GetMessage * rename * throw exception when no script hash in state root * Clean double enter * Clean big line * format * put root sig into request and response * update consensus ut * fix some * fix some * format * comment * fix * requst in recovery * StateRootSignature fixed size * no need ? * format * Update ConsensusContext.cs * Check sc.Complete Co-authored-by: Shargon --- src/neo/Consensus/ConsensusContext.cs | 50 +++++-- src/neo/Consensus/ConsensusService.cs | 16 +++ src/neo/Consensus/PrepareRequest.cs | 8 +- src/neo/Consensus/PrepareResponse.cs | 5 +- ...coveryMessage.PreparationPayloadCompact.cs | 17 ++- src/neo/Consensus/RecoveryMessage.cs | 3 +- src/neo/Ledger/Blockchain.state.cs | 12 ++ src/neo/Network/P2P/Payloads/StateRoot.cs | 8 +- tests/neo.UnitTests/Consensus/UT_Consensus.cs | 128 +++++++++++++----- 9 files changed, 192 insertions(+), 55 deletions(-) create mode 100644 src/neo/Ledger/Blockchain.state.cs diff --git a/src/neo/Consensus/ConsensusContext.cs b/src/neo/Consensus/ConsensusContext.cs index 3d3a4fcb5d4..c234220a1cd 100644 --- a/src/neo/Consensus/ConsensusContext.cs +++ b/src/neo/Consensus/ConsensusContext.cs @@ -24,6 +24,7 @@ internal class ConsensusContext : IDisposable, ISerializable private const byte ConsensusStatePrefix = 0xf4; public Block Block; + public StateRoot PreviousBlockStateRoot; public byte ViewNumber; public ECPoint[] Validators; public int MyIndex; @@ -91,11 +92,31 @@ public Block CreateBlock() sc.AddSignature(contract, Validators[i], CommitPayloads[i].GetDeserializedMessage().Signature); j++; } + if (!sc.Completed) throw new Exception("There are not enough signatures for sign the Block."); Block.Witness = sc.GetWitnesses()[0]; Block.Transactions = TransactionHashes.Select(p => Transactions[p]).ToArray(); return Block; } + public StateRoot CreateStateRoot() + { + EnsureHeader(); + Contract contract = Contract.CreateMultiSigContract(M, Validators); + ContractParametersContext sc = new ContractParametersContext(PreviousBlockStateRoot); + for (int i = 0, j = 0; i < Validators.Length && j < M; i++) + { + if (PreparationPayloads[i]?.ConsensusMessage.ViewNumber != ViewNumber) continue; + if (i == GetPrimaryIndex(ViewNumber)) + sc.AddSignature(contract, Validators[i], PreparationPayloads[i].GetDeserializedMessage().StateRootSignature); + else + sc.AddSignature(contract, Validators[i], PreparationPayloads[i].GetDeserializedMessage().StateRootSignature); + j++; + } + if (!sc.Completed) throw new Exception("There are not enough signatures for sign the state root."); + PreviousBlockStateRoot.Witness = sc.GetWitnesses()[0]; + return PreviousBlockStateRoot; + } + public void Deserialize(BinaryReader reader) { Reset(0); @@ -137,6 +158,20 @@ public Block EnsureHeader() return Block; } + public StateRoot EnsureStateRoot() + { + if (PreviousBlockStateRoot is null) + { + PreviousBlockStateRoot = new StateRoot + { + Version = 0, + Index = Block.Index - 1, + RootHash = Blockchain.Singleton.GetLocalStateRoot(Block.Index - 1) + }; + } + return PreviousBlockStateRoot; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint GetPrimaryIndex(byte viewNumber) { @@ -304,7 +339,8 @@ public ConsensusPayload MakePrepareRequest() { Timestamp = Block.Timestamp, Nonce = Block.ConsensusData.Nonce, - TransactionHashes = TransactionHashes + TransactionHashes = TransactionHashes, + StateRootSignature = EnsureStateRoot().Sign(keyPair) }); } @@ -321,13 +357,7 @@ public ConsensusPayload MakeRecoveryMessage() PrepareRequest prepareRequestMessage = null; if (TransactionHashes != null) { - prepareRequestMessage = new PrepareRequest - { - ViewNumber = ViewNumber, - Timestamp = Block.Timestamp, - Nonce = Block.ConsensusData.Nonce, - TransactionHashes = TransactionHashes - }; + prepareRequestMessage = PreparationPayloads[GetPrimaryIndex(ViewNumber)].GetDeserializedMessage(); } return MakeSignedPayload(new RecoveryMessage() { @@ -346,7 +376,8 @@ public ConsensusPayload MakePrepareResponse() { return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareResponse { - PreparationHash = PreparationPayloads[Block.ConsensusData.PrimaryIndex].Hash + PreparationHash = PreparationPayloads[Block.ConsensusData.PrimaryIndex].Hash, + StateRootSignature = EnsureStateRoot().Sign(keyPair) }); } @@ -399,6 +430,7 @@ public void Reset(byte viewNumber) keyPair = account.GetKey(); break; } + PreviousBlockStateRoot = null; } else { diff --git a/src/neo/Consensus/ConsensusService.cs b/src/neo/Consensus/ConsensusService.cs index 26648c4429c..405dcc429ea 100644 --- a/src/neo/Consensus/ConsensusService.cs +++ b/src/neo/Consensus/ConsensusService.cs @@ -165,6 +165,10 @@ private void CheckPreparations() localNode.Tell(new LocalNode.SendDirectly { Inventory = payload }); // Set timer, so we will resend the commit in case of a networking issue ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock)); + + StateRoot stateRoot = context.CreateStateRoot(); + Log($"relay state root, index={stateRoot.Index}, root_hash={stateRoot.RootHash}"); + blockchain.Tell(stateRoot); CheckCommits(); } } @@ -424,6 +428,12 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m Log($"Invalid request: transaction already exists", LogLevel.Warning); return; } + var stateRootHashData = context.EnsureStateRoot().GetHashData(); + if (!Crypto.VerifySignature(stateRootHashData, message.StateRootSignature, context.Validators[payload.ValidatorIndex])) + { + Log($"Invalid request: invalid state root signature", LogLevel.Warning); + return; + } // Timeout extension: prepare request has been received with success // around 2*15/M=30.0/5 ~ 40% block time (for M=5) @@ -486,6 +496,12 @@ private void OnPrepareResponseReceived(ConsensusPayload payload, PrepareResponse if (context.PreparationPayloads[payload.ValidatorIndex] != null || context.NotAcceptingPayloadsDueToViewChanging) return; if (context.PreparationPayloads[context.Block.ConsensusData.PrimaryIndex] != null && !message.PreparationHash.Equals(context.PreparationPayloads[context.Block.ConsensusData.PrimaryIndex].Hash)) return; + byte[] stateRootHashData = context.EnsureStateRoot().GetHashData(); + if (!Crypto.VerifySignature(stateRootHashData, message.StateRootSignature, context.Validators[payload.ValidatorIndex])) + { + Log($"Invalid response: invalid state root signature, height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex}", LogLevel.Warning); + return; + } // Timeout extension: prepare response has been received with success // around 2*15/M=30.0/5 ~ 40% block time (for M=5) diff --git a/src/neo/Consensus/PrepareRequest.cs b/src/neo/Consensus/PrepareRequest.cs index 2369b4f9f7a..659c5ff7954 100644 --- a/src/neo/Consensus/PrepareRequest.cs +++ b/src/neo/Consensus/PrepareRequest.cs @@ -11,11 +11,13 @@ public class PrepareRequest : ConsensusMessage public ulong Timestamp; public ulong Nonce; public UInt256[] TransactionHashes; + public byte[] StateRootSignature; public override int Size => base.Size - + sizeof(ulong) //Timestamp + + sizeof(ulong) //Timestamp + sizeof(ulong) //Nonce - + TransactionHashes.GetVarSize(); //TransactionHashes + + TransactionHashes.GetVarSize() //TransactionHashes + + StateRootSignature.Length; //StateRootSignature public PrepareRequest() : base(ConsensusMessageType.PrepareRequest) @@ -30,6 +32,7 @@ public override void Deserialize(BinaryReader reader) TransactionHashes = reader.ReadSerializableArray(Block.MaxTransactionsPerBlock); if (TransactionHashes.Distinct().Count() != TransactionHashes.Length) throw new FormatException(); + StateRootSignature = reader.ReadFixedBytes(64); } public override void Serialize(BinaryWriter writer) @@ -38,6 +41,7 @@ public override void Serialize(BinaryWriter writer) writer.Write(Timestamp); writer.Write(Nonce); writer.Write(TransactionHashes); + writer.Write(StateRootSignature); } } } diff --git a/src/neo/Consensus/PrepareResponse.cs b/src/neo/Consensus/PrepareResponse.cs index 7c2956ccc25..b1628650f6e 100644 --- a/src/neo/Consensus/PrepareResponse.cs +++ b/src/neo/Consensus/PrepareResponse.cs @@ -6,8 +6,9 @@ namespace Neo.Consensus public class PrepareResponse : ConsensusMessage { public UInt256 PreparationHash; + public byte[] StateRootSignature; - public override int Size => base.Size + PreparationHash.Size; + public override int Size => base.Size + PreparationHash.Size + StateRootSignature.Length; public PrepareResponse() : base(ConsensusMessageType.PrepareResponse) @@ -18,12 +19,14 @@ public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); PreparationHash = reader.ReadSerializable(); + StateRootSignature = reader.ReadFixedBytes(64); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); writer.Write(PreparationHash); + writer.Write(StateRootSignature); } } } diff --git a/src/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs b/src/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs index 962ae691850..ceac4563fc5 100644 --- a/src/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs +++ b/src/neo/Consensus/RecoveryMessage.PreparationPayloadCompact.cs @@ -1,5 +1,6 @@ using Neo.IO; using Neo.Network.P2P.Payloads; +using System; using System.IO; namespace Neo.Consensus @@ -10,23 +11,32 @@ public class PreparationPayloadCompact : ISerializable { public ushort ValidatorIndex; public byte[] InvocationScript; + public byte[] StateRootSignature; int ISerializable.Size => - sizeof(ushort) + //ValidatorIndex - InvocationScript.GetVarSize(); //InvocationScript + sizeof(ushort) + //ValidatorIndex + InvocationScript.GetVarSize() + //InvocationScript + StateRootSignature.Length; //StateRootSignature void ISerializable.Deserialize(BinaryReader reader) { ValidatorIndex = reader.ReadUInt16(); InvocationScript = reader.ReadVarBytes(1024); + StateRootSignature = reader.ReadFixedBytes(64); } public static PreparationPayloadCompact FromPayload(ConsensusPayload payload) { + byte[] state_root_sig = Array.Empty(); + if (payload.ConsensusMessage is PrepareResponse req) + state_root_sig = req.StateRootSignature; + else if (payload.ConsensusMessage is PrepareResponse resp) + state_root_sig = resp.StateRootSignature; return new PreparationPayloadCompact { ValidatorIndex = payload.ValidatorIndex, - InvocationScript = payload.Witness.InvocationScript + InvocationScript = payload.Witness.InvocationScript, + StateRootSignature = state_root_sig }; } @@ -34,6 +44,7 @@ void ISerializable.Serialize(BinaryWriter writer) { writer.Write(ValidatorIndex); writer.WriteVarBytes(InvocationScript); + writer.Write(StateRootSignature); } } } diff --git a/src/neo/Consensus/RecoveryMessage.cs b/src/neo/Consensus/RecoveryMessage.cs index cadb137b808..9a0aabf94a6 100644 --- a/src/neo/Consensus/RecoveryMessage.cs +++ b/src/neo/Consensus/RecoveryMessage.cs @@ -120,7 +120,8 @@ internal ConsensusPayload[] GetPrepareResponsePayloads(ConsensusContext context, ConsensusMessage = new PrepareResponse { ViewNumber = ViewNumber, - PreparationHash = preparationHash + PreparationHash = preparationHash, + StateRootSignature = p.StateRootSignature }, Witness = new Witness { diff --git a/src/neo/Ledger/Blockchain.state.cs b/src/neo/Ledger/Blockchain.state.cs new file mode 100644 index 00000000000..9c1a7eb4793 --- /dev/null +++ b/src/neo/Ledger/Blockchain.state.cs @@ -0,0 +1,12 @@ +using Akka.Actor; + +namespace Neo.Ledger +{ + public sealed partial class Blockchain : UntypedActor + { + public UInt256 GetLocalStateRoot(uint index) + { + return UInt256.Zero; + } + } +} diff --git a/src/neo/Network/P2P/Payloads/StateRoot.cs b/src/neo/Network/P2P/Payloads/StateRoot.cs index e6da3b7e9ea..dd2bcba374e 100644 --- a/src/neo/Network/P2P/Payloads/StateRoot.cs +++ b/src/neo/Network/P2P/Payloads/StateRoot.cs @@ -47,10 +47,10 @@ Witness[] IVerifiable.Witnesses } public int Size => - sizeof(byte) + //Version - sizeof(uint) + //Index - UInt256.Length + //Root - Witness.Size; //Witness + sizeof(byte) + //Version + sizeof(uint) + //Index + UInt256.Length + //RootHash + Witness.Size; //Witness StateRoot ICloneable.Clone() { diff --git a/tests/neo.UnitTests/Consensus/UT_Consensus.cs b/tests/neo.UnitTests/Consensus/UT_Consensus.cs index f99f7ba8ac6..f6adb37f80e 100644 --- a/tests/neo.UnitTests/Consensus/UT_Consensus.cs +++ b/tests/neo.UnitTests/Consensus/UT_Consensus.cs @@ -183,6 +183,7 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm // Forcing hashes to 0 because mempool is currently shared ppToSend.TransactionHashes = new UInt256[0]; ppToSend.TransactionHashes.Length.Should().Be(0); + prepReq.Data = ppToSend.ToArray(); Console.WriteLine($"\nAsserting PreparationPayloads is 1 (After MakePrepareRequest)..."); mockContext.Object.PreparationPayloads.Count(p => p != null).Should().Be(1); mockContext.Object.PreparationPayloads[prepReq.ValidatorIndex] = null; @@ -199,9 +200,27 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm mockContext.Object.CountFailed.Should().Be(6); Console.WriteLine("\nFailed because it is not primary and it created the prereq...Time to adjust"); - prepReq.ValidatorIndex = 1; //simulating primary as prepreq creator (signature is skip, no problem) + var stateRootData = mockContext.Object.EnsureStateRoot().GetHashData(); + prepReq = GetPrepareRequestAndSignStateRoot(prepReq, 1, kp_array[1], stateRootData); + //prepReq.ValidatorIndex = 1; //simulating primary as prepreq creator (signature is skip, no problem) // cleaning old try with Self ValidatorIndex mockContext.Object.PreparationPayloads[mockContext.Object.MyIndex] = null; + for (int i = 0; i < mockContext.Object.Validators.Length; i++) + Console.WriteLine($"{mockContext.Object.Validators[i]}/{Contract.CreateSignatureContract(mockContext.Object.Validators[i]).ScriptHash}"); + mockContext.Object.Validators = new ECPoint[7] + { + kp_array[0].PublicKey, + kp_array[1].PublicKey, + kp_array[2].PublicKey, + kp_array[3].PublicKey, + kp_array[4].PublicKey, + kp_array[5].PublicKey, + kp_array[6].PublicKey + }; + mockContext.Object.GetPrimaryIndex(mockContext.Object.ViewNumber).Should().Be(1); + mockContext.Object.MyIndex.Should().Be(0); + Console.WriteLine($"\nAsserting tx count is 0..."); + prepReq.GetDeserializedMessage().TransactionHashes.Count().Should().Be(0); TellConsensusPayload(actorConsensus, prepReq); var OnPrepResponse = subscriber.ExpectMsg(); @@ -212,9 +231,13 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm mockContext.Object.PreparationPayloads.Count(p => p != null).Should().Be(2); Console.WriteLine($"\nAsserting CountFailed is 5..."); mockContext.Object.CountFailed.Should().Be(5); + Console.WriteLine("\nAsserting PrepareResponse ValidatorIndex is 0..."); + prepResponsePayload.ValidatorIndex.Should().Be(0); + // Using correct signed response to replace prepareresponse sent + mockContext.Object.PreparationPayloads[prepResponsePayload.ValidatorIndex] = GetPrepareResponsePayloadAndSignStateRoot(prepResponsePayload, 0, kp_array[0], stateRootData); // Simulating CN 3 - TellConsensusPayload(actorConsensus, GetPayloadAndModifyValidator(prepResponsePayload, 2)); + TellConsensusPayload(actorConsensus, GetPrepareResponsePayloadAndSignStateRoot(prepResponsePayload, 2, kp_array[2], stateRootData)); //Waiting for RecoveryRequest for a more deterministic UT backupOnRecoveryDueToFailedNodes = subscriber.ExpectMsg(); recoveryPayload = (ConsensusPayload)backupOnRecoveryDueToFailedNodes.Inventory; @@ -227,7 +250,7 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm mockContext.Object.CountFailed.Should().Be(4); // Simulating CN 5 - TellConsensusPayload(actorConsensus, GetPayloadAndModifyValidator(prepResponsePayload, 4)); + TellConsensusPayload(actorConsensus, GetPrepareResponsePayloadAndSignStateRoot(prepResponsePayload, 4, kp_array[4], stateRootData)); //Waiting for RecoveryRequest for a more deterministic UT backupOnRecoveryDueToFailedNodes = subscriber.ExpectMsg(); recoveryPayload = (ConsensusPayload)backupOnRecoveryDueToFailedNodes.Inventory; @@ -238,10 +261,20 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm mockContext.Object.PreparationPayloads.Count(p => p != null).Should().Be(4); Console.WriteLine($"\nAsserting CountFailed is 3..."); mockContext.Object.CountFailed.Should().Be(3); + var updatedContract = Contract.CreateMultiSigContract(mockContext.Object.M, mockContext.Object.Validators); + // Mock StateRoot to use mock Validators to sign + var root = mockContext.Object.EnsureStateRoot(); + var mockRoot = new Mock(); + mockRoot.Object.Version = root.Version; + mockRoot.Object.Index = root.Index; + mockRoot.Object.RootHash = root.RootHash; + mockRoot.Setup(p => p.GetScriptHashesForVerifying(It.IsAny())).Returns(p => new UInt160[] { updatedContract.ScriptHash }); + mockContext.Object.PreviousBlockStateRoot = mockRoot.Object; // Simulating CN 4 - TellConsensusPayload(actorConsensus, GetPayloadAndModifyValidator(prepResponsePayload, 3)); + TellConsensusPayload(actorConsensus, GetPrepareResponsePayloadAndSignStateRoot(prepResponsePayload, 3, kp_array[3], stateRootData)); var onCommitPayload = subscriber.ExpectMsg(); + var onStateRoot = subscriber.ExpectMsg(); var commitPayload = (ConsensusPayload)onCommitPayload.Inventory; Commit cm = (Commit)commitPayload.ConsensusMessage; Console.WriteLine("\nAsserting PreparationPayloads count is 5..."); @@ -254,22 +287,9 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm Console.WriteLine($"ORIGINAL BlockHash: {mockContext.Object.Block.Hash}"); Console.WriteLine($"ORIGINAL Block NextConsensus: {mockContext.Object.Block.NextConsensus}"); - for (int i = 0; i < mockContext.Object.Validators.Length; i++) - Console.WriteLine($"{mockContext.Object.Validators[i]}/{Contract.CreateSignatureContract(mockContext.Object.Validators[i]).ScriptHash}"); - mockContext.Object.Validators = new ECPoint[7] - { - kp_array[0].PublicKey, - kp_array[1].PublicKey, - kp_array[2].PublicKey, - kp_array[3].PublicKey, - kp_array[4].PublicKey, - kp_array[5].PublicKey, - kp_array[6].PublicKey - }; Console.WriteLine($"Generated keypairs PKey:"); for (int i = 0; i < mockContext.Object.Validators.Length; i++) Console.WriteLine($"{mockContext.Object.Validators[i]}/{Contract.CreateSignatureContract(mockContext.Object.Validators[i]).ScriptHash}"); - var updatedContract = Contract.CreateMultiSigContract(mockContext.Object.M, mockContext.Object.Validators); Console.WriteLine($"\nContract updated: {updatedContract.ScriptHash}"); // =============================================================== @@ -303,6 +323,7 @@ public void ConsensusService_SingleNodeActors_OnStart_PrepReq_PrepResponses_Comm Console.WriteLine("\n=========================="); Console.WriteLine("\nCN7 simulation time"); + TellConsensusPayload(actorConsensus, cmPayloadTemp); var tempPayloadToBlockAndWait = subscriber.ExpectMsg(); var rmPayload = (ConsensusPayload)tempPayloadToBlockAndWait.Inventory; @@ -456,6 +477,25 @@ public ConsensusPayload GetPayloadAndModifyValidator(ConsensusPayload cpToCopy, return cpTemp; } + public ConsensusPayload GetPrepareRequestAndSignStateRoot(ConsensusPayload req, ushort vI, KeyPair kp, byte[] stateRootData) + { + var tmp = req.ToArray().AsSerializable(); + tmp.ValidatorIndex = vI; + var message = tmp.GetDeserializedMessage(); + message.StateRootSignature = Crypto.Sign(stateRootData, kp.PrivateKey, kp.PublicKey.EncodePoint(false).Skip(1).ToArray()); + tmp.ConsensusMessage = message; + return tmp; + } + public ConsensusPayload GetPrepareResponsePayloadAndSignStateRoot(ConsensusPayload resp, ushort vI, KeyPair kp, byte[] stateRootData) + { + var tmp = resp.ToArray().AsSerializable(); + tmp.ValidatorIndex = vI; + var message = tmp.GetDeserializedMessage(); + message.StateRootSignature = Crypto.Sign(stateRootData, kp.PrivateKey, kp.PublicKey.EncodePoint(false).Skip(1).ToArray()); + tmp.ConsensusMessage = message; + return tmp; + } + private void SignPayload(ConsensusPayload payload, KeyPair kp) { ContractParametersContext sc; @@ -520,13 +560,14 @@ public void TestSerializeAndDeserializeConsensusContext() var prepareRequestMessage = new PrepareRequest { TransactionHashes = consensusContext.TransactionHashes, - Timestamp = 23 + Timestamp = 23, + StateRootSignature = new byte[64] }; consensusContext.PreparationPayloads[6] = MakeSignedPayload(consensusContext, prepareRequestMessage, 6, new[] { (byte)'3', (byte)'!' }); - consensusContext.PreparationPayloads[0] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash }, 0, new[] { (byte)'t', (byte)'e' }); - consensusContext.PreparationPayloads[1] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash }, 1, new[] { (byte)'s', (byte)'t' }); + consensusContext.PreparationPayloads[0] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash, StateRootSignature = new byte[64] }, 0, new[] { (byte)'t', (byte)'e' }); + consensusContext.PreparationPayloads[1] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash, StateRootSignature = new byte[64] }, 1, new[] { (byte)'s', (byte)'t' }); consensusContext.PreparationPayloads[2] = null; - consensusContext.PreparationPayloads[3] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash }, 3, new[] { (byte)'1', (byte)'2' }); + consensusContext.PreparationPayloads[3] = MakeSignedPayload(consensusContext, new PrepareResponse { PreparationHash = consensusContext.PreparationPayloads[6].Hash, StateRootSignature = new byte[64] }, 3, new[] { (byte)'1', (byte)'2' }); consensusContext.PreparationPayloads[4] = null; consensusContext.PreparationPayloads[5] = null; @@ -624,7 +665,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndNoPrepar new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 0, - InvocationScript = new[] { (byte)'t', (byte)'e' } + InvocationScript = new[] { (byte)'t', (byte)'e' }, + StateRootSignature = new byte[64] } }, { @@ -632,7 +674,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndNoPrepar new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 3, - InvocationScript = new[] { (byte)'1', (byte)'2' } + InvocationScript = new[] { (byte)'1', (byte)'2' }, + StateRootSignature = new byte[64] } }, { @@ -640,7 +683,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndNoPrepar new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 6, - InvocationScript = new[] { (byte)'3', (byte)'!' } + InvocationScript = new[] { (byte)'3', (byte)'!' }, + StateRootSignature = new byte[64] } } }, @@ -714,6 +758,7 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndPrepareR }, PrepareRequestMessage = new PrepareRequest { + StateRootSignature = new byte[64], TransactionHashes = txs.Select(p => p.Hash).ToArray() }, PreparationHash = new UInt256(Crypto.Hash256(new[] { (byte)'a' })), @@ -724,7 +769,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndPrepareR new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 0, - InvocationScript = new[] { (byte)'t', (byte)'e' } + InvocationScript = new[] { (byte)'t', (byte)'e' }, + StateRootSignature = new byte[64], } }, { @@ -732,7 +778,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndPrepareR new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 1, - InvocationScript = new[] { (byte)'s', (byte)'t' } + InvocationScript = new[] { (byte)'s', (byte)'t' }, + StateRootSignature = new byte[64], } }, { @@ -740,7 +787,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithChangeViewsAndPrepareR new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 3, - InvocationScript = new[] { (byte)'1', (byte)'2' } + InvocationScript = new[] { (byte)'1', (byte)'2' }, + StateRootSignature = new byte[64], } } }, @@ -767,6 +815,7 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithoutC ChangeViewMessages = new Dictionary(), PrepareRequestMessage = new PrepareRequest { + StateRootSignature = new byte[64], TransactionHashes = txs.Select(p => p.Hash).ToArray() }, PreparationMessages = new Dictionary() @@ -776,7 +825,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithoutC new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 0, - InvocationScript = new[] { (byte)'t', (byte)'e' } + InvocationScript = new[] { (byte)'t', (byte)'e' }, + StateRootSignature = new byte[64] } }, { @@ -784,7 +834,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithoutC new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 1, - InvocationScript = new[] { (byte)'s', (byte)'t' } + InvocationScript = new[] { (byte)'s', (byte)'t' }, + StateRootSignature = new byte[64] } }, { @@ -792,7 +843,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithoutC new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 3, - InvocationScript = new[] { (byte)'1', (byte)'2' } + InvocationScript = new[] { (byte)'1', (byte)'2' }, + StateRootSignature = new byte[64] } }, { @@ -800,7 +852,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithoutC new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 6, - InvocationScript = new[] { (byte)'3', (byte)'!' } + InvocationScript = new[] { (byte)'3', (byte)'!' }, + StateRootSignature = new byte[64] } } }, @@ -827,6 +880,7 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithComm ChangeViewMessages = new Dictionary(), PrepareRequestMessage = new PrepareRequest { + StateRootSignature = new byte[64], TransactionHashes = txs.Select(p => p.Hash).ToArray() }, PreparationMessages = new Dictionary() @@ -836,7 +890,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithComm new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 0, - InvocationScript = new[] { (byte)'t', (byte)'e' } + InvocationScript = new[] { (byte)'t', (byte)'e' }, + StateRootSignature = new byte[64], } }, { @@ -844,7 +899,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithComm new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 1, - InvocationScript = new[] { (byte)'s', (byte)'t' } + InvocationScript = new[] { (byte)'s', (byte)'t' }, + StateRootSignature = new byte[64], } }, { @@ -852,7 +908,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithComm new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 3, - InvocationScript = new[] { (byte)'1', (byte)'2' } + InvocationScript = new[] { (byte)'1', (byte)'2' }, + StateRootSignature = new byte[64], } }, { @@ -860,7 +917,8 @@ public void TestSerializeAndDeserializeRecoveryMessageWithoutChangeViewsWithComm new RecoveryMessage.PreparationPayloadCompact { ValidatorIndex = 6, - InvocationScript = new[] { (byte)'3', (byte)'!' } + InvocationScript = new[] { (byte)'3', (byte)'!' }, + StateRootSignature = new byte[64], } } },