Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 13 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0.101-noble

# Install required dependencies for LevelDB and SQLite
RUN apt-get update && \
apt-get install -y \
libleveldb-dev \
sqlite3 \
libsqlite3-dev \
librocksdb-dev \
libsnappy-dev \
libunwind8-dev \
&& rm -rf /var/lib/apt/lists/*

21 changes: 21 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be moved to another PR later

"name": "Neo Node",
"build": {
"dockerfile": "Dockerfile",
"context": ".."
},
"workspaceFolder": "/workspace",
"workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind",
"features": {},
"customizations": {
"vscode": {
"extensions": [
"ms-dotnettools.csharp",
"ms-dotnettools.csdevkit"
]
}
},
"remoteUser": "root",
"postCreateCommand": "dotnet restore"
}

37 changes: 30 additions & 7 deletions plugins/DBFTPlugin/Consensus/ConsensusContext.Get.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ private RecoveryMessage.ChangeViewPayloadCompact GetChangeViewPayloadCompact(Ext
};
}


private RecoveryMessage.PreCommitPayloadCompact GetPreCommitPayloadCompact(ExtensiblePayload payload)
{
PreCommit preCommit = GetMessage<PreCommit>(payload);
return new RecoveryMessage.PreCommitPayloadCompact
{
ViewNumber = preCommit.ViewNumber,
ValidatorIndex = preCommit.ValidatorIndex,
PreparationHash = preCommit.PreparationHash,
InvocationScript = payload.Witness.InvocationScript,
};
}

private RecoveryMessage.CommitPayloadCompact GetCommitPayloadCompact(ExtensiblePayload payload)
{
Commit message = GetMessage<Commit>(payload);
Expand All @@ -68,12 +81,21 @@ private RecoveryMessage.PreparationPayloadCompact GetPreparationPayloadCompact(E
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte GetPrimaryIndex(byte viewNumber)
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 priorityPrimaryIndex)
{
if (Validators.Length <= 1) return priorityPrimaryIndex;
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);
}

public UInt160 GetSender(int index)
{
return Contract.CreateSignatureRedeemScript(Validators[index]).ToScriptHash();
Expand All @@ -82,18 +104,19 @@ public UInt160 GetSender(int index)
/// <summary>
/// Return the expected block size
/// </summary>
public int GetExpectedBlockSize()
public int GetExpectedBlockSize(uint pId)
{
return GetExpectedBlockSizeWithoutTransactions(Transactions!.Count) + // Base size
Transactions.Values.Sum(u => u.Size); // Sum Txs
return GetExpectedBlockSizeWithoutTransactions(Transactions[pId].Count) + // Base size
Transactions[pId].Values.Sum(u => u.Size); // Sum Txs
}

/// <summary>
/// Return the expected block system fee
/// </summary>
public long GetExpectedBlockSystemFee()
public long GetExpectedBlockSystemFee(uint pId)
{
return Transactions!.Values.Sum(u => u.SystemFee); // Sum Txs
// check ! on the original todo
return Transactions[pId].Values.Sum(u => u.SystemFee); // Sum Txs
}

/// <summary>
Expand Down
100 changes: 63 additions & 37 deletions plugins/DBFTPlugin/Consensus/ConsensusContext.MakePayload.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,22 +29,22 @@ public ExtensiblePayload MakeChangeView(ChangeViewReason reason)
});
}

public ExtensiblePayload MakeCommit()
public ExtensiblePayload MakeCommit(uint pId)
{
if (CommitPayloads[MyIndex] is ExtensiblePayload payload)
if (CommitPayloads[pId][MyIndex] is ExtensiblePayload payload)
return payload;

var block = EnsureHeader()!;
CommitPayloads[MyIndex] = MakeSignedPayload(new Commit
var block = EnsureHeader(pId)!;
CommitPayloads[pId][MyIndex] = MakeSignedPayload(new Commit
{
Signature = _signer.SignBlock(block, _myPublicKey!, dbftSettings.Network)
});
return CommitPayloads[MyIndex]!;
return CommitPayloads[pId][MyIndex]!;
}

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);
Expand All @@ -69,11 +69,11 @@ private void SignPayload(ExtensiblePayload payload)
/// Prevent that block exceed the max size
/// </summary>
/// <param name="txs">Ordered transactions</param>
internal void EnsureMaxBlockLimitation(Transaction[] txs)
internal void EnsureMaxBlockLimitation(Transaction[] txs, uint pId)
{
var hashes = new List<UInt256>();
Transactions = new Dictionary<UInt256, Transaction>();
VerificationContext = new TransactionVerificationContext();
Transactions[pId] = new Dictionary<UInt256, Transaction>();
VerificationContext[pId] = new TransactionVerificationContext();

// Expected block size
var blockSize = GetExpectedBlockSizeWithoutTransactions(txs.Length);
Expand All @@ -91,27 +91,41 @@ internal void EnsureMaxBlockLimitation(Transaction[] txs)
if (blockSystemFee > dbftSettings.MaxBlockSystemFee) break;

hashes.Add(tx.Hash);
Transactions.Add(tx.Hash, tx);
VerificationContext.AddTransaction(tx);
Transactions[pId].Add(tx.Hash, tx);
VerificationContext[pId].AddTransaction(tx);
}

TransactionHashes = hashes.ToArray();
TransactionHashes[pId] = hashes.ToArray();
}

public ExtensiblePayload MakePrepareRequest()
internal IEnumerable<Transaction> PickTransactions()
{
var maxTransactionsPerBlock = neoSystem.Settings.MaxTransactionsPerBlock;
var verifiedTxes = neoSystem.MemPool.GetSortedVerifiedTransactions((int)maxTransactionsPerBlock));
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(PickTransactions(), pId);
// Limit Speaker proposal to the limit `MaxTransactionsPerBlock` or all available transactions of the mempool
EnsureMaxBlockLimitation(neoSystem.MemPool.GetSortedVerifiedTransactions((int)maxTransactionsPerBlock));
Block.Header.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1);
Block.Header.Nonce = GetNonce();
return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest

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
{
Version = Block.Version,
PrevHash = Block.PrevHash,
Timestamp = Block.Timestamp,
Nonce = Block.Nonce,
TransactionHashes = TransactionHashes!
Version = Block[pId].Version,
PrevHash = Block[pId].PrevHash,
Timestamp = Block[pId].Timestamp,
Nonce = Block[pId].Nonce,
TransactionHashes = TransactionHashes![pId]
});
}

Expand All @@ -126,52 +140,64 @@ public ExtensiblePayload MakeRecoveryRequest()
public ExtensiblePayload MakeRecoveryMessage()
{
PrepareRequest? prepareRequestMessage = null;
if (TransactionHashes != null)
uint pId = TransactionHashes[0] != null ? 0u : (TransactionHashes[1] != null ? 1u : 0u);
if (TransactionHashes[pId] != null)
{
prepareRequestMessage = new PrepareRequest
{
Version = Block.Version,
PrevHash = Block.PrevHash,
Version = Block[pId].Version,
PrevHash = Block[pId].PrevHash,
ViewNumber = ViewNumber,
Timestamp = Block.Timestamp,
Nonce = Block.Nonce,
BlockIndex = Block.Index,
ValidatorIndex = Block.PrimaryIndex,
TransactionHashes = TransactionHashes
Timestamp = Block[pId].Timestamp,
Nonce = Block[pId].Nonce,
BlockIndex = Block[pId].Index,
ValidatorIndex = Block[pId].PrimaryIndex,
TransactionHashes = TransactionHashes[pId]
};
}
return MakeSignedPayload(new RecoveryMessage
{
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.
PreparationHash = TransactionHashes == null
? PreparationPayloads.Where(p => p != null)
PreparationHash = TransactionHashes[pId] == null
? PreparationPayloads[pId].Where(p => p != null)
.GroupBy(p => GetMessage<PrepareResponse>(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)
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.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<byte, RecoveryMessage.CommitPayloadCompact>()
});
}

public ExtensiblePayload MakePrepareResponse()
public ExtensiblePayload MakePrepareResponse(uint pId)
{
return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareResponse
return PreparationPayloads[pId][MyIndex] = MakeSignedPayload(new PrepareResponse
{
PreparationHash = PreparationPayloads[Block.PrimaryIndex]!.Hash
PreparationHash = PreparationPayloads[Block[pId].PrimaryIndex]!.Hash,
PId = pId
});
}

public ExtensiblePayload MakePreCommit(uint pId)
{
return PreCommitPayloads[pId][MyIndex] = MakeSignedPayload(new PreCommit
{
PreparationHash = PreparationPayloads[pId][Block[pId].PrimaryIndex].Hash,
PId = pId
});
}
// Related to issue https://github.com/neo-project/neo/issues/3431
// Ref. https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator?view=net-8.0
//
Expand Down
Loading
Loading