forked from neo-project/neo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MemoryPool: state-dependent concurrent verification in TryAdd
MemoryPool contents is always valid (verified) against some snapshot. This snapshot is only changed when new block is added. Between blocks we only have one valid chain state that can be read by multiple threads without any issues, thus we can execute concurrently not only state-independent, but also state-dependent parts of transaction verification. To simplify execution flow (minimize single-threaded Blockchain message handling and eliminate duplicate DB accesses for ContainsTransaction) TransactionRouter is an independent entity now, though of course we can also attach the same actor functionality to MemoryPool itself. TransactionVerificationContext balance checking is moved to MemoryPool from Transaction with this, Transaction shouldn't care (it can check overall GAS balance though). This is directly related to neo-project#2045 work (it solves state access problem there) and in some sense is an alternative to neo-project#2054 (makes fee calculation easier, though IsStandardContract() trick to optimize out these contracts during reverification is still relevant and can be added here). At this stage it's just a prototype, some additional optimizations and simplifications are possible of course, but this prototype shows the direction and the main question for now is whether this direction is interesting for us.
- Loading branch information
1 parent
0c24322
commit c4abe4b
Showing
10 changed files
with
173 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,58 @@ | ||
using Akka.Actor; | ||
using Akka.Routing; | ||
using Neo.Network.P2P; | ||
using Neo.Network.P2P.Payloads; | ||
using System; | ||
|
||
namespace Neo.Ledger | ||
{ | ||
internal class TransactionRouter : UntypedActor | ||
public sealed class TransactionRouter : UntypedActor | ||
{ | ||
public class Task { public Transaction Transaction; public bool Relay; } | ||
private readonly NeoSystem system; | ||
private readonly Blockchain chain; | ||
|
||
private readonly IActorRef blockchain; | ||
|
||
public TransactionRouter(NeoSystem system) | ||
public TransactionRouter(NeoSystem system, Blockchain bc) | ||
{ | ||
this.blockchain = system.Blockchain; | ||
this.system = system; | ||
this.chain = bc; | ||
} | ||
|
||
protected override void OnReceive(object message) | ||
{ | ||
if (!(message is Task task)) return; | ||
blockchain.Tell(new Blockchain.PreverifyCompleted | ||
switch (message) | ||
{ | ||
case Transaction tx: | ||
OnTransaction(tx, true); | ||
break; | ||
case Transaction[] transactions: | ||
// This message comes from a mempool's revalidation, already relayed | ||
foreach (var tx in transactions) OnTransaction(tx, false); | ||
break; | ||
} | ||
} | ||
|
||
private void OnTransaction(Transaction tx, bool relay) | ||
{ | ||
VerifyResult res = chain.MemPool.TryAdd(tx); | ||
if (relay && res == VerifyResult.Succeed) | ||
system.LocalNode.Tell(new LocalNode.RelayDirectly { Inventory = tx }); | ||
SendRelayResult(tx, res); | ||
} | ||
|
||
private void SendRelayResult(IInventory inventory, VerifyResult result) | ||
{ | ||
Blockchain.RelayResult rr = new Blockchain.RelayResult | ||
{ | ||
Transaction = task.Transaction, | ||
Result = task.Transaction.VerifyStateIndependent(), | ||
Relay = task.Relay | ||
}, Sender); | ||
Inventory = inventory, | ||
Result = result | ||
}; | ||
Sender.Tell(rr); | ||
Context.System.EventStream.Publish(rr); | ||
} | ||
|
||
internal static Props Props(NeoSystem system) | ||
public static Props Props(NeoSystem system, Blockchain bc) | ||
{ | ||
return Akka.Actor.Props.Create(() => new TransactionRouter(system)).WithRouter(new SmallestMailboxPool(Environment.ProcessorCount)); | ||
return Akka.Actor.Props.Create(() => new TransactionRouter(system, bc)).WithRouter(new SmallestMailboxPool(Environment.ProcessorCount)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.