Skip to content
Juvix imports

module arch.node.engines.mempool_worker;

import prelude open;
import arch.node.types.engine open;
import arch.node.engines.mempool_worker_config open public;
import arch.node.engines.mempool_worker_messages open public;
import arch.node.engines.mempool_worker_environment open public;
import arch.node.engines.mempool_worker_behaviour open public;
import arch.node.types.anoma as Anoma open;

open mempool_worker_config_example;
open mempool_worker_environment_example;

Mempool Worker Engine

Purpose

Workers are one of the mempool engines and, in V2, they are the only one and there is only a single worker.

The worker receives transaction requests from users and solvers and batches these transaction requests, assigning a unique TxFingerprint to every new transaction. Each transaction candidate will be sent to an Executor inside an ExecuteTransaction message. Once the worker has received a KVSLockAcquired for every part of the transaction request's label (from the shards of the same Anoma validator in response to KVSAcquireLock-messages), it knows that this transaction candidate has been "seen" by all Shards, which implies that all shards are prepared to process lock requests from execution processes (see KVSReadRequest and KVSWrite for details). This information about locks being recorded is distributed to all shards via UpdateSeenAll messages, which contain the most recent TxFingerprint for which it is certain that all Shards have "seen" this transaction candidate and all previous ones from the same worker (and they are thus prepared to grant locks). Note that if shards receive transaction candidates in a different order than the final total order of transactions, UpdateSeenAll messages are necessary to avoid that shards grant locks before all locks of previous transaction executions have been served.

Workers also are in charge of collecting and curating logs of transaction execution. Success is equivalent to all reads and writes being successful and an ExecutorFinished-message from the executor that was spawned to execute the message.

Components

Type

MempoolWorkerEngine : Type :=
Engine
MempoolWorkerCfg
MempoolWorkerLocalState
MempoolWorkerMailboxState
MempoolWorkerTimerHandle
MempoolWorkerActionArguments
Anoma.Msg
Anoma.Cfg
Anoma.Env;

Example of a mempool worker engine

exampleMempoolWorkerEngine : MempoolWorkerEngine :=
mkEngine@{
cfg := mempoolWorkerCfg;
env := mempoolWorkerEnv;
behaviour := mempoolWorkerBehaviour;
};

where mempoolWorkerCfg is defined as follows:

mempoolWorkerCfg : EngineCfg MempoolWorkerCfg :=
mkEngineCfg@{
node := Curve25519PubKey "0xabcd1234";
name := "mempool worker";
cfg := mkMempoolWorkerCfg;
};

where mempoolWorkerEnv is defined as follows:

mempoolWorkerEnv : MempoolWorkerEnv :=
mkEngineEnv@{
localState :=
mkMempoolWorkerLocalState@{
batch_number := 0;
transactions := Map.empty;
transactionEngines := Map.empty;
locks_acquired := [];
seen_all_writes := 0;
seen_all_reads := 0;
execution_summaries := Map.empty;
gensym := 0;
};
mailboxCluster := Map.empty;
acquaintances := Set.empty;
timers := [];
};

and mempoolWorkerBehaviour is defined as follows:

mempoolWorkerBehaviour : MempoolWorkerBehaviour :=
mkEngineBehaviour@{
guards :=
First
[
handleTransactionRequestGuard;
handleLockAcquiredGuard;
handleExecutorFinishedGuard;
];
};