-
Notifications
You must be signed in to change notification settings - Fork 1k
/
Copy pathHelper.cs
48 lines (43 loc) · 3.07 KB
/
Helper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System.Linq;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using System.Runtime.CompilerServices;
namespace Neo.Consensus
{
internal static class Helper
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int F(this IConsensusContext context) => (context.Validators.Length - 1) / 3;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int M(this IConsensusContext context) => context.Validators.Length - context.F();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsPrimary(this IConsensusContext context) => context.MyIndex == context.PrimaryIndex;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsBackup(this IConsensusContext context) => context.MyIndex >= 0 && context.MyIndex != context.PrimaryIndex;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Header PrevHeader(this IConsensusContext context) => context.Snapshot.GetHeader(context.PrevHash);
// Consensus States
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool RequestSentOrReceived(this IConsensusContext context) => context.PreparationPayloads[context.PrimaryIndex] != null;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ResponseSent(this IConsensusContext context) => context.PreparationPayloads[context.MyIndex] != null;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool CommitSent(this IConsensusContext context) => context.CommitPayloads[context.MyIndex] != null;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool BlockSent(this IConsensusContext context) => context.Block != null;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ViewChanging(this IConsensusContext context) => context.ChangeViewPayloads[context.MyIndex]?.GetDeserializedMessage<ChangeView>().NewViewNumber > context.ViewNumber && !context.MoreThanFNodesCommitted();
// A possible attack can happen if the last node to commit is malicious and either sends change view after his
// commit to stall nodes in a higher view, or if he refuses to send recovery messages. In addition, if a node
// asking change views loses network or crashes and comes back when nodes are committed in more than one higher
// numbered view, it is possible for the node accepting recovery and commit in any of the higher views, thus
// potentially splitting nodes among views and stalling the network.
public static bool MoreThanFNodesCommitted(this IConsensusContext context) => context.CommitPayloads.Count(p => p != null) > context.F();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint GetPrimaryIndex(this IConsensusContext context, byte viewNumber)
{
int p = ((int)context.BlockIndex - viewNumber) % context.Validators.Length;
return p >= 0 ? (uint)p : (uint)(p + context.Validators.Length);
}
}
}