Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore MemoryPool transactions from saved consensus context. #575

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
999251c
Save consensus context each time we change view (so we will be close …
Jan 25, 2019
2ce8b71
Add extension methods for loading and saving the ConsensusContext to …
Jan 25, 2019
ae56b38
Load MemoryPool initially with transactions from saved consensus.
Jan 25, 2019
232e2fd
Fix tests.
Jan 25, 2019
d930e2c
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
vncoelho Jan 25, 2019
4ae84f7
Remove unused 'using' statements.
Jan 25, 2019
947aa53
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
Jan 27, 2019
91a2e3a
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
shargon Jan 28, 2019
dc7482c
Pass consensus store into the NeoSystem constructor instead of StartC…
Jan 29, 2019
411f905
Add one extra check when restoring transactions from saved consensus …
Jan 29, 2019
f43a5ed
Move loading transactions from the last saved ConsensusContext out of…
Jan 29, 2019
28f05eb
More clean-up.
Jan 29, 2019
91f31de
Further decoupling, don't expose the consensus store from NeoSystem.
Jan 29, 2019
eedeffb
Handle saving and restoring consensus conetext when RequestSent, Requ…
Jan 30, 2019
8eaf669
Make unit tests pass again. Consensus unit tests still need attention…
Jan 30, 2019
240c5bb
Don't write the consensus state after resposne sent to reduce writes.
Jan 30, 2019
92e6987
Remove unneeded commented code.
Jan 31, 2019
3b06474
Fix saving context to include the miner transaction after receiving t…
Jan 31, 2019
323384c
Ensure consensus context has snapshot and keypair set upon loading th…
Jan 31, 2019
d312b2c
Fix loading transactions into the MemoryPool from consensus context.
Jan 31, 2019
6c33b62
More precise check when restoring consensus context.
Jan 31, 2019
1c744ea
Don't need to save consensus state on request sent or received since …
Feb 4, 2019
1d81e54
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
Feb 16, 2019
700a0aa
Fix test compile.
Feb 16, 2019
62d5e5a
Fix tests.
Feb 16, 2019
5e29fdc
Don't separate the code for obtaining transactions into a separte met…
Feb 16, 2019
48035df
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
erikzhang Feb 17, 2019
9b16fb8
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
Feb 19, 2019
f955db5
Write consensus state synchronously upon commit. Move constant for co…
Feb 19, 2019
8aeaf80
Use the passed writeOptions for Put to the store.
Feb 19, 2019
82a0f2b
Decouple restoring memory pool from the consensus state from the Bloc…
Feb 19, 2019
3dd2928
Remove unused using statement.
Feb 19, 2019
2fc2139
Clean-up.
Feb 19, 2019
fc4cfe8
More clean-up. Remove unused using statements.
Feb 19, 2019
14a0a2c
Remove one more unused using statement.
Feb 19, 2019
7e0f518
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
jsolman Feb 20, 2019
3d6a2b1
Minor changes
erikzhang Feb 20, 2019
438c105
Add method `PutSync()` to class `Store`
erikzhang Feb 20, 2019
e362f55
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
Feb 20, 2019
465e587
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
erikzhang Feb 21, 2019
3ebb75e
Renaming
erikzhang Feb 21, 2019
75c81d9
Remove unused variable.
Feb 21, 2019
becf0f5
Optimize the serialization of `ConsensusContext`
erikzhang Feb 21, 2019
0f9856e
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
erikzhang Feb 21, 2019
b957d1b
Merge branch 'consensus/improved_dbft' into consensus/recoveryLog2
erikzhang Feb 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions neo.UnitTests/TestBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static NeoSystem InitializeMockNeoSystem()
mockSnapshot.SetupGet(p => p.HeaderHashIndex).Returns(new TestMetaDataCache<HashIndexState>());

var mockStore = new Mock<Store>();
mockStore.Setup(p => p.Get(Consensus.Helper.CN_Context, It.IsAny<byte[]>())).Returns((byte[]) null);

var defaultTx = TestUtils.CreateRandomHashInvocationMockTransaction().Object;
mockStore.Setup(p => p.GetBlocks()).Returns(new TestDataCache<UInt256, BlockState>());
Expand Down
1 change: 0 additions & 1 deletion neo.UnitTests/UT_Consensus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Moq;
using Neo.Consensus;
using Neo.Cryptography;
using Neo.IO;
using Neo.Ledger;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
Expand Down
31 changes: 9 additions & 22 deletions neo/Consensus/ConsensusService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace Neo.Consensus
Expand All @@ -22,8 +21,6 @@ public class Start { public bool IgnoreRecoveryLogs; }
public class SetViewNumber { public byte ViewNumber; }
internal class Timer { public uint Height; public byte ViewNumber; }

private const byte ContextSerializationPrefix = 0xf4;

private readonly IConsensusContext context;
private readonly IActorRef localNode;
private readonly IActorRef taskManager;
Expand Down Expand Up @@ -127,7 +124,7 @@ private void CheckPreparations()
ConsensusPayload payload = context.MakeCommit();
Log($"send commit");
context.State |= ConsensusState.CommitSent;
store.Put(ContextSerializationPrefix, new byte[0], context.ToArray());
context.WriteContextToStore(store);
jsolman marked this conversation as resolved.
Show resolved Hide resolved
localNode.Tell(new LocalNode.SendDirectly { Inventory = payload });
// Set timer, so we will resend the commit in case of a networking issue
ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock));
Expand Down Expand Up @@ -412,27 +409,17 @@ private void OnStart(Start options)
{
Log("OnStart");
started = true;
if (!options.IgnoreRecoveryLogs)
bool loadedState = !options.IgnoreRecoveryLogs && context.LoadContextFromStore(store);
if (loadedState && context.State.HasFlag(ConsensusState.CommitSent) && Blockchain.Singleton.Height + 1 == context.BlockIndex)
{
byte[] data = store.Get(ContextSerializationPrefix, new byte[0]);
if (data != null)
{
using (MemoryStream ms = new MemoryStream(data, false))
using (BinaryReader reader = new BinaryReader(ms))
{
context.Deserialize(reader);
}
}
}
if (context.State.HasFlag(ConsensusState.CommitSent) && context.BlockIndex == Blockchain.Singleton.Height + 1)
CheckPreparations();
else
{
InitializeConsensus(0);
// Issue a ChangeView with NewViewNumber of 0 to request recovery messages on start-up.
if (context.BlockIndex == Blockchain.Singleton.HeaderHeight + 1)
localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView(0) });
return;
}

InitializeConsensus(0);
// Issue a ChangeView with NewViewNumber of 0 to request recovery messages on start-up.
if (context.BlockIndex == Blockchain.Singleton.HeaderHeight + 1)
localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView(0) });
}

private void OnTimer(Timer timer)
Expand Down
44 changes: 44 additions & 0 deletions neo/Consensus/Helper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Neo.IO;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using System.Collections.Generic;
using System.IO;

namespace Neo.Consensus
{
internal static class Helper
{
/// <summary>
/// Prefix for saving consensus state.
/// </summary>
public const byte CN_Context = 0xf4;

public static void WriteContextToStore(this IConsensusContext context, Store store)
{
store.PutSync(CN_Context, new byte[0], context.ToArray());
}

public static bool LoadContextFromStore(this IConsensusContext context, Store store, bool shouldReset = true)
{
byte[] data = store.Get(CN_Context, new byte[0]);
if (data != null)
{
if (shouldReset) context.Reset(0);
using (MemoryStream ms = new MemoryStream(data, false))
using (BinaryReader reader = new BinaryReader(ms))
{
context.Deserialize(reader);
return true;
}
}
return false;
}

public static IEnumerable<Transaction> RetreiveTransactionsFromSavedConsensusContext(Store consensusStore)
{
IConsensusContext context = new ConsensusContext(null);
context.LoadContextFromStore(consensusStore, false);
return context.Transactions?.Values ?? (IEnumerable<Transaction>)new Transaction[0];
}
}
}
3 changes: 2 additions & 1 deletion neo/Ledger/Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,9 @@ static Blockchain()
public Blockchain(NeoSystem system, Store store)
{
this.system = system;
this.MemPool = new MemoryPool(system, MemoryPoolMaxTransactions);
this.Store = store;
this.MemPool = new MemoryPool(system, MemoryPoolMaxTransactions);

lock (lockObj)
{
if (singleton != null)
Expand Down
16 changes: 11 additions & 5 deletions neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@ public class NeoSystem : IDisposable
public IActorRef Consensus { get; private set; }
public RpcServer RpcServer { get; private set; }

private readonly Store store;
private readonly Store blockchainStore;
jsolman marked this conversation as resolved.
Show resolved Hide resolved
private readonly Store consensusStore;
private Peer.Start start_message = null;
private bool suspend = false;

public NeoSystem(Store store)
public NeoSystem(Store store, Store consensusStore = null)
{
this.store = store;
this.blockchainStore = store;
this.consensusStore = consensusStore ?? store;
this.Blockchain = ActorSystem.ActorOf(Ledger.Blockchain.Props(this, store));
this.LocalNode = ActorSystem.ActorOf(Network.P2P.LocalNode.Props(this));
this.TaskManager = ActorSystem.ActorOf(Network.P2P.TaskManager.Props(this));
Expand All @@ -56,9 +58,9 @@ internal void ResumeNodeStartup()
}
}

public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ignoreRecoveryLogs = false)
public void StartConsensus(Wallet wallet, bool ignoreRecoveryLogs = false)
{
Consensus = ActorSystem.ActorOf(ConsensusService.Props(this.LocalNode, this.TaskManager, consensus_store ?? store, wallet));
Consensus = ActorSystem.ActorOf(ConsensusService.Props(this.LocalNode, this.TaskManager, consensusStore, wallet));
Consensus.Tell(new ConsensusService.Start { IgnoreRecoveryLogs = ignoreRecoveryLogs });
}

Expand All @@ -74,6 +76,10 @@ public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ign
};
if (!suspend)
{
var consensusTransactions = Neo.Consensus.Helper.RetreiveTransactionsFromSavedConsensusContext(consensusStore);
foreach (var tx in consensusTransactions)
Blockchain.Tell(tx, ActorRefs.NoSender);

LocalNode.Tell(start_message);
start_message = null;
}
Expand Down
5 changes: 5 additions & 0 deletions neo/Persistence/LevelDB/LevelDBStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,5 +116,10 @@ public override void Put(byte prefix, byte[] key, byte[] value)
{
db.Put(WriteOptions.Default, SliceBuilder.Begin(prefix).Add(key), value);
}

public override void PutSync(byte prefix, byte[] key, byte[] value)
{
db.Put(new WriteOptions { Sync = true }, SliceBuilder.Begin(prefix).Add(key), value);
}
}
}
5 changes: 5 additions & 0 deletions neo/Persistence/LevelDB/Prefixes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,10 @@ internal static class Prefixes
public const byte IX_CurrentHeader = 0xc1;

public const byte SYS_Version = 0xf0;

/* Prefixes 0xf1 to 0xff are reserved for external use.
*
* Note: The saved consensus state uses the Prefix 0xf4
*/
}
}
1 change: 1 addition & 0 deletions neo/Persistence/Store.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public abstract class Store : IPersistence
public abstract MetaDataCache<HashIndexState> GetBlockHashIndex();
public abstract MetaDataCache<HashIndexState> GetHeaderHashIndex();
public abstract void Put(byte prefix, byte[] key, byte[] value);
jsolman marked this conversation as resolved.
Show resolved Hide resolved
public abstract void PutSync(byte prefix, byte[] key, byte[] value);

public abstract Snapshot GetSnapshot();
}
Expand Down