You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@resilientdb.apache.org by ju...@apache.org on 2026/09/02 07:34:09 UTC

(incubator-resilientdb) 01/01: add thun

This is an automated email from the ASF dual-hosted git repository.

cjcchen pushed a commit to branch thun_merge
in repository https://gitbox.apache.org/repos/asf/incubator-resilientdb.git

commit 50e5c04d0560a414f865779d880c835ee15e6d85
Author: cjcchen <ic...@gmail.com>
AuthorDate: Wed Sep 2 15:33:53 2026 +0800

    add thun
---
 benchmark/bin/thunderbolt/BUILD                    |   13 +
 benchmark/bin/thunderbolt/kv_server.cpp            |   78 +
 benchmark/protocols/thunderbolt/BUILD              |   25 +
 .../thunderbolt/kv_server_performance.cpp          |   89 +
 .../protocols/thunderbolt/kv_service_tools.cpp     |   57 +
 executor/common/transaction_manager.h              |   19 +
 .../consensus/execution/transaction_executor.cpp   |    7 +
 .../consensus/execution/transaction_executor.h     |    3 +
 .../common/framework/performance_manager.cpp       |    5 +
 .../common/framework/performance_manager.h         |    3 +
 .../consensus/ordering/thunderbolt/algorithm/BUILD |   36 +
 .../thunderbolt/algorithm/proposal_manager.cpp     |  258 +++
 .../thunderbolt/algorithm/proposal_manager.h       |   54 +
 .../ordering/thunderbolt/algorithm/thunderbolt.cpp |  555 ++++++
 .../ordering/thunderbolt/algorithm/thunderbolt.h   |   79 +
 .../algorithm/transaction_collector.cpp            |   55 +
 .../thunderbolt/algorithm/transaction_collector.h  |   71 +
 .../ordering/thunderbolt/executor/common/BUILD     |   18 +
 .../executor/common/contract_execute_info.h        |   71 +
 .../ordering/thunderbolt/executor/common/utils.h   |   36 +
 .../thunderbolt/executor/common/x_verifier.cpp     |  187 ++
 .../thunderbolt/executor/common/x_verifier.h       |   72 +
 .../ordering/thunderbolt/executor/eo_service/BUILD |   26 +
 .../eo_service/contract_transaction_manager.cpp    |  130 ++
 .../eo_service/contract_transaction_manager.h      |   56 +
 .../contract_transaction_manager_test.cpp          |  270 +++
 .../executor/eo_service/test_data/BUILD            |    1 +
 .../executor/eo_service/test_data/contract.json    |   19 +
 .../ordering/thunderbolt/executor/manager/BUILD    |  620 +++++++
 .../executor/manager/address_manager.cpp           |   81 +
 .../thunderbolt/executor/manager/address_manager.h |   56 +
 .../executor/manager/address_manager_test.cpp      |   58 +
 .../executor/manager/committer_context.cpp         |   60 +
 .../executor/manager/committer_context.h           |   53 +
 .../executor/manager/concurrency_controller.cpp    |   16 +
 .../executor/manager/concurrency_controller.h      |   51 +
 .../executor/manager/contract_committer.h          |   80 +
 .../executor/manager/contract_deployer.cpp         |  186 ++
 .../executor/manager/contract_deployer.h           |   68 +
 .../executor/manager/contract_deployer_test.cpp    |  119 ++
 .../executor/manager/contract_executor.cpp         |   98 +
 .../executor/manager/contract_executor.h           |   73 +
 .../executor/manager/contract_executor_test.cpp    |  367 ++++
 .../executor/manager/contract_manager.cpp          |  225 +++
 .../executor/manager/contract_manager.h            |   95 +
 .../executor/manager/contract_manager_test.cpp     |  260 +++
 .../executor/manager/contract_verifier.cpp         |   50 +
 .../executor/manager/contract_verifier.h           |   59 +
 .../thunderbolt/executor/manager/d_storage.cpp     |  162 ++
 .../thunderbolt/executor/manager/d_storage.h       |   35 +
 .../thunderbolt/executor/manager/data_storage.cpp  |   72 +
 .../thunderbolt/executor/manager/data_storage.h    |   36 +
 .../thunderbolt/executor/manager/evm_state.h       |   23 +
 .../thunderbolt/executor/manager/global_state.cpp  |   46 +
 .../thunderbolt/executor/manager/global_state.h    |   43 +
 .../thunderbolt/executor/manager/global_view.cpp   |   23 +
 .../thunderbolt/executor/manager/global_view.h     |   25 +
 .../executor/manager/level_d_storage.cpp           |  207 +++
 .../thunderbolt/executor/manager/level_d_storage.h |   36 +
 .../thunderbolt/executor/manager/leveldb.cpp       |   30 +
 .../thunderbolt/executor/manager/leveldb.h         |   25 +
 .../executor/manager/leveldb_d_storage.cpp         |  203 +++
 .../executor/manager/leveldb_d_storage.h           |   40 +
 .../executor/manager/leveldb_storage.cpp           |  111 ++
 .../thunderbolt/executor/manager/leveldb_storage.h |   41 +
 .../thunderbolt/executor/manager/local_state.cpp   |   70 +
 .../thunderbolt/executor/manager/local_state.h     |   52 +
 .../thunderbolt/executor/manager/local_view.cpp    |   77 +
 .../thunderbolt/executor/manager/local_view.h      |   38 +
 .../executor/manager/local_view_test.cpp           |  122 ++
 .../thunderbolt/executor/manager/mock_d_storage.h  |   49 +
 .../executor/manager/mock_data_storage.h           |   47 +
 .../thunderbolt/executor/manager/ooo_committer.cpp |  113 ++
 .../thunderbolt/executor/manager/ooo_committer.h   |   74 +
 .../executor/manager/ooo_controller.cpp            |   36 +
 .../thunderbolt/executor/manager/ooo_controller.h  |   17 +
 .../executor/manager/sequential_cc_controller.cpp  |  267 +++
 .../executor/manager/sequential_cc_controller.h    |   70 +
 .../manager/sequential_cc_controller_test.cpp      | 1011 +++++++++++
 .../manager/sequential_concurrency_committer.cpp   |  252 +++
 .../manager/sequential_concurrency_committer.h     |  113 ++
 .../sequential_concurrency_committer_test.cpp      |  258 +++
 .../executor/manager/streaming_committer.cpp       |  333 ++++
 .../executor/manager/streaming_committer.h         |  133 ++
 .../executor/manager/streaming_controller.cpp      |  232 +++
 .../executor/manager/streaming_controller.h        |   61 +
 .../executor/manager/streaming_dq_committer.cpp    |  370 ++++
 .../executor/manager/streaming_dq_committer.h      |  110 ++
 .../manager/streaming_dq_committer_test.cpp        | 1137 ++++++++++++
 .../executor/manager/streaming_dq_controller.cpp   |  249 +++
 .../executor/manager/streaming_dq_controller.h     |   76 +
 .../manager/streaming_single_committer.cpp         |   96 +
 .../executor/manager/streaming_single_committer.h  |   83 +
 .../executor/manager/test_committer.cpp            |   74 +
 .../thunderbolt/executor/manager/test_committer.h  |   62 +
 .../executor/manager/test_controller.cpp           |   38 +
 .../thunderbolt/executor/manager/test_controller.h |   19 +
 .../thunderbolt/executor/manager/test_data/BUILD   |    4 +
 .../executor/manager/test_data/compile.sh          |    5 +
 .../executor/manager/test_data/contract.json       |   19 +
 .../thunderbolt/executor/manager/test_data/kv.json |   18 +
 .../thunderbolt/executor/manager/test_data/kv.sol  |   59 +
 .../executor/manager/two_phase_committer.cpp       |  170 ++
 .../executor/manager/two_phase_committer.h         |   72 +
 .../executor/manager/two_phase_committer_test.cpp  |  352 ++++
 .../executor/manager/two_phase_controller.cpp      |  115 ++
 .../executor/manager/two_phase_controller.h        |   33 +
 .../executor/manager/two_phase_controller_test.cpp |  435 +++++
 .../executor/manager/two_phase_ooo_committer.cpp   |  162 ++
 .../executor/manager/two_phase_ooo_committer.h     |   72 +
 .../executor/manager/two_phase_ooo_controller.cpp  |   89 +
 .../executor/manager/two_phase_ooo_controller.h    |   33 +
 .../thunderbolt/executor/manager/v_controller.cpp  |   87 +
 .../thunderbolt/executor/manager/v_controller.h    |   32 +
 .../thunderbolt/executor/manager/x_committer.cpp   |  206 +++
 .../thunderbolt/executor/manager/x_committer.h     |   89 +
 .../executor/manager/x_committer_test.cpp          |  258 +++
 .../thunderbolt/executor/manager/x_controller.cpp  |  237 +++
 .../thunderbolt/executor/manager/x_controller.h    |   79 +
 .../thunderbolt/executor/manager/x_verifier.cpp    |  188 ++
 .../thunderbolt/executor/manager/x_verifier.h      |   72 +
 .../executor/manager/x_verifier_test.cpp           |  236 +++
 .../thunderbolt/executor/manager/xexecutor.cpp     |  286 +++
 .../thunderbolt/executor/manager/xexecutor.h       |  108 ++
 .../ordering/thunderbolt/executor/paral_sm/BUILD   |  299 ++++
 .../executor/paral_sm/address_manager.cpp          |   75 +
 .../executor/paral_sm/address_manager.h            |   57 +
 .../executor/paral_sm/address_manager_test.cpp     |   58 +
 .../executor/paral_sm/committer_context.cpp        |   58 +
 .../executor/paral_sm/committer_context.h          |   54 +
 .../executor/paral_sm/concurrency_controller.cpp   |   16 +
 .../executor/paral_sm/concurrency_controller.h     |   48 +
 .../executor/paral_sm/contract_committer.h         |   79 +
 .../executor/paral_sm/contract_deployer.cpp        |  130 ++
 .../executor/paral_sm/contract_deployer.h          |   63 +
 .../executor/paral_sm/contract_deployer_test.cpp   |  119 ++
 .../executor/paral_sm/contract_executor.cpp        |   98 +
 .../executor/paral_sm/contract_executor.h          |   69 +
 .../executor/paral_sm/contract_executor_test.cpp   |  367 ++++
 .../executor/paral_sm/contract_manager.cpp         |  118 ++
 .../executor/paral_sm/contract_manager.h           |   80 +
 .../executor/paral_sm/contract_manager_test.cpp    |  260 +++
 .../thunderbolt/executor/paral_sm/d_storage.cpp    |  149 ++
 .../thunderbolt/executor/paral_sm/d_storage.h      |   37 +
 .../thunderbolt/executor/paral_sm/data_storage.cpp |   49 +
 .../thunderbolt/executor/paral_sm/data_storage.h   |   35 +
 .../thunderbolt/executor/paral_sm/db_view.cpp      |   41 +
 .../thunderbolt/executor/paral_sm/db_view.h        |   41 +
 .../thunderbolt/executor/paral_sm/evm_state.h      |   23 +
 .../thunderbolt/executor/paral_sm/executor_state.h |   54 +
 .../thunderbolt/executor/paral_sm/global_state.cpp |   48 +
 .../thunderbolt/executor/paral_sm/global_state.h   |   45 +
 .../thunderbolt/executor/paral_sm/global_view.cpp  |   25 +
 .../thunderbolt/executor/paral_sm/global_view.h    |   27 +
 .../thunderbolt/executor/paral_sm/leveldb.cpp      |   30 +
 .../thunderbolt/executor/paral_sm/leveldb.h        |   25 +
 .../thunderbolt/executor/paral_sm/local_state.cpp  |   70 +
 .../thunderbolt/executor/paral_sm/local_state.h    |   52 +
 .../thunderbolt/executor/paral_sm/local_view.cpp   |   51 +
 .../thunderbolt/executor/paral_sm/local_view.h     |   38 +
 .../executor/paral_sm/local_view_test.cpp          |  122 ++
 .../thunderbolt/executor/paral_sm/mock_d_storage.h |   54 +
 .../executor/paral_sm/mock_data_storage.h          |   47 +
 .../executor/paral_sm/mock_e_controller.h          |   50 +
 .../executor/paral_sm/streaming_e_committer.cpp    |  317 ++++
 .../executor/paral_sm/streaming_e_committer.h      |  110 ++
 .../paral_sm/streaming_e_committer_test.cpp        |  909 ++++++++++
 .../executor/paral_sm/streaming_e_controller.cpp   |  718 ++++++++
 .../executor/paral_sm/streaming_e_controller.h     |  112 ++
 .../executor/paral_sm/test_committer.cpp           |   74 +
 .../thunderbolt/executor/paral_sm/test_committer.h |   62 +
 .../executor/paral_sm/test_controller.cpp          |   38 +
 .../executor/paral_sm/test_controller.h            |   19 +
 .../thunderbolt/executor/paral_sm/test_data/BUILD  |    4 +
 .../executor/paral_sm/test_data/compile.sh         |    5 +
 .../executor/paral_sm/test_data/contract.json      |   19 +
 .../executor/paral_sm/test_data/kv.json            |   18 +
 .../thunderbolt/executor/paral_sm/test_data/kv.sol |   59 +
 .../ordering/thunderbolt/executor/paral_sm/utils.h |   36 +
 .../thunderbolt/executor/paral_sm/xcommitter.h     |  110 ++
 .../thunderbolt/executor/paral_sm/xcontroller.cpp  |  626 +++++++
 .../thunderbolt/executor/paral_sm/xcontroller.h    |   75 +
 .../thunderbolt/executor/paral_sm/xexecutor.cpp    |  286 +++
 .../thunderbolt/executor/paral_sm/xexecutor.h      |  108 ++
 .../ordering/thunderbolt/executor/service/BUILD    |   26 +
 .../service/contract_transaction_manager.cpp       |  128 ++
 .../service/contract_transaction_manager.h         |   56 +
 .../service/contract_transaction_manager_test.cpp  |  270 +++
 .../thunderbolt/executor/service/test_data/BUILD   |    1 +
 .../executor/service/test_data/contract.json       |   19 +
 .../executor/x_manager/2pl_committer.cpp           |  246 +++
 .../thunderbolt/executor/x_manager/2pl_committer.h |  106 ++
 .../executor/x_manager/2pl_controller.cpp          |  302 ++++
 .../executor/x_manager/2pl_controller.h            |  108 ++
 .../ordering/thunderbolt/executor/x_manager/BUILD  |  569 ++++++
 .../executor/x_manager/address_manager.cpp         |   83 +
 .../executor/x_manager/address_manager.h           |   58 +
 .../executor/x_manager/address_manager_test.cpp    |   58 +
 .../executor/x_manager/committer_context.cpp       |   62 +
 .../executor/x_manager/committer_context.h         |   57 +
 .../executor/x_manager/concurrency_controller.cpp  |   18 +
 .../executor/x_manager/concurrency_controller.h    |   56 +
 .../executor/x_manager/contract_committer.h        |   82 +
 .../executor/x_manager/contract_deployer.cpp       |  190 ++
 .../executor/x_manager/contract_deployer.h         |   70 +
 .../executor/x_manager/contract_deployer_test.cpp  |  119 ++
 .../executor/x_manager/contract_executor.cpp       |   98 +
 .../executor/x_manager/contract_executor.h         |   75 +
 .../executor/x_manager/contract_executor_test.cpp  |  367 ++++
 .../executor/x_manager/contract_manager.cpp        |  174 ++
 .../executor/x_manager/contract_manager.h          |   96 +
 .../executor/x_manager/contract_manager_test.cpp   |  260 +++
 .../executor/x_manager/contract_verifier.cpp       |   52 +
 .../executor/x_manager/contract_verifier.h         |   62 +
 .../thunderbolt/executor/x_manager/d_storage.cpp   |  171 ++
 .../thunderbolt/executor/x_manager/d_storage.h     |   37 +
 .../executor/x_manager/data_storage.cpp            |   81 +
 .../thunderbolt/executor/x_manager/data_storage.h  |   37 +
 .../thunderbolt/executor/x_manager/db_view.cpp     |   43 +
 .../thunderbolt/executor/x_manager/db_view.h       |   42 +
 .../executor/x_manager/dx_committer.cpp            |  270 +++
 .../thunderbolt/executor/x_manager/dx_committer.h  |  107 ++
 .../executor/x_manager/dx_controller.cpp           | 1794 +++++++++++++++++++
 .../thunderbolt/executor/x_manager/dx_controller.h |  149 ++
 .../thunderbolt/executor/x_manager/e_committer.cpp |  256 +++
 .../thunderbolt/executor/x_manager/e_committer.h   |  107 ++
 .../executor/x_manager/e_committer_test.cpp        |  293 +++
 .../executor/x_manager/e_controller.cpp            |  697 ++++++++
 .../thunderbolt/executor/x_manager/e_controller.h  |  111 ++
 .../thunderbolt/executor/x_manager/evm_state.h     |   23 +
 .../executor/x_manager/executor_state.cpp          |   75 +
 .../executor/x_manager/executor_state.h            |   54 +
 .../executor/x_manager/fx_committer.cpp            |  258 +++
 .../thunderbolt/executor/x_manager/fx_committer.h  |  107 ++
 .../executor/x_manager/fx_controller.cpp           | 1872 +++++++++++++++++++
 .../executor/x_manager/fx_controller.cpp.bak2      | 1648 +++++++++++++++++
 .../executor/x_manager/fx_controller.cpp.bak3      | 1891 ++++++++++++++++++++
 .../thunderbolt/executor/x_manager/fx_controller.h |  161 ++
 .../executor/x_manager/fx_controller.h.bak3        |  149 ++
 .../executor/x_manager/global_state.cpp            |   48 +
 .../thunderbolt/executor/x_manager/global_state.h  |   45 +
 .../thunderbolt/executor/x_manager/global_view.cpp |   25 +
 .../thunderbolt/executor/x_manager/global_view.h   |   27 +
 .../thunderbolt/executor/x_manager/leveldb.cpp     |   30 +
 .../thunderbolt/executor/x_manager/leveldb.h       |   25 +
 .../executor/x_manager/leveldb_d_storage.cpp       |  210 +++
 .../executor/x_manager/leveldb_d_storage.h         |   42 +
 .../executor/x_manager/leveldb_storage.cpp         |  121 ++
 .../executor/x_manager/leveldb_storage.h           |   43 +
 .../thunderbolt/executor/x_manager/local_state.cpp |   72 +
 .../thunderbolt/executor/x_manager/local_state.h   |   54 +
 .../thunderbolt/executor/x_manager/local_view.cpp  |   59 +
 .../thunderbolt/executor/x_manager/local_view.h    |   40 +
 .../executor/x_manager/local_view_test.cpp         |  122 ++
 .../executor/x_manager/mock_d_storage.h            |   54 +
 .../executor/x_manager/mock_data_storage.h         |   47 +
 .../executor/x_manager/mock_e_controller.h         |   50 +
 .../executor/x_manager/seq_committer.cpp           |   85 +
 .../thunderbolt/executor/x_manager/seq_committer.h |   92 +
 .../executor/x_manager/seq_controller.cpp          | 1792 +++++++++++++++++++
 .../executor/x_manager/seq_controller.h            |  149 ++
 .../executor/x_manager/streaming_e_committer.cpp   |  337 ++++
 .../executor/x_manager/streaming_e_committer.h     |  112 ++
 .../x_manager/streaming_e_committer_test.cpp       |  873 +++++++++
 .../executor/x_manager/streaming_e_controller.cpp  |  618 +++++++
 .../executor/x_manager/streaming_e_controller.h    |  153 ++
 .../executor/x_manager/test_committer.cpp          |   74 +
 .../executor/x_manager/test_committer.h            |   62 +
 .../executor/x_manager/test_controller.cpp         |   38 +
 .../executor/x_manager/test_controller.h           |   19 +
 .../thunderbolt/executor/x_manager/test_data/BUILD |    4 +
 .../executor/x_manager/test_data/compile.sh        |    5 +
 .../executor/x_manager/test_data/contract.json     |   19 +
 .../executor/x_manager/test_data/kv.json           |   18 +
 .../executor/x_manager/test_data/kv.sol            |   59 +
 .../thunderbolt/executor/x_manager/utils.h         |   36 +
 .../executor/x_manager/v_controller.cpp            |   89 +
 .../thunderbolt/executor/x_manager/v_controller.h  |   34 +
 .../thunderbolt/executor/x_manager/x_committer.cpp |  254 +++
 .../thunderbolt/executor/x_manager/x_committer.h   |  107 ++
 .../executor/x_manager/x_controller.cpp            | 1793 +++++++++++++++++++
 .../thunderbolt/executor/x_manager/x_controller.h  |  149 ++
 .../thunderbolt/executor/x_manager/x_verifier.cpp  |  214 +++
 .../thunderbolt/executor/x_manager/x_verifier.h    |   74 +
 .../consensus/ordering/thunderbolt/framework/BUILD |   19 +
 .../ordering/thunderbolt/framework/consensus.cpp   |  217 +++
 .../ordering/thunderbolt/framework/consensus.h     |   84 +
 .../thunderbolt/framework/consensus_test.cpp       |  179 ++
 .../framework/performance_manager.cpp              |  159 +-
 .../framework/performance_manager.h                |   66 +-
 .../thunderbolt/framework/response_manager.cpp     |  240 +++
 .../thunderbolt/framework/response_manager.h       |   83 +
 .../consensus/ordering/thunderbolt/proto/BUILD     |   18 +
 .../ordering/thunderbolt/proto/proposal.proto      |  101 ++
 .../consensus/ordering/thunderbolt/protocol/BUILD  |   35 +
 .../thunderbolt/protocol/proposal_manager.cpp      |  414 +++++
 .../thunderbolt/protocol/proposal_manager.h        |   76 +
 .../ordering/thunderbolt/protocol/thunderbolt.cpp  |  923 ++++++++++
 .../ordering/thunderbolt/protocol/thunderbolt.h    |  120 ++
 .../thunderbolt/protocol/transaction_collector.cpp |   55 +
 .../thunderbolt/protocol/transaction_collector.h   |   71 +
 platform/proto/resdb.proto                         |    9 +-
 scripts/deploy/config/thunderbolt.config           |   10 +
 .../deploy/performance/thunderbolt_performance.sh  |   53 +
 .../performance/thunderboltcc_performance.sh       |    2 +
 service/contract/thunderbolt_service/BUILD         |   53 +
 .../thunderbolt_service/contract_server.cpp        |  288 +++
 .../contract_transaction_manager.cpp               |  377 ++++
 .../contract_transaction_manager.h                 |   79 +
 .../thunderbolt_service/execution_helper.cpp       |  156 ++
 .../thunderbolt_service/execution_helper.h         |   71 +
 .../contract/thunderbolt_service/test_data/BUILD   |    4 +
 .../thunderbolt_service/test_data/compile.sh       |    5 +
 .../thunderbolt_service/test_data/contract.json    |   19 +
 .../contract/thunderbolt_service/test_data/kv.json |   18 +
 .../contract/thunderbolt_service/test_data/kv.sol  |   59 +
 .../thunderbolt_service/thunderbolt_service.cpp    |  189 ++
 .../thunderbolt_service/thunderbolt_service.h      |   71 +
 318 files changed, 49131 insertions(+), 113 deletions(-)

diff --git a/benchmark/bin/thunderbolt/BUILD b/benchmark/bin/thunderbolt/BUILD
new file mode 100644
index 000000000..a528a08f0
--- /dev/null
+++ b/benchmark/bin/thunderbolt/BUILD
@@ -0,0 +1,13 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_binary(
+    name = "kv_server",
+    srcs = ["kv_server.cpp"],
+    deps = [
+        "//platform/config:resdb_config_utils",
+        "//platform/consensus/ordering/thunderbolt/framework:consensus",
+        "//executor/kv:kv_executor",
+        "//chain/storage:memory_db",
+        "//service/utils:server_factory",
+    ],
+)
diff --git a/benchmark/bin/thunderbolt/kv_server.cpp b/benchmark/bin/thunderbolt/kv_server.cpp
new file mode 100644
index 000000000..1aca9a12b
--- /dev/null
+++ b/benchmark/bin/thunderbolt/kv_server.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <glog/logging.h>
+
+#include "chain/storage/memory_db.h"
+#include "executor/kv/kv_executor.h"
+#include "platform/config/resdb_config_utils.h"
+#include "platform/consensus/ordering/thunderbolt/framework/consensus.h"
+#include "platform/statistic/stats.h"
+#include "service/utils/server_factory.h"
+
+using resdb::CustomGenerateResDBServer;
+using resdb::GenerateResDBConfig;
+using resdb::KVExecutor;
+using resdb::ResConfigData;
+using resdb::ResDBConfig;
+using resdb::ResDBServer;
+using resdb::Stats;
+using resdb::storage::MemoryDB;
+using resdb::thunderbolt::ThunderboltConsensus;
+
+void ShowUsage() {
+  printf(
+      "<config> <private_key> <cert_file> <durability_option> [logging_dir]\n");
+}
+
+int main(int argc, char** argv) {
+  if (argc < 4) {
+    ShowUsage();
+    exit(0);
+  }
+
+  char* config_file = argv[1];
+  char* private_key_file = argv[2];
+  char* cert_file = argv[3];
+  char* logging_dir = nullptr;
+
+  if (argc >= 7) {
+    logging_dir = argv[5];
+  }
+
+  if (argc >= 6) {
+    auto monitor_port = Stats::GetGlobalStats(5);
+    monitor_port->SetPrometheus(argv[4]);
+  }
+
+  std::unique_ptr<ResDBConfig> config =
+      GenerateResDBConfig(config_file, private_key_file, cert_file);
+  ResConfigData config_data = config->GetConfigData();
+
+  auto server = CustomGenerateResDBServer<ThunderboltConsensus>(
+      config_file, private_key_file, cert_file,
+      std::make_unique<KVExecutor>(std::make_unique<MemoryDB>()), logging_dir);
+  server->Run();
+}
diff --git a/benchmark/protocols/thunderbolt/BUILD b/benchmark/protocols/thunderbolt/BUILD
new file mode 100644
index 000000000..09fcf2698
--- /dev/null
+++ b/benchmark/protocols/thunderbolt/BUILD
@@ -0,0 +1,25 @@
+package(default_visibility = ["//visibility:private"])
+
+load("@bazel_skylib//rules:common_settings.bzl", "bool_flag")
+
+cc_binary(
+    name = "kv_server_performance",
+    srcs = ["kv_server_performance.cpp"],
+    deps = [
+        "//chain/storage:memory_db",
+        "//executor/kv:kv_executor",
+        "//platform/config:resdb_config_utils",
+        "//platform/consensus/ordering/thunderbolt/framework:consensus",
+        "//service/utils:server_factory",
+    ],
+)
+
+cc_binary(
+    name = "kv_service_tools",
+    srcs = ["kv_service_tools.cpp"],
+    deps = [
+        "//common/proto:signature_info_cc_proto",
+        "//interface/kv:kv_client",
+        "//platform/config:resdb_config_utils",
+    ],
+)
diff --git a/benchmark/protocols/thunderbolt/kv_server_performance.cpp b/benchmark/protocols/thunderbolt/kv_server_performance.cpp
new file mode 100644
index 000000000..6693df82d
--- /dev/null
+++ b/benchmark/protocols/thunderbolt/kv_server_performance.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <glog/logging.h>
+
+#include "chain/storage/memory_db.h"
+#include "executor/kv/kv_executor.h"
+#include "platform/config/resdb_config_utils.h"
+#include "platform/consensus/ordering/thunderbolt/framework/consensus.h"
+#include "platform/networkstrate/service_network.h"
+#include "platform/statistic/stats.h"
+#include "proto/kv/kv.pb.h"
+
+using namespace resdb;
+using namespace resdb::thunderbolt;
+using namespace resdb::storage;
+
+void ShowUsage() {
+  printf("<config> <private_key> <cert_file> [logging_dir]\n");
+}
+
+std::string GetRandomKey() {
+  int num1 = rand() % 10;
+  int num2 = rand() % 10;
+  return std::to_string(num1) + std::to_string(num2);
+}
+
+int main(int argc, char** argv) {
+  if (argc < 3) {
+    ShowUsage();
+    exit(0);
+  }
+
+  // google::InitGoogleLogging(argv[0]);
+  // FLAGS_minloglevel = google::GLOG_WARNING;
+
+  char* config_file = argv[1];
+  char* private_key_file = argv[2];
+  char* cert_file = argv[3];
+
+  if (argc >= 5) {
+    auto monitor_port = Stats::GetGlobalStats(5);
+    monitor_port->SetPrometheus(argv[4]);
+  }
+
+  std::unique_ptr<ResDBConfig> config =
+      GenerateResDBConfig(config_file, private_key_file, cert_file);
+
+  config->RunningPerformance(true);
+  ResConfigData config_data = config->GetConfigData();
+
+  auto performance_consens = std::make_unique<ThunderboltConsensus>(
+      *config, std::make_unique<KVExecutor>(std::make_unique<MemoryDB>()));
+  performance_consens->SetupPerformanceDataFunc([]() {
+    KVRequest request;
+    request.set_cmd(KVRequest::SET);
+    request.set_key(GetRandomKey());
+    request.set_value("helloworld");
+    std::string request_data;
+    request.SerializeToString(&request_data);
+    return request_data;
+  });
+
+  auto server =
+      std::make_unique<ServiceNetwork>(*config, std::move(performance_consens));
+  server->Run();
+}
diff --git a/benchmark/protocols/thunderbolt/kv_service_tools.cpp b/benchmark/protocols/thunderbolt/kv_service_tools.cpp
new file mode 100644
index 000000000..17858ef21
--- /dev/null
+++ b/benchmark/protocols/thunderbolt/kv_service_tools.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+
+#include "common/proto/signature_info.pb.h"
+#include "interface/kv/kv_client.h"
+#include "platform/config/resdb_config_utils.h"
+
+using resdb::GenerateReplicaInfo;
+using resdb::GenerateResDBConfig;
+using resdb::KVClient;
+using resdb::ReplicaInfo;
+using resdb::ResDBConfig;
+
+int main(int argc, char** argv) {
+  if (argc < 2) {
+    printf("<config path>\n");
+    return 0;
+  }
+  std::string client_config_file = argv[1];
+  ResDBConfig config = GenerateResDBConfig(client_config_file);
+
+  config.SetClientTimeoutMs(100000);
+
+  KVClient client(config);
+
+  client.Set("start", "value");
+  printf("start benchmark\n");
+}
diff --git a/executor/common/transaction_manager.h b/executor/common/transaction_manager.h
index 33c23389c..294f13926 100644
--- a/executor/common/transaction_manager.h
+++ b/executor/common/transaction_manager.h
@@ -20,6 +20,7 @@
 #pragma once
 
 #include <cstdint>
+#include <functional>
 #include <memory>
 
 #include "chain/storage/storage.h"
@@ -44,6 +45,23 @@ class TransactionManager {
   virtual std::unique_ptr<BatchUserResponse> ExecuteBatch(
       const BatchUserRequest& request);
 
+  virtual std::unique_ptr<BatchUserResponse> ExecutePreparedData(
+      const BatchUserRequest&) {
+    return nullptr;
+  }
+
+  virtual void SetAsyncCallback(
+      std::function<void(const BatchUserRequest, std::unique_ptr<Request>,
+                         std::unique_ptr<BatchUserResponse>)>) {}
+
+  virtual void Attach(std::unique_ptr<Request> request) {
+    request_ = std::move(request);
+  }
+
+  virtual std::unique_ptr<Request> FetchRequest() {
+    return std::move(request_);
+  }
+
   std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>
   Prepare(const BatchUserRequest& request);
 
@@ -69,6 +87,7 @@ class TransactionManager {
   uint64_t seq_ = 0;
 
   std::unique_ptr<Storage> storage_;
+  std::unique_ptr<Request> request_;
 
  private:
   bool is_out_of_order_ = false;
diff --git a/platform/consensus/execution/transaction_executor.cpp b/platform/consensus/execution/transaction_executor.cpp
index bf29a0fb5..46b0028fc 100644
--- a/platform/consensus/execution/transaction_executor.cpp
+++ b/platform/consensus/execution/transaction_executor.cpp
@@ -320,6 +320,9 @@ void TransactionExecutor::Execute(std::unique_ptr<Request> request,
     if (execute_thread_num_ == 1) {
       response = transaction_manager_->ExecuteBatchWithSeq(request->seq(),
                                                            *batch_request_p);
+      if (request->flag() > 0 && user_func_) {
+        user_func_(request->flag());
+      }
     } else {
       std::vector<std::unique_ptr<std::string>> response_v;
 
@@ -350,6 +353,10 @@ void TransactionExecutor::Execute(std::unique_ptr<Request> request,
       }
       FinishExecute(request->seq());
 
+      if (request->flag() > 0 && user_func_) {
+        user_func_(request->flag());
+      }
+
       if (response == nullptr) {
         response = std::make_unique<BatchUserResponse>();
         for (auto& s : response_v) {
diff --git a/platform/consensus/execution/transaction_executor.h b/platform/consensus/execution/transaction_executor.h
index e181920b1..597656d27 100644
--- a/platform/consensus/execution/transaction_executor.h
+++ b/platform/consensus/execution/transaction_executor.h
@@ -72,6 +72,8 @@ class TransactionExecutor {
   void WaitForExecute(int64_t seq);
   void FinishExecute(int64_t seq);
 
+  void SetUserFunc(std::function<void(int)> func) { user_func_ = std::move(func); }
+
   void Prepare(std::unique_ptr<Request> request);
 
  private:
@@ -104,6 +106,7 @@ class TransactionExecutor {
   std::atomic<uint64_t> next_execute_seq_ = 1;
   PreExecuteFunc pre_exec_func_ = nullptr;
   SeqUpdateNotifyFunc seq_update_notify_func_ = nullptr;
+  std::function<void(int)> user_func_ = nullptr;
   PostExecuteFunc post_exec_func_ = nullptr;
   SystemInfo* system_info_ = nullptr;
   std::unique_ptr<TransactionManager> transaction_manager_ = nullptr;
diff --git a/platform/consensus/ordering/common/framework/performance_manager.cpp b/platform/consensus/ordering/common/framework/performance_manager.cpp
index 21454e4b5..86fd1ddcb 100644
--- a/platform/consensus/ordering/common/framework/performance_manager.cpp
+++ b/platform/consensus/ordering/common/framework/performance_manager.cpp
@@ -93,6 +93,11 @@ void PerformanceManager::SetDataFunc(std::function<std::string()> func) {
   data_func_ = std::move(func);
 }
 
+void PerformanceManager::SetPreprocessFunc(
+    std::function<std::vector<std::string>()> preprocess_func) {
+  preprocess_func_ = std::move(preprocess_func);
+}
+
 int PerformanceManager::StartEval() {
   if (eval_started_) {
     return 0;
diff --git a/platform/consensus/ordering/common/framework/performance_manager.h b/platform/consensus/ordering/common/framework/performance_manager.h
index dba5fd8f8..3a6441f6f 100644
--- a/platform/consensus/ordering/common/framework/performance_manager.h
+++ b/platform/consensus/ordering/common/framework/performance_manager.h
@@ -46,6 +46,8 @@ class PerformanceManager {
   int ProcessResponseMsg(std::unique_ptr<Context> context,
                          std::unique_ptr<Request> request);
   void SetDataFunc(std::function<std::string()> func);
+  void SetPreprocessFunc(
+      std::function<std::vector<std::string>()> preprocess_func);
 
  protected:
   virtual void SendMessage(const Request& request);
@@ -85,6 +87,7 @@ class PerformanceManager {
   SignatureVerifier* verifier_;
   SignatureInfo sig_;
   std::function<std::string()> data_func_;
+  std::function<std::vector<std::string>()> preprocess_func_;
   std::future<bool> eval_ready_future_;
   std::promise<bool> eval_ready_promise_;
   std::atomic<int64_t> eval_ready_counter_{0};
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/BUILD b/platform/consensus/ordering/thunderbolt/algorithm/BUILD
new file mode 100644
index 000000000..289235db4
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/BUILD
@@ -0,0 +1,36 @@
+package(default_visibility = ["//platform/consensus/ordering/thunderbolt:__subpackages__"])
+
+cc_library(
+    name = "proposal_manager",
+    srcs = ["proposal_manager.cpp"],
+    hdrs = ["proposal_manager.h"],
+    deps = [
+        "//common:comm",
+        "//common/crypto:signature_verifier",
+        "//common/utils",
+        "//platform/consensus/ordering/thunderbolt/proto:proposal_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "thunderbolt",
+    srcs = ["thunderbolt.cpp"],
+    hdrs = ["thunderbolt.h"],
+    deps = [
+        ":proposal_manager",
+        "//common:comm",
+        "//common/crypto:signature_verifier",
+        "//platform/common/queue:lock_free_queue",
+        "//platform/consensus/ordering/common/algorithm:protocol_base",
+        "//platform/statistic:stats",
+    ],
+)
+
+cc_library(
+    name = "transaction_collector",
+    srcs = ["transaction_collector.cpp"],
+    hdrs = ["transaction_collector.h"],
+    deps = [
+        "//platform/statistic:stats",
+    ],
+)
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.cpp b/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.cpp
new file mode 100644
index 000000000..6679baefc
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.cpp
@@ -0,0 +1,258 @@
+#include "platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.h"
+
+#include <glog/logging.h>
+
+#include "common/crypto/signature_verifier.h"
+#include "common/utils/utils.h"
+
+namespace resdb {
+namespace thunderbolt {
+
+ProposalManager::ProposalManager(int32_t id, int limit_count)
+    : id_(id), limit_count_(limit_count) {
+  round_ = 0;
+}
+
+bool ProposalManager::VerifyHash(const Proposal& proposal) {
+  std::string data;
+  for (const auto& txn : proposal.transactions()) {
+    std::string tmp;
+    txn.SerializeToString(&tmp);
+    data += tmp;
+  }
+
+  std::string header_data;
+  proposal.header().SerializeToString(&header_data);
+  data += header_data;
+
+  std::string hash = SignatureVerifier::CalculateHash(data);
+  return hash == proposal.hash();
+}
+
+std::unique_ptr<Proposal> ProposalManager::GenerateProposal(
+    const std::vector<std::unique_ptr<Transaction>>& txns) {
+  std::unique_ptr<Proposal> proposal = std::make_unique<Proposal>();
+  std::string data;
+  {
+    std::unique_lock<std::mutex> lk(txn_mutex_);
+    for (const auto& txn : txns) {
+      *proposal->add_transactions() = *txn;
+      std::string tmp;
+      txn->SerializeToString(&tmp);
+      data += tmp;
+    }
+    proposal->mutable_header()->set_proposer_id(id_);
+    proposal->mutable_header()->set_create_time(GetCurrentTime());
+    proposal->mutable_header()->set_round(round_);
+    proposal->set_sender(id_);
+
+    GetMetaData(proposal.get());
+  }
+
+  std::string header_data;
+  proposal->header().SerializeToString(&header_data);
+  data += header_data;
+
+  std::string hash = SignatureVerifier::CalculateHash(data);
+  proposal->set_hash(hash);
+
+  round_++;
+  return proposal;
+}
+
+int ProposalManager::CurrentRound() { return round_; }
+
+void ProposalManager::AddLocalBlock(std::unique_ptr<Proposal> proposal) {
+  std::unique_lock<std::mutex> lk(local_mutex_);
+  local_block_[proposal->hash()] = std::move(proposal);
+}
+
+const Proposal* ProposalManager::GetLocalBlock(const std::string& hash) {
+  std::unique_lock<std::mutex> lk(local_mutex_);
+  auto bit = local_block_.find(hash);
+  if (bit == local_block_.end()) {
+    LOG(ERROR) << " block not exist:" << hash.size();
+    return nullptr;
+  }
+  return bit->second.get();
+}
+
+std::unique_ptr<Proposal> ProposalManager::FetchLocalBlock(
+    const std::string& hash) {
+  std::unique_lock<std::mutex> lk(local_mutex_);
+  auto bit = local_block_.find(hash);
+  if (bit == local_block_.end()) {
+    // LOG(ERROR) << " block not exist:" << hash.size();
+    return nullptr;
+  }
+  auto tmp = std::move(bit->second);
+  local_block_.erase(bit);
+  return tmp;
+}
+
+void ProposalManager::AddBlock(std::unique_ptr<Proposal> proposal) {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  // LOG(ERROR) << "add block hash :" << proposal->hash().size()
+  //            << " round:" << proposal->header().round()
+  //            << " proposer:" << proposal->header().proposer_id();
+  block_[proposal->hash()] = std::move(proposal);
+}
+
+bool ProposalManager::CheckBlock(const std::string& hash) {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  // LOG(ERROR)<<"add block hash :"<<proposal->hash().size()<<"
+  // round:"<<proposal->header().round()<<"
+  // proposer:"<<proposal->header().proposer_id();
+  return block_.find(hash) != block_.end();
+}
+
+int ProposalManager::GetReferenceNum(const Proposal& req) {
+  int round = req.header().round();
+  int proposer = req.header().proposer_id();
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  return reference_[std::make_pair(round, proposer)];
+}
+
+std::unique_ptr<Proposal> ProposalManager::FetchRequest(int round, int sender) {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  auto it = cert_list_[round].find(sender);
+  if (it == cert_list_[round].end()) {
+    // LOG(ERROR)<<" cert from sender:"<<sender<<" round:"<<round<<" not exist";
+    return nullptr;
+  }
+  std::string hash = it->second->hash();
+  auto bit = block_.find(hash);
+  if (bit == block_.end()) {
+    LOG(ERROR) << " block from sender:" << sender << " round:" << round
+               << " not exist";
+    assert(1 == 0);
+    return nullptr;
+  }
+  auto tmp = std::move(bit->second);
+  // cert_list_[round].erase(sender);
+  // LOG(ERROR)<<" featch sender done, round:"<<round<<" sender:"<<sender;
+  if (sender == id_) {
+    FetchLocalBlock(hash);
+  }
+  return tmp;
+}
+
+const Proposal* ProposalManager::GetRequest(int round, int sender) {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  auto it = cert_list_[round].find(sender);
+  if (it == cert_list_[round].end()) {
+    // LOG(ERROR) << " cert from sender:" << sender << " round:" << round
+    //           << " not exist";
+    return nullptr;
+  }
+  std::string hash = it->second->hash();
+  auto bit = block_.find(hash);
+  if (bit == block_.end()) {
+    LOG(ERROR) << " block from sender:" << sender << " round:" << round
+               << " not exist";
+    return nullptr;
+  }
+  return bit->second.get();
+}
+
+void ProposalManager::AddCert(std::unique_ptr<Certificate> cert) {
+  int proposer = cert->proposer();
+  int round = cert->round();
+  std::string hash = cert->hash();
+
+  // LOG(ERROR)<<"add cert sender:"<<proposer<<" round:"<<round;
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+
+  // LOG(ERROR)<<"strong cert size:"<<cert->strong_cert().cert_size();
+  for (auto& link : cert->strong_cert().cert()) {
+    int link_round = link.round();
+    int link_proposer = link.proposer();
+    // LOG(ERROR)<<"refer round:"<<link_round<<" proposer:"<<link_proposer;
+    reference_[std::make_pair(link_round, link_proposer)]++;
+  }
+
+  cert->mutable_strong_cert()->Clear();
+  cert->mutable_metadata()->Clear();
+
+  auto tmp = std::make_unique<Certificate>(*cert);
+  cert_list_[round][proposer] = std::move(cert);
+  latest_cert_from_sender_[proposer] = std::move(tmp);
+}
+
+bool ProposalManager::CheckCert(int round, int sender) {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  return cert_list_[round].find(sender) != cert_list_[round].end();
+}
+
+void ProposalManager::GetMetaData(Proposal* proposal) {
+  if (round_ == 0) {
+    return;
+  }
+  assert(cert_list_[round_ - 1].size() >= limit_count_);
+  assert(cert_list_[round_ - 1].find(id_) != cert_list_[round_ - 1].end());
+
+  // LOG(ERROR)<<"get metadata:"<<" proposal
+  // round:"<<proposal->header().round();
+  std::set<int> meta_ids;
+  for (const auto& preview_cert : cert_list_[round_ - 1]) {
+    *proposal->mutable_header()->mutable_strong_cert()->add_cert() =
+        *preview_cert.second;
+    meta_ids.insert(preview_cert.first);
+    // LOG(ERROR)<<"add strong round:"<<preview_cert.second->round()
+    //<<" id:"<<preview_cert.second->proposer()<<"
+    //first:"<<preview_cert.first<<" limit:"<<limit_count_<<" proposal
+    //round:"<<proposal->header().round();
+    if (meta_ids.size() == limit_count_) {
+      break;
+    }
+  }
+  // LOG(ERROR)<<"strong link:"<<proposal->header().strong_cert().cert_size()<<"
+  // round:"<<proposal->header().round();
+
+  for (const auto& meta : latest_cert_from_sender_) {
+    // LOG(ERROR)<<"check:"<<meta.first<<" proposal
+    // round:"<<proposal->header().round();
+    if (meta_ids.find(meta.first) != meta_ids.end()) {
+      continue;
+    }
+    if (meta.second->round() >= round_) {
+      for (int j = round_ - 1; j >= 0; --j) {
+        if (cert_list_[j].find(meta.first) != cert_list_[j].end()) {
+          // LOG(ERROR) << " add weak cert from his:" << j
+          //           << " proposer:" << meta.first<< " cert
+          //           round:"<<cert_list_[j][meta.first]->round()<< " proposal
+          //           round:"<<proposal->header().round();
+          *proposal->mutable_header()->mutable_weak_cert()->add_cert() =
+              *cert_list_[j][meta.first];
+          break;
+        }
+      }
+    } else {
+      assert(meta.second->round() <= round_);
+      // LOG(ERROR)<<"add weak cert:"<<meta.second->round()<<"
+      // proposer:"<<meta.second->proposer()<<" proposal
+      // round:"<<proposal->header().round();
+      *proposal->mutable_header()->mutable_weak_cert()->add_cert() =
+          *meta.second;
+    }
+  }
+  // LOG(ERROR)<<"weak link:"<<proposal->header().weak_cert().cert_size()<<"
+  // round:"<<proposal->header().round();
+}
+
+bool ProposalManager::Ready() {
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  if (round_ == 0) {
+    return true;
+  }
+  if (cert_list_[round_ - 1].size() < limit_count_) {
+    return false;
+  }
+  if (cert_list_[round_ - 1].find(id_) == cert_list_[round_ - 1].end()) {
+    return false;
+  }
+  return true;
+}
+
+}  // namespace thunderbolt
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.h b/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.h
new file mode 100644
index 000000000..344562c42
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.h
@@ -0,0 +1,54 @@
+#pragma once
+
+#include "platform/consensus/ordering/thunderbolt/proto/proposal.pb.h"
+
+namespace resdb {
+namespace thunderbolt {
+
+class ProposalManager {
+ public:
+  ProposalManager(int32_t id, int limit_count);
+
+  std::unique_ptr<Proposal> GenerateProposal(
+      const std::vector<std::unique_ptr<Transaction>>& txns);
+
+  int CurrentRound();
+  void AddLocalBlock(std::unique_ptr<Proposal> proposal);
+  const Proposal* GetLocalBlock(const std::string& hash);
+  std::unique_ptr<Proposal> FetchLocalBlock(const std::string& hash);
+
+  void AddBlock(std::unique_ptr<Proposal> proposal);
+  void AddCert(std::unique_ptr<Certificate> cert);
+  bool Ready();
+
+  const Proposal* GetRequest(int round, int sender);
+  std::unique_ptr<Proposal> FetchRequest(int round, int sender);
+  int GetReferenceNum(const Proposal& req);
+
+  bool VerifyHash(const Proposal& proposal);
+
+  bool CheckCert(int round, int sender);
+  bool CheckBlock(const std::string& hash);
+
+  void SetCommittedRound(int r);
+
+ protected:
+  void GetMetaData(Proposal* proposal);
+
+ private:
+  int32_t id_;
+  int round_;
+  int limit_count_;
+  std::map<std::string, std::unique_ptr<Proposal>> block_, local_block_;
+
+  std::map<int64_t, std::map<int, std::unique_ptr<Certificate>>> cert_list_;
+  std::map<int, std::unique_ptr<Certificate>> latest_cert_from_sender_;
+
+  std::mutex txn_mutex_, local_mutex_;
+  std::map<std::pair<int, int>, int> reference_;
+
+  std::atomic<int> committed_round_ = 0;
+};
+
+}  // namespace thunderbolt
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.cpp b/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.cpp
new file mode 100644
index 000000000..64cf81034
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.cpp
@@ -0,0 +1,555 @@
+#include "platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.h"
+
+#include <glog/logging.h>
+
+#include "common/utils/utils.h"
+
+namespace resdb {
+namespace thunderbolt {
+
+Thunderbolt::Thunderbolt(int id, int f, int total_num, SignatureVerifier* verifier)
+    : ProtocolBase(id, f, total_num), verifier_(verifier) {
+  limit_count_ = 2 * f + 1;
+  batch_size_ = 5;
+  proposal_manager_ = std::make_unique<ProposalManager>(id, limit_count_);
+
+  execute_id_ = 1;
+  start_ = 0;
+  queue_size_ = 0;
+
+  send_thread_ = std::thread(&Thunderbolt::AsyncSend, this);
+  commit_thread_ = std::thread(&Thunderbolt::AsyncCommit, this);
+  execute_thread_ = std::thread(&Thunderbolt::AsyncExecute, this);
+  cert_thread_ = std::thread(&Thunderbolt::AsyncProcessCert, this);
+
+  global_stats_ = Stats::GetGlobalStats();
+
+  LOG(ERROR) << "id:" << id << " f:" << f << " total:" << total_num;
+}
+
+Thunderbolt::~Thunderbolt() {
+  if (send_thread_.joinable()) {
+    send_thread_.join();
+  }
+  if (commit_thread_.joinable()) {
+    commit_thread_.join();
+  }
+  if (cert_thread_.joinable()) {
+    cert_thread_.join();
+  }
+}
+
+int Thunderbolt::GetLeader(int64_t r) { return r / 2 % total_num_ + 1; }
+
+void Thunderbolt::AsyncSend() {
+  uint64_t last_time = 0;
+  while (!IsStop()) {
+    auto txn = txns_.Pop();
+    if (txn == nullptr) {
+      if (start_) {
+        // LOG(ERROR)<<"not enough txn";
+        // break;
+      }
+      continue;
+    }
+
+    queue_size_--;
+    // LOG(ERROR)<<"txn before waiting time:"<<GetCurrentTime() -
+    // txn->create_time()<<" queue size:"<<queue_size_;
+    while (!IsStop()) {
+      int current_round = proposal_manager_->CurrentRound();
+      std::unique_lock<std::mutex> lk(mutex_);
+      vote_cv_.wait_for(lk, std::chrono::microseconds(10000),
+                        [&] { return proposal_manager_->Ready(); });
+
+      if (proposal_manager_->Ready()) {
+        start_ = 1;
+        break;
+      }
+    }
+
+    // LOG(ERROR)<<"txn waiting time:"<<GetCurrentTime() - txn->create_time();
+    txn->set_queuing_time(GetCurrentTime() - txn->create_time());
+    global_stats_->AddQueuingLatency(GetCurrentTime() - txn->create_time());
+    global_stats_->AddRoundLatency(GetCurrentTime() - last_time);
+    last_time = GetCurrentTime();
+
+    std::vector<std::unique_ptr<Transaction>> txns;
+    txns.push_back(std::move(txn));
+    for (int i = 1; i < batch_size_; ++i) {
+      auto txn = txns_.Pop(10);
+      if (txn == nullptr) {
+        continue;
+        break;
+      }
+      txn->set_queuing_time(GetCurrentTime() - txn->create_time());
+      queue_size_--;
+      global_stats_->AddQueuingLatency(GetCurrentTime() - txn->create_time());
+      txns.push_back(std::move(txn));
+    }
+
+    global_stats_->ConsumeTransactions(queue_size_);
+
+    auto proposal = proposal_manager_->GenerateProposal(txns);
+    Broadcast(MessageType::NewBlock, *proposal);
+
+    std::string block_data;
+    proposal->SerializeToString(&block_data);
+    global_stats_->AddBlockSize(block_data.size());
+
+    proposal_manager_->AddLocalBlock(std::move(proposal));
+
+    int round = proposal_manager_->CurrentRound() - 1;
+    // LOG(ERROR) << "bc txn:" << txns.size() << " round:" << round;
+    if (round > 1) {
+      if (round % 2 == 0) {
+        CommitRound(round - 2);
+      }
+    }
+  }
+}
+
+void Thunderbolt::AsyncCommit() {
+  int previous_round = -2;
+  while (!IsStop()) {
+    std::unique_ptr<int> round_or = commit_queue_.Pop();
+    if (round_or == nullptr) {
+      continue;
+    }
+
+    int round = *round_or;
+    // int64_t start_time = GetCurrentTime();
+    // LOG(ERROR) << "commit round:" << round;
+
+    int new_round = previous_round;
+    for (int r = previous_round + 2; r <= round; r += 2) {
+      int leader = GetLeader(r);
+      const Proposal* req = nullptr;
+      while (!IsStop()) {
+        req = proposal_manager_->GetRequest(r, leader);
+        // req:"<<(req==nullptr);
+        if (req == nullptr) {
+          // LOG(ERROR)<<" get leader:"<<leader<<" round:"<<r<<" not exit";
+          // usleep(1000);
+          std::unique_lock<std::mutex> lk(mutex_);
+          vote_cv_.wait_for(lk, std::chrono::microseconds(100),
+                            [&] { return true; });
+
+          continue;
+        }
+        break;
+      }
+      // LOG(ERROR)<<" get leader:"<<leader<<" round:"<<r<<"
+      // delay:"<<(GetCurrentTime() - req->header().create_time());
+      int reference_num = proposal_manager_->GetReferenceNum(*req);
+      // LOG(ERROR)<<" get leader:"<<leader<<" round:"<<r<<"
+      // ref:"<<reference_num;
+      if (reference_num < limit_count_) {
+        continue;
+      } else {
+        // LOG(ERROR) << "go to commit r:" << r << " previous:" <<
+        // previous_round;
+        for (int j = new_round + 2; j <= r; j += 2) {
+          int pre_leader = GetLeader(j);
+
+          auto req = proposal_manager_->GetRequest(j, pre_leader);
+          if (req == nullptr) {
+            continue;
+          }
+          int reference_num = proposal_manager_->GetReferenceNum(*req);
+          if (reference_num < limit_count_) {
+            continue;
+          }
+
+          CommitProposal(j, pre_leader);
+        }
+      }
+      new_round = r;
+    }
+    // int64_t end_time = GetCurrentTime();
+    // global_stats_->AddCommitRuntime(end_time-commit_time);
+    previous_round = new_round;
+  }
+}
+
+void Thunderbolt::AsyncExecute() {
+  int64_t last_commit_time = 0;
+  int last_round = 0;
+  while (!IsStop()) {
+    std::unique_ptr<Proposal> proposal = execute_queue_.Pop();
+    if (proposal == nullptr) {
+      continue;
+    }
+
+    int commit_round = proposal->header().round();
+    int64_t commit_time = GetCurrentTime();
+    int64_t waiting_time = commit_time - proposal->queuing_time();
+    global_stats_->AddCommitQueuingLatency(waiting_time);
+    // global_stats_->AddCommitInterval(commit_time - last_commit_time);
+    // last_commit_time = commit_time;
+    std::map<int, std::vector<std::unique_ptr<Proposal>>> ps;
+    std::queue<std::unique_ptr<Proposal>> q;
+    q.push(std::move(proposal));
+
+    // LOG(ERROR)<<" commit round:"<<commit_round;
+    // proposal_manager_->SetCommittedRound(commit_round);
+
+    // global_stats_->AddCommitRoundLatency(commit_round - last_round);
+    // last_round = commit_round;
+
+    // int64_t start_time = GetCurrentTime();
+    while (!q.empty()) {
+      std::unique_ptr<Proposal> p = std::move(q.front());
+      q.pop();
+
+      for (auto& link : p->header().strong_cert().cert()) {
+        int link_round = link.round();
+        int link_proposer = link.proposer();
+        auto next_p =
+            proposal_manager_->FetchRequest(link_round, link_proposer);
+        if (next_p == nullptr) {
+          continue;
+        }
+        q.push(std::move(next_p));
+      }
+
+      for (auto& link : p->header().weak_cert().cert()) {
+        int link_round = link.round();
+        int link_proposer = link.proposer();
+        auto next_p =
+            proposal_manager_->FetchRequest(link_round, link_proposer);
+        if (next_p == nullptr) {
+          // LOG(ERROR)<<"no data round:"<<link_round<<" link
+          // proposer:"<<link_proposer;
+          continue;
+        }
+        q.push(std::move(next_p));
+      }
+      ps[p->header().round()].push_back(std::move(p));
+    }
+
+    int num = 0;
+    int pro = 0;
+    for (auto& it : ps) {
+      for (auto& p : it.second) {
+        // LOG(ERROR) << "=============== commit proposal round :"
+        //           << p->header().round()
+        //           << " header round:"<<p->header().round()
+        //           << " commit round:"<<commit_round
+        //           << " proposer:" << p->header().proposer_id()
+        //           << " transaction size:" << p->transactions_size()
+        //           << " commit time:"
+        //           << (GetCurrentTime() - p->header().create_time())
+        //           << " create time:" << p->header().create_time()
+        //           <<" execute id:"<<execute_id_
+        //          <<" round delay:"<<(commit_round - p->header().round());
+
+        global_stats_->AddCommitLatency(
+            commit_time - p->header().create_time() - waiting_time);
+        global_stats_->AddCommitRoundLatency(commit_round -
+                                             p->header().round());
+        for (auto& tx : *p->mutable_transactions()) {
+          tx.set_id(execute_id_++);
+          num++;
+          // LOG(ERROR)<<" commit txn create time:"<<tx.create_time();
+          Commit(tx);
+        }
+        pro++;
+      }
+    }
+    int64_t end_time = GetCurrentTime();
+    global_stats_->AddCommitRuntime(end_time - commit_time);
+    global_stats_->AddCommitTxn(num);
+    global_stats_->AddCommitBlock(pro);
+  }
+}
+
+void Thunderbolt::CommitProposal(int round, int proposer) {
+  // LOG(ERROR) << "commit round:" << round << " proposer:" << proposer;
+
+  // int64_t last_commit_time = 0;
+  int64_t commit_time = GetCurrentTime();
+  global_stats_->AddCommitInterval(commit_time - last_commit_time_);
+  last_commit_time_ = commit_time;
+
+  std::unique_ptr<Proposal> p =
+      proposal_manager_->FetchRequest(round, proposer);
+  if (p == nullptr) {
+    LOG(ERROR) << "commit round:" << round << " proposer:" << proposer
+               << " not exist";
+    assert(1 == 0);
+    return;
+  }
+  assert(p != nullptr);
+  p->set_queuing_time(GetCurrentTime());
+  execute_queue_.Push(std::move(p));
+}
+
+void Thunderbolt::CommitRound(int round) {
+  // LOG(ERROR)<<" commit round:"<<round;
+  commit_queue_.Push(std::make_unique<int>(round));
+}
+
+bool Thunderbolt::ReceiveTransaction(std::unique_ptr<Transaction> txn) {
+  //  LOG(ERROR)<<"recv txn";
+  txn->set_create_time(GetCurrentTime());
+  txns_.Push(std::move(txn));
+  queue_size_++;
+  if (start_ == 0) {
+    std::unique_lock<std::mutex> lk(mutex_);
+    vote_cv_.notify_all();
+  }
+  return true;
+}
+
+bool Thunderbolt::ReceiveBlock(std::unique_ptr<Proposal> proposal) {
+  // LOG(ERROR) << "recv block from " << proposal->header().proposer_id()
+  //           << " round:" << proposal->header().round();
+
+  std::unique_lock<std::mutex> lk(check_block_mutex_);
+  {
+    proposal->set_queuing_time(GetCurrentTime());
+    // std::unique_lock<std::mutex> lk(check_block_mutex_);
+    if (!CheckBlock(*proposal)) {
+      std::unique_lock<std::mutex> lk(future_block_mutex_);
+      // LOG(ERROR)<<"add future block:"<<proposal->header().round()<<"
+      // sender:"<<proposal->header().proposer_id();
+      future_block_[proposal->header().round()][proposal->hash()] =
+          std::move(proposal);
+      return false;
+    }
+  }
+  return SendBlockAck(std::move(proposal));
+}
+
+void Thunderbolt::ReceiveBlockACK(std::unique_ptr<Metadata> metadata) {
+  std::string hash = metadata->hash();
+  int round = metadata->round();
+  int sender = metadata->sender();
+  std::unique_lock<std::mutex> lk(txn_mutex_);
+  received_num_[hash][sender] = std::move(metadata);
+  // LOG(ERROR) << "recv block ack from:" << sender << " num:" <<
+  // received_num_[hash].size()<<" round:"<<round;
+  if (received_num_[hash].size() == limit_count_) {
+    Certificate cert;
+    for (auto& it : received_num_[hash]) {
+      *cert.add_metadata() = *it.second;
+    }
+    cert.set_hash(hash);
+    cert.set_round(round);
+    cert.set_proposer(id_);
+    const Proposal* p = proposal_manager_->GetLocalBlock(hash);
+    assert(p != nullptr);
+    assert(p->header().proposer_id() == id_);
+    assert(p->header().round() == round);
+    global_stats_->AddExecutePrepareDelay(GetCurrentTime() -
+                                          p->header().create_time());
+    // global_stats_->AddCommitLatency(GetCurrentTime() -
+    // p->header().create_time());
+    *cert.mutable_strong_cert() = p->header().strong_cert();
+    // LOG(ERROR)<<"send cert, round:"<<p->header().round();
+    Broadcast(MessageType::Cert, cert);
+  }
+}
+
+bool Thunderbolt::VerifyCert(const Certificate& cert) {
+  std::map<std::string, int> hash_num;
+  bool vote_num = false;
+  for (auto& metadata : cert.metadata()) {
+    bool valid = verifier_->VerifyMessage(metadata.hash(), metadata.sign());
+    if (!valid) {
+      return false;
+    }
+    hash_num[metadata.hash()]++;
+    if (hash_num[metadata.hash()] >= 2 * f_ + 1) {
+      vote_num = true;
+    }
+  }
+  return vote_num;
+}
+
+bool Thunderbolt::CheckBlock(const Proposal& p) {
+  for (auto& link : p.header().strong_cert().cert()) {
+    int link_round = link.round();
+    int link_proposer = link.proposer();
+    if (!proposal_manager_->CheckCert(link_round, link_proposer)) {
+      // LOG(ERROR)<<" check block round:"<<p.header().round()<<"
+      // proposer:"<<p.header().proposer_id()<<" strong link:"<<link_proposer<<"
+      // link round:"<<link_round<<" not exist";
+      return false;
+    }
+  }
+
+  for (auto& link : p.header().weak_cert().cert()) {
+    int link_round = link.round();
+    int link_proposer = link.proposer();
+    if (!proposal_manager_->CheckCert(link_round, link_proposer)) {
+      // LOG(ERROR)<<" check block round:"<<p.header().round()<<"
+      // proposer:"<<p.header().proposer_id()<<" weak link:"<<link_proposer<<"
+      // link round:"<<link_round<<" not exist";
+      return false;
+    }
+  }
+  // LOG(ERROR)<<" check cert round:"<<p.header().round()<<"
+  // proposer:"<<p.header().proposer_id()<<" strong link
+  // size:"<<p.header().strong_cert().cert_size()<<" weak link
+  // size:"<<p.header().weak_cert().cert_size();
+  return true;
+}
+
+bool Thunderbolt::CheckCert(const Certificate& cert) {
+  if (!proposal_manager_->CheckBlock(cert.hash())) {
+    // future_cert_[cert->round()][cert->hash()] = std::move(cert);
+    return false;
+  }
+  return true;
+}
+
+bool Thunderbolt::SendBlockAck(std::unique_ptr<Proposal> proposal) {
+  Metadata metadata;
+  metadata.set_sender(id_);
+  metadata.set_hash(proposal->hash());
+  metadata.set_round(proposal->header().round());
+  metadata.set_proposer(proposal->header().proposer_id());
+
+  std::string data_str = proposal->hash();
+  auto hash_signature_or = verifier_->SignMessage(data_str);
+  if (!hash_signature_or.ok()) {
+    LOG(ERROR) << "Sign message fail";
+    return false;
+  }
+  *metadata.mutable_sign() = *hash_signature_or;
+  metadata.set_sender(id_);
+
+  {
+    // std::unique_lock<std::mutex> lk(txn_mutex_);
+    // LOG(ERROR) << "recv block from " << proposal->header().proposer_id()
+    //         << " round:" << proposal->header().round();
+    int round = proposal->header().round();
+    std::string hash = proposal->hash();
+    int proposer = proposal->header().proposer_id();
+    global_stats_->AddCommitWaitingLatency(GetCurrentTime() -
+                                           proposal->queuing_time());
+    proposal->set_queuing_time(0);
+    {
+      // std::unique_lock<std::mutex> lk(check_block_mutex_);
+      proposal_manager_->AddBlock(std::move(proposal));
+      CheckFutureCert(round, hash, proposer);
+    }
+  }
+  SendMessage(MessageType::BlockACK, metadata, metadata.proposer());
+  return true;
+}
+
+void Thunderbolt::CheckFutureBlock(int round) {
+  // LOG(ERROR)<<" check block round from cert:"<<round;
+  std::map<std::string, std::unique_ptr<Proposal>> hashs;
+  {
+    std::unique_lock<std::mutex> lk(future_block_mutex_);
+    if (future_block_.find(round) == future_block_.end()) {
+      return;
+    }
+    for (auto& it : future_block_[round]) {
+      if (CheckBlock(*it.second)) {
+        // LOG(ERROR)<<" add new block round:"<<it.second->header().round();
+        hashs[it.first] = std::move(it.second);
+      }
+    }
+
+    // LOG(ERROR)<<" check round:"<<round<<" hash size:"<<hashs.size();
+    for (auto& it : hashs) {
+      future_block_[round].erase(future_block_[round].find(it.first));
+    }
+
+    if (future_block_[round].size() == 0) {
+      future_block_.erase(future_block_.find(round));
+    }
+  }
+
+  for (auto& it : hashs) {
+    // LOG(ERROR)<<"send future block round:"<<it.second->header().round()<<"
+    // proposer:"<<it.second->header().proposer_id();
+    int block_round = it.second->header().round();
+    // std::unique_lock<std::mutex> lk(check_block_mutex_);
+    {
+      std::unique_lock<std::mutex> lk(future_cert_mutex_);
+      if (future_cert_[block_round].find(it.first) !=
+          future_cert_[block_round].end()) {
+        std::unique_ptr<Certificate> cert =
+            std::move(future_cert_[block_round][it.first]);
+        // LOG(ERROR)<<" add new cert:"<<block_round<<"
+        // from:"<<cert->proposer();
+        cert_queue_.Push(std::move(cert));
+        future_cert_[block_round].erase(
+            future_cert_[block_round].find(it.first));
+        if (future_cert_[block_round].size() == 0) {
+          future_cert_.erase(future_cert_.find(block_round));
+        }
+      }
+    }
+    SendBlockAck(std::move(it.second));
+  }
+}
+
+void Thunderbolt::CheckFutureCert(int round, const std::string& hash, int proposer) {
+  std::unique_lock<std::mutex> lk(future_cert_mutex_);
+  auto it = future_cert_[round].find(hash);
+  if (it != future_cert_[round].end()) {
+    // LOG(ERROR)<<" add back future cert, round:"<<round<<"
+    // proposer:"<<proposer;
+    cert_queue_.Push(std::move(it->second));
+    future_cert_[round].erase(it);
+    if (future_cert_[round].empty()) {
+      future_cert_.erase(future_cert_.find(round));
+    }
+  }
+}
+
+void Thunderbolt::AsyncProcessCert() {
+  while (!IsStop()) {
+    std::unique_ptr<Certificate> cert = cert_queue_.Pop();
+    if (cert == nullptr) {
+      continue;
+    }
+
+    int round = cert->round();
+    int cert_sender = cert->proposer();
+
+    // LOG(ERROR)<<" add cert, round:"<<round<<" from:"<<cert_sender;
+    std::unique_lock<std::mutex> clk(check_block_mutex_);
+    proposal_manager_->AddCert(std::move(cert));
+    {
+      std::unique_lock<std::mutex> lk(mutex_);
+      vote_cv_.notify_all();
+    }
+
+    CheckFutureBlock(round + 1);
+  }
+}
+
+void Thunderbolt::ReceiveBlockCert(std::unique_ptr<Certificate> cert) {
+  int64_t start_time = GetCurrentTime();
+  if (!VerifyCert(*cert)) {
+    assert(1 == 0);
+    return;
+  }
+
+  int64_t end_time = GetCurrentTime();
+  global_stats_->AddVerifyLatency(end_time - start_time);
+
+  {
+    std::unique_lock<std::mutex> lk(check_block_mutex_);
+    if (!CheckCert(*cert)) {
+      // LOG(ERROR)<<" add future cert round:"<<cert->round()<<"
+      // proposer:"<<cert->proposer();
+      std::unique_lock<std::mutex> lk(future_cert_mutex_);
+      future_cert_[cert->round()][cert->hash()] = std::move(cert);
+      return;
+    }
+  }
+
+  cert_queue_.Push(std::move(cert));
+}
+
+}  // namespace thunderbolt
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.h b/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.h
new file mode 100644
index 000000000..63fd2009f
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/thunderbolt.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <deque>
+#include <map>
+#include <queue>
+#include <thread>
+
+#include "common/crypto/signature_verifier.h"
+#include "platform/common/queue/lock_free_queue.h"
+#include "platform/consensus/ordering/common/algorithm/protocol_base.h"
+#include "platform/consensus/ordering/thunderbolt/algorithm/proposal_manager.h"
+#include "platform/consensus/ordering/thunderbolt/proto/proposal.pb.h"
+#include "platform/statistic/stats.h"
+
+namespace resdb {
+namespace thunderbolt {
+
+class Thunderbolt : public common::ProtocolBase {
+ public:
+  Thunderbolt(int id, int f, int total_num, SignatureVerifier* verifier);
+  ~Thunderbolt();
+
+  bool ReceiveTransaction(std::unique_ptr<Transaction> txn);
+  bool ReceiveBlock(std::unique_ptr<Proposal> proposal);
+  void ReceiveBlockACK(std::unique_ptr<Metadata> metadata);
+  void ReceiveBlockCert(std::unique_ptr<Certificate> cert);
+
+ private:
+  void CommitProposal(int round, int proposer);
+  void CommitRound(int round);
+  void AsyncCommit();
+  void AsyncSend();
+  void AsyncExecute();
+
+  bool VerifyCert(const Certificate& cert);
+
+  bool CheckBlock(const Proposal& p);
+  void CheckFutureBlock(int round);
+  void CheckFutureCert(const Proposal& proposal);
+  void CheckFutureCert(int round, const std::string& hash, int proposer);
+  bool CheckCert(const Certificate& cert);
+  bool SendBlockAck(std::unique_ptr<Proposal> proposal);
+
+  void AsyncProcessCert();
+
+  int GetLeader(int64_t r);
+
+ private:
+  LockFreeQueue<Proposal> execute_queue_, pending_block_;
+  LockFreeQueue<int> commit_queue_;
+  LockFreeQueue<Transaction> txns_;
+
+  std::unique_ptr<ProposalManager> proposal_manager_;
+  SignatureVerifier* verifier_;
+
+  std::thread send_thread_;
+  std::thread commit_thread_, execute_thread_;
+  std::mutex txn_mutex_, mutex_;
+  int limit_count_;
+  std::map<std::string, std::map<int, std::unique_ptr<Metadata>>> received_num_;
+  std::condition_variable vote_cv_;
+  int start_ = 0;
+  int batch_size_ = 0;
+  int execute_id_ = 1;
+  std::atomic<int> queue_size_;
+
+  Stats* global_stats_;
+
+  std::thread cert_thread_;
+  LockFreeQueue<Certificate> cert_queue_;
+  std::mutex future_block_mutex_, future_cert_mutex_, check_block_mutex_;
+  std::map<int, std::map<std::string, std::unique_ptr<Proposal>>> future_block_;
+  std::map<int, std::map<std::string, std::unique_ptr<Certificate>>>
+      future_cert_;
+  int64_t last_commit_time_ = 0;
+};
+
+}  // namespace thunderbolt
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.cpp b/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.cpp
new file mode 100644
index 000000000..3d3c5e41b
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+
+TransactionStatue TransactionCollector::GetStatus() const { return status_; }
+
+int TransactionCollector::AddRequest(
+    std::unique_ptr<google::protobuf::Message> request, int sender_id, int type,
+    std::function<void(const google::protobuf::Message&, int received_count,
+                       std::atomic<TransactionStatue>* status)>
+        call_back) {
+  if (status_.load() == EXECUTED) {
+    return -2;
+  }
+
+  if (request) {
+    request_ = std::move(request);
+    call_back(*request, 1, &status_);
+  } else {
+    senders_[type].insert(sender_id);
+    if (request_) {
+      call_back(*request_, senders_[type].size(), &status_);
+    }
+  }
+  return 0;
+}
+
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.h b/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.h
new file mode 100644
index 000000000..b38a41f62
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/algorithm/transaction_collector.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <google/protobuf/message.h>
+
+#include "platform/statistic/stats.h"
+
+namespace resdb {
+
+enum TransactionStatue {
+  None = 0,
+  Prepare = -999,
+  READY_PREPARE = 1,
+  READY_COMMIT = 2,
+  READY_EXECUTE = 3,
+  EXECUTED = 4,
+};
+
+class TransactionCollector {
+ public:
+  TransactionCollector(int64_t seq)
+      : seq_(seq), status_(TransactionStatue::None) {}
+
+  ~TransactionCollector() = default;
+
+  int AddRequest(
+      std::unique_ptr<google::protobuf::Message> request, int sender_id,
+      int type,
+      std::function<void(const google::protobuf::Message&, int received_count,
+                         std::atomic<TransactionStatue>* status)>
+          call_back);
+
+  TransactionStatue GetStatus() const;
+  int64_t GetSeq() { return seq_; }
+
+  std::unique_ptr<google::protobuf::Message> GetData() {
+    return std::move(request_);
+  }
+
+ private:
+  int64_t seq_;
+  std::unique_ptr<google::protobuf::Message> request_;
+  std::atomic<TransactionStatue> status_ = TransactionStatue::None;
+  std::set<int> senders_[10];
+};
+
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/common/BUILD b/platform/consensus/ordering/thunderbolt/executor/common/BUILD
new file mode 100644
index 000000000..769670a06
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/common/BUILD
@@ -0,0 +1,18 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+    name = "utils",
+    hdrs = ["utils.h"],
+    deps = [
+        "//third_party:evm_lib",
+    ],
+)
+
+cc_library(
+    name = "contract_execute_info",
+    hdrs = ["contract_execute_info.h"],
+    deps = [
+        ":utils",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
diff --git a/platform/consensus/ordering/thunderbolt/executor/common/contract_execute_info.h b/platform/consensus/ordering/thunderbolt/executor/common/contract_execute_info.h
new file mode 100644
index 000000000..4db40bf3d
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/common/contract_execute_info.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "absl/status/statusor.h"
+#include "eEVM/address.h"
+#include "eEVM/opcode.h"
+#include "service/contract/executor/common/utils.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+struct ContractExecuteInfo {
+  eevm::Address caller_address;
+  eevm::Address contract_address;
+  std::string func_addr;
+  Params func_params;
+  int64_t commit_id;
+  uint64_t user_id;
+  bool is_only;
+  ContractExecuteInfo() {}
+  ContractExecuteInfo(eevm::Address caller_address,
+                      eevm::Address contract_address, std::string func_addr,
+                      Params func_params, int64_t commit_id)
+      : caller_address(caller_address),
+        contract_address(contract_address),
+        func_addr(func_addr),
+        func_params(func_params),
+        commit_id(commit_id),
+        is_only(false) {}
+};
+
+struct ExecuteResp {
+  int ret;
+  absl::Status state;
+  int64_t commit_id;
+  Address contract_address;
+  // ConcurrencyController :: ModifyMap rws;
+  std::string result;
+  int retry_time = 0;
+  uint64_t user_id = 0;
+  double runtime = 0;
+  double delay = 0;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/common/utils.h b/platform/consensus/ordering/thunderbolt/executor/common/utils.h
new file mode 100644
index 000000000..2d243d66f
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/common/utils.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "eEVM/address.h"
+
+namespace resdb {
+namespace contract {
+
+typedef eevm::Address Address;
+
+}
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.cpp b/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.cpp
new file mode 100644
index 000000000..fbee05b41
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/x_verifier.h"
+
+#include <queue>
+
+#include "common/utils/utils.h"
+#include "eEVM/processor.h"
+#include "glog/logging.h"
+#include "service/contract/executor/manager/local_state.h"
+
+namespace resdb {
+namespace contract {
+
+XVerifier::XVerifier(DataStorage* storage, GlobalState* global_state,
+                     int worker_num)
+    : storage_(storage), gs_(global_state), worker_num_(worker_num) {
+  controller_ = std::make_unique<VController>(storage);
+  is_stop_ = false;
+
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_.push_back(std::thread([&]() {
+      while (!is_stop_) {
+        auto request = request_queue_.Pop();
+        if (request == nullptr) {
+          continue;
+        }
+
+        LocalState local_state(controller_.get());
+        local_state.Set(
+            gs_->GetAccount(
+                request->GetContractExecuteInfo()->contract_address),
+            request->GetContractExecuteInfo()->commit_id);
+
+        std::unique_ptr<ExecuteResp> resp = std::make_unique<ExecuteResp>();
+        auto ret = ExecContract(
+            request->GetContractExecuteInfo()->caller_address,
+            request->GetContractExecuteInfo()->contract_address,
+            request->GetContractExecuteInfo()->func_addr,
+            request->GetContractExecuteInfo()->func_params, &local_state);
+        resp->state = ret.status();
+        resp->contract_address =
+            request->GetContractExecuteInfo()->contract_address;
+        resp->commit_id = request->GetContractExecuteInfo()->commit_id;
+        resp->user_id = request->GetContractExecuteInfo()->user_id;
+        if (ret.ok()) {
+          resp->ret = 0;
+          resp->result = *ret;
+          if (request->IsRedo()) {
+            resp->retry_time++;
+          }
+          local_state.Flesh(request->GetContractExecuteInfo()->contract_address,
+                            request->GetContractExecuteInfo()->commit_id);
+        } else {
+          resp->ret = -1;
+        }
+        resp_queue_.Push(std::move(resp));
+      }
+    }));
+  }
+}
+
+XVerifier::~XVerifier() {
+  is_stop_ = true;
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_[i].join();
+  }
+}
+
+bool XVerifier::VerifyContract(
+    const std::vector<ContractExecuteInfo>& request_list,
+    const std::vector<ConcurrencyController ::ModifyMap>& rws_list) {
+  std::vector<int> d;
+  std::map<int, std::vector<int> > g;
+  std::map<Address, int> id;
+
+  for (int i = 0; i < rws_list.size(); ++i) {
+    d.push_back(0);
+    for (auto it : rws_list[i]) {
+      const Address& address = it.first;
+      // LOG(ERROR)<<"i ="<<i<<" address:"<<address;
+      if (id.find(address) == id.end() || id[address] == i) {
+        id[address] = i;
+        continue;
+      }
+      g[id[address]].push_back(i);
+      // LOG(ERROR)<<"add edge:"<<id[address]<<" to "<<i;
+      id[address] = i;
+      d[i]++;
+    }
+  }
+
+  std::queue<int> q;
+  for (int i = 0; i < request_list.size(); ++i) {
+    if (d[i] == 0) {
+      auto context = std::make_unique<ExecutionContext>(request_list[i]);
+      context->GetContractExecuteInfo()->commit_id = i;
+      request_queue_.Push(std::move(context));
+      // LOG(ERROR)<<"add:"<<i;
+    }
+  }
+
+  int process_num = request_list.size();
+  while (process_num > 0) {
+    auto resp = resp_queue_.Pop();
+    if (resp == nullptr) {
+      continue;
+    }
+    process_num--;
+    int resp_commit_id = resp->commit_id;
+    bool ret = controller_->Commit(resp_commit_id);
+    if (!ret) {
+      return false;
+    }
+    // LOG(ERROR)<<"verify:"<<resp_commit_id;
+    auto* rws = controller_->GetChangeList(resp_commit_id);
+    if (!RWSEqual(*rws, rws_list[resp_commit_id])) {
+      LOG(ERROR) << "rws not equal";
+      return false;
+    }
+    for (int n_id : g[resp_commit_id]) {
+      // LOG(ERROR)<<"next id:"<<n_id;
+      d[n_id]--;
+      if (d[n_id] == 0) {
+        auto context = std::make_unique<ExecutionContext>(request_list[n_id]);
+        context->GetContractExecuteInfo()->commit_id = n_id;
+        request_queue_.Push(std::move(context));
+        // LOG(ERROR)<<"add next:"<<n_id;
+      }
+    }
+  }
+  // LOG(ERROR)<<"verified";
+  return true;
+}
+
+bool XVerifier::RWSEqual(const ConcurrencyController ::ModifyMap& a,
+                         const ConcurrencyController ::ModifyMap& b) {
+  // LOG(ERROR)<<"size:"<<a.size()<<" "<<b.size();
+  if (a.size() != b.size()) {
+    return false;
+  }
+  for (auto it1 = a.begin(), it2 = b.begin(); it1 != a.end() && it2 != b.end();
+       it1++, it2++) {
+    if (it1->first != it2->first) {
+      LOG(ERROR) << "address not equal:" << it1->first << " " << it2->first;
+      return false;
+    }
+    if (it1->second.size() != it2->second.size()) {
+      LOG(ERROR) << "item size not equal:" << it1->second.size() << " "
+                 << it2->second.size();
+      return false;
+    }
+    for (int i = 0; i < it1->second.size(); i++) {
+      if (it1->second[i] != it2->second[i]) {
+        LOG(ERROR) << "data not equal";
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.h b/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.h
new file mode 100644
index 000000000..7413d2893
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/common/x_verifier.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <future>
+#include <shared_mutex>
+
+#include "absl/status/statusor.h"
+#include "eEVM/opcode.h"
+#include "platform/common/queue/lock_free_queue.h"
+#include "service/contract/executor/manager/committer_context.h"
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/contract_verifier.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/executor/manager/utils.h"
+#include "service/contract/executor/manager/v_controller.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+class XVerifier : public ContractVerifier {
+ public:
+  XVerifier(DataStorage* storage, GlobalState* global_state,
+            int worker_num = 2);
+
+  ~XVerifier();
+
+  bool VerifyContract(
+      const std::vector<ContractExecuteInfo>& request_list,
+      const std::vector<ConcurrencyController ::ModifyMap>& rws_list);
+
+  bool RWSEqual(const ConcurrencyController ::ModifyMap& a,
+                const ConcurrencyController ::ModifyMap& b);
+
+ private:
+  DataStorage* storage_;
+  GlobalState* gs_;
+  std::vector<std::thread> workers_;
+  std::unique_ptr<VController> controller_;
+  std::atomic<bool> is_stop_;
+
+  LockFreeQueue<ExecutionContext> request_queue_;
+  LockFreeQueue<ExecuteResp> resp_queue_;
+  const int worker_num_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/BUILD b/platform/consensus/ordering/thunderbolt/executor/eo_service/BUILD
new file mode 100644
index 000000000..46776a78a
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/BUILD
@@ -0,0 +1,26 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+    name = "contract_transaction_manager",
+    srcs = ["contract_transaction_manager.cpp"],
+    hdrs = ["contract_transaction_manager.h"],
+    deps = [
+        "//platform/config:resdb_config_utils",
+        "//service/contract/executor/manager:address_manager",
+        "//service/contract/executor/manager:contract_manager",
+        "//service/contract/proto:rpc_cc_proto",
+        "//service/utils:server_factory",
+    ],
+)
+
+cc_test(
+    name = "contract_transaction_manager_test",
+    srcs = ["contract_transaction_manager_test.cpp"],
+    data = [
+        "//service/contract/executor/service/test_data:contract.json",
+    ],
+    deps = [
+        ":contract_transaction_manager",
+        "//common/test:test_main",
+    ],
+)
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.cpp b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.cpp
new file mode 100644
index 000000000..163c369fa
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/service/contract_transaction_manager.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+ContractTransactionManager::ContractTransactionManager(void)
+    : contract_manager_(
+          std::make_unique<ContractManager>(std::make_unique<DataStorage>())),
+      address_manager_(std::make_unique<AddressManager>()) {}
+
+std::unique_ptr<std::string> ContractTransactionManager::ExecuteData(
+    const std::string& client_request) {
+  Request request;
+  Response response;
+
+  if (!request.ParseFromString(client_request)) {
+    LOG(ERROR) << "parse data fail";
+    return nullptr;
+  }
+
+  int ret = 0;
+  if (request.cmd() == Request::CREATE_ACCOUNT) {
+    LOG(ERROR) << " create account";
+    absl::StatusOr<Account> account_or = CreateAccount();
+    if (account_or.ok()) {
+      response.mutable_account()->Swap(&(*account_or));
+    } else {
+      ret = -1;
+    }
+  } else if (request.cmd() == Request::DEPLOY) {
+    LOG(ERROR) << " deploy";
+    absl::StatusOr<Contract> contract_or = Deploy(request);
+    if (contract_or.ok()) {
+      response.mutable_contract()->Swap(&(*contract_or));
+    } else {
+      ret = -1;
+    }
+  } else if (request.cmd() == Request::EXECUTE) {
+    auto res_or = Execute(request);
+    if (res_or.ok()) {
+      response.set_res(*res_or);
+    } else {
+      ret = -1;
+    }
+  }
+
+  response.set_ret(ret);
+
+  std::unique_ptr<std::string> resp_str = std::make_unique<std::string>();
+  if (!response.SerializeToString(resp_str.get())) {
+    return nullptr;
+  }
+
+  return resp_str;
+}
+
+absl::StatusOr<Account> ContractTransactionManager::CreateAccount() {
+  std::string address =
+      AddressManager::AddressToHex(address_manager_->CreateRandomAddress());
+  Account account;
+  account.set_address(address);
+  return account;
+}
+
+absl::StatusOr<Contract> ContractTransactionManager::Deploy(
+    const Request& request) {
+  Address caller_address =
+      AddressManager::HexToAddress(request.caller_address());
+  if (!address_manager_->Exist(caller_address)) {
+    LOG(ERROR) << "caller doesn't have an account";
+    return absl::InvalidArgumentError("Account not exist.");
+  }
+
+  Address contract_address =
+      contract_manager_->DeployContract(caller_address, request.deploy_info());
+
+  if (contract_address > 0) {
+    Contract contract;
+    contract.set_owner_address(request.caller_address());
+    contract.set_contract_address(
+        AddressManager::AddressToHex(contract_address));
+    contract.set_contract_name(request.deploy_info().contract_name());
+    return contract;
+  }
+  return absl::InternalError("Deploy Contract fail.");
+}
+
+absl::StatusOr<std::string> ContractTransactionManager::Execute(
+    const Request& request) {
+  Address caller_address =
+      AddressManager::HexToAddress(request.caller_address());
+  if (!address_manager_->Exist(caller_address)) {
+    LOG(ERROR) << "caller doesn't have an account";
+    return absl::InvalidArgumentError("Account not exist.");
+  }
+
+  return contract_manager_->ExecContract(
+      caller_address, AddressManager::HexToAddress(request.contract_address()),
+      request.func_params());
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.h b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.h
new file mode 100644
index 000000000..33638c2f4
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "platform/config/resdb_config_utils.h"
+#include "platform/consensus/execution/transaction_manager.h"
+#include "service/contract/executor/manager/address_manager.h"
+#include "service/contract/executor/manager/contract_manager.h"
+#include "service/contract/proto/func_params.pb.h"
+#include "service/contract/proto/rpc.pb.h"
+
+namespace resdb {
+namespace contract {
+
+class ContractTransactionManager : public TransactionManager {
+ public:
+  ContractTransactionManager(void);
+  virtual ~ContractTransactionManager() = default;
+
+  std::unique_ptr<std::string> ExecuteData(const std::string& request) override;
+
+ private:
+  absl::StatusOr<Account> CreateAccount();
+  absl::StatusOr<Contract> Deploy(const Request& request);
+  absl::StatusOr<std::string> Execute(const Request& request);
+
+ private:
+  std::unique_ptr<ContractManager> contract_manager_;
+  std::unique_ptr<AddressManager> address_manager_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager_test.cpp b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager_test.cpp
new file mode 100644
index 000000000..e0d59e186
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/contract_transaction_manager_test.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/service/contract_transaction_manager.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
+                             std::string(getenv("TEST_WORKSPACE")) +
+                             "/service/contract/executor/service/";
+
+std::string ToString(const Request& request) {
+  std::string ret;
+  request.SerializeToString(&ret);
+  return ret;
+}
+
+class ContractTransactionManagerTest : public Test {
+ public:
+  ContractTransactionManagerTest() {
+    std::string contract_path = test_dir + "test_data/contract.json";
+
+    std::ifstream contract_fstream(contract_path);
+    if (!contract_fstream) {
+      throw std::runtime_error(fmt::format(
+          "Unable to open contract definition file {}", contract_path));
+    }
+
+    nlohmann::json definition = nlohmann::json::parse(contract_fstream);
+    contracts_json_ = definition["contracts"];
+  }
+
+  Account CreateAccount() {
+    Request request;
+    Response response;
+
+    request.set_cmd(Request::CREATE_ACCOUNT);
+    std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
+    EXPECT_TRUE(ret != nullptr);
+    response.ParseFromString(*ret);
+    return response.account();
+  }
+
+  absl::StatusOr<Contract> Deploy(const Account& account,
+                                  DeployInfo deploy_info) {
+    Request request;
+    Response response;
+
+    request.set_caller_address(account.address());
+    *request.mutable_deploy_info() = deploy_info;
+    request.set_cmd(Request::DEPLOY);
+
+    std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
+    EXPECT_TRUE(ret != nullptr);
+
+    response.ParseFromString(*ret);
+    if (response.ret() == 0) {
+      return response.contract();
+    } else {
+      return absl::InternalError("DeployFail.");
+    }
+  }
+
+  absl::StatusOr<uint256_t> Execute(const std::string& caller_address,
+                                    const std::string& contract_address,
+                                    const Params& params) {
+    Request request;
+    Response response;
+
+    request.set_caller_address(caller_address);
+    request.set_contract_address(contract_address);
+    request.set_cmd(Request::EXECUTE);
+    *request.mutable_func_params() = params;
+
+    std::unique_ptr<std::string> ret = executor_.ExecuteData(ToString(request));
+    EXPECT_TRUE(ret != nullptr);
+
+    response.ParseFromString(*ret);
+
+    if (response.ret() == 0) {
+      return eevm::to_uint256(response.res());
+    } else {
+      return absl::InternalError("DeployFail.");
+    }
+  }
+
+ protected:
+  nlohmann::json contracts_json_;
+  ContractTransactionManager executor_;
+};
+
+TEST_F(ContractTransactionManagerTest, ExecContract) {
+  // create an account.
+  Account account = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+
+  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_code = contracts_json_[contract_name]["bin"];
+  nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
+
+  // deploy
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_code);
+  deploy_info.set_contract_name(contract_name);
+
+  for (auto& func : func_hashes.items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+  deploy_info.add_init_param("1000");
+
+  absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
+  EXPECT_TRUE(contract_or.ok());
+  Contract contract = *contract_or;
+
+  // query owner should return 1000
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(account.address());
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 0x3e8);
+  }
+
+  Account transfer_receiver = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+  // receiver 0
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(transfer_receiver.address());
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 0);
+  }
+
+  // transfer 400 to receiver
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(transfer_receiver.address());
+    func_params.add_param("400");
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 1);
+  }
+
+  // query owner should return 600
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(account.address());
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 600);
+  }
+
+  // receiver 400
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(transfer_receiver.address());
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 400);
+  }
+}
+
+TEST_F(ContractTransactionManagerTest, DeployFail) {
+  // create an account.
+  Account account = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+
+  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_code = contracts_json_[contract_name]["bin"];
+  nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
+
+  // deploy
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_code);
+  deploy_info.set_contract_name(contract_name);
+
+  for (auto& func : func_hashes.items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+  // deploy_info.add_init_param("1000");
+
+  absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
+  EXPECT_FALSE(contract_or.ok());
+}
+
+TEST_F(ContractTransactionManagerTest, NoFunc) {
+  // create an account.
+  Account account = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+
+  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_code = contracts_json_[contract_name]["bin"];
+  nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
+
+  // deploy
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_code);
+  deploy_info.set_contract_name(contract_name);
+
+  for (auto& func : func_hashes.items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+  deploy_info.add_init_param("1000");
+
+  absl::StatusOr<Contract> contract_or = Deploy(account, deploy_info);
+  EXPECT_TRUE(contract_or.ok());
+  Contract contract = *contract_or;
+
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf()");
+    func_params.add_param(account.address());
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_FALSE(result.ok());
+  }
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/BUILD b/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/BUILD
new file mode 100644
index 000000000..65e3dc3d9
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/BUILD
@@ -0,0 +1 @@
+exports_files(["contract.json"])
diff --git a/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/contract.json b/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/contract.json
new file mode 100644
index 000000000..e9c0d972f
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/eo_service/test_data/contract.json
@@ -0,0 +1,19 @@
+{
+  "contracts":
+  {
+    "ERC20.sol:ERC20Token":
+    {
+      "bin": "608060405234801561001057600080fd5b506040516104423803806104428339818101604052602081101561003357600080fd5b50516000818155338152600160205260409020556103ec806100566000396000f3fe608060405234801561001057600080fd5b506004361061007e577c01000000000000000000000000000000000000000000000000000000006000350463095ea7b3811461008357806318160ddd146100c357806323b872dd146100dd57806370a0823114610113578063a9059cbb14610139578063dd62ed3e14610165575b600080fd5b6100af6004803603604081101561009957600080fd [...]
+      "hashes":
+      {
+        "allowance(address,address)": "dd62ed3e",
+        "approve(address,uint256)": "095ea7b3",
+        "balanceOf(address)": "70a08231",
+        "totalSupply()": "18160ddd",
+        "transfer(address,uint256)": "a9059cbb",
+        "transferFrom(address,address,uint256)": "23b872dd"
+      }
+    }
+  },
+  "version": "0.5.16+commit.9c3226ce.Linux.g++"
+}
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/BUILD b/platform/consensus/ordering/thunderbolt/executor/manager/BUILD
new file mode 100644
index 000000000..64b36e2d0
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/BUILD
@@ -0,0 +1,620 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+    name = "address_manager",
+    srcs = ["address_manager.cpp"],
+    hdrs = ["address_manager.h"],
+    deps = [
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+    ],
+)
+
+cc_test(
+    name = "address_manager_test",
+    srcs = ["address_manager_test.cpp"],
+    deps = [
+        ":address_manager",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "data_storage",
+    srcs = ["data_storage.cpp"],
+    hdrs = ["data_storage.h"],
+    deps = [
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+    ],
+)
+
+cc_library(
+    name = "leveldb_storage",
+    srcs = ["leveldb_storage.cpp"],
+    hdrs = ["leveldb_storage.h"],
+    deps = [
+        ":data_storage",
+        "//common:comm",
+        "//storage:res_leveldb",
+    ],
+)
+
+cc_library(
+    name = "mock_data_storage",
+    hdrs = ["mock_data_storage.h"],
+    deps = [
+        ":data_storage",
+        "//common/test",
+    ],
+)
+
+cc_library(
+    name = "mock_d_storage",
+    hdrs = ["mock_d_storage.h"],
+    deps = [
+        ":d_storage",
+        "//common/test",
+    ],
+)
+
+cc_library(
+    name = "d_storage",
+    srcs = ["d_storage.cpp"],
+    hdrs = ["d_storage.h"],
+    deps = [
+        ":data_storage",
+        "//common:comm",
+    ],
+)
+
+cc_library(
+    name = "leveldb_d_storage",
+    srcs = ["leveldb_d_storage.cpp"],
+    hdrs = ["leveldb_d_storage.h"],
+    deps = [
+        ":data_storage",
+        "//common:comm",
+        "//storage:res_leveldb",
+    ],
+)
+
+cc_library(
+    name = "leveldb",
+    srcs = ["leveldb.cpp"],
+    hdrs = ["leveldb.h"],
+    deps = [
+        ":data_storage",
+        "//common:comm",
+        "//storage:res_leveldb",
+    ],
+)
+
+cc_library(
+    name = "global_view",
+    srcs = ["global_view.cpp"],
+    hdrs = ["global_view.h"],
+    deps = [
+        ":data_storage",
+        "//common:comm",
+    ],
+)
+
+cc_library(
+    name = "local_view",
+    srcs = ["local_view.cpp"],
+    hdrs = ["local_view.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+    ],
+)
+
+cc_test(
+    name = "local_view_test",
+    srcs = ["local_view_test.cpp"],
+    deps = [
+        ":local_view",
+        ":two_phase_controller",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "evm_state",
+    hdrs = ["evm_state.h"],
+    deps = [
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+    ],
+)
+
+cc_library(
+    name = "global_state",
+    srcs = ["global_state.cpp"],
+    hdrs = ["global_state.h"],
+    deps = [
+        ":evm_state",
+        ":global_view",
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+    ],
+)
+
+cc_library(
+    name = "local_state",
+    srcs = ["local_state.cpp"],
+    hdrs = ["local_state.h"],
+    deps = [
+        ":evm_state",
+        ":local_view",
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+    ],
+)
+
+cc_library(
+    name = "concurrency_controller",
+    srcs = ["concurrency_controller.cpp"],
+    hdrs = ["concurrency_controller.h"],
+    deps = [
+        ":data_storage",
+    ],
+)
+
+cc_library(
+    name = "two_phase_ooo_controller",
+    srcs = ["two_phase_ooo_controller.cpp"],
+    hdrs = ["two_phase_ooo_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+    ],
+)
+
+cc_library(
+    name = "two_phase_ooo_committer",
+    srcs = ["two_phase_ooo_committer.cpp"],
+    hdrs = ["two_phase_ooo_committer.h"],
+    deps = [
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":two_phase_ooo_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "two_phase_controller",
+    srcs = ["two_phase_controller.cpp"],
+    hdrs = ["two_phase_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+    ],
+)
+
+cc_test(
+    name = "two_phase_controller_test",
+    srcs = ["two_phase_controller_test.cpp"],
+    deps = [
+        ":two_phase_controller",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "ooo_controller",
+    srcs = ["ooo_controller.cpp"],
+    hdrs = ["ooo_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+    ],
+)
+
+cc_library(
+    name = "sequential_cc_controller",
+    srcs = ["sequential_cc_controller.cpp"],
+    hdrs = ["sequential_cc_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_test(
+    name = "sequential_cc_controller_test",
+    srcs = ["sequential_cc_controller_test.cpp"],
+    deps = [
+        ":sequential_cc_controller",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "streaming_dq_controller",
+    srcs = ["streaming_dq_controller.cpp"],
+    hdrs = ["streaming_dq_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        ":d_storage",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_library(
+    name = "test_controller",
+    testonly = True,
+    srcs = ["test_controller.cpp"],
+    hdrs = ["test_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_library(
+    name = "contract_executor",
+    srcs = ["contract_executor.cpp"],
+    hdrs = ["contract_executor.h"],
+    deps = [
+        ":concurrency_controller",
+        ":evm_state",
+        "//common:comm",
+        "//service/contract/executor/common:contract_execute_info",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "committer_context",
+    srcs = ["committer_context.cpp"],
+    hdrs = ["committer_context.h"],
+    deps = [
+        ":contract_committer",
+    ],
+)
+
+cc_library(
+    name = "contract_committer",
+    hdrs = ["contract_committer.h"],
+    deps = [
+        ":contract_executor",
+        "//service/contract/executor/common:contract_execute_info",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "contract_verifier",
+    srcs = ["contract_verifier.cpp"],
+    hdrs = ["contract_verifier.h"],
+    deps = [
+        ":committer_context",
+        ":contract_committer",
+        ":contract_executor",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "ooo_committer",
+    srcs = ["ooo_committer.cpp"],
+    hdrs = ["ooo_committer.h"],
+    deps = [
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":ooo_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "two_phase_committer",
+    srcs = ["two_phase_committer.cpp"],
+    hdrs = ["two_phase_committer.h"],
+    deps = [
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":two_phase_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_test(
+    name = "two_phase_committer_test",
+    srcs = ["two_phase_committer_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+    ],
+    deps = [
+        ":address_manager",
+        ":contract_deployer",
+        ":two_phase_committer",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "sequential_concurrency_committer",
+    srcs = ["sequential_concurrency_committer.cpp"],
+    hdrs = ["sequential_concurrency_committer.h"],
+    deps = [
+        ":committer_context",
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":sequential_cc_controller",
+        "//common/utils",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "x_committer",
+    srcs = ["x_committer.cpp"],
+    hdrs = ["x_committer.h"],
+    deps = [
+        ":committer_context",
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":streaming_dq_controller",
+        ":x_controller",
+        "//common/utils",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "x_controller",
+    srcs = ["x_controller.cpp"],
+    hdrs = ["x_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_library(
+    name = "v_controller",
+    srcs = ["v_controller.cpp"],
+    hdrs = ["v_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_library(
+    name = "x_verifier",
+    srcs = ["x_verifier.cpp"],
+    hdrs = ["x_verifier.h"],
+    deps = [
+        ":contract_verifier",
+        ":global_state",
+        ":local_state",
+        ":v_controller",
+        "//common/utils",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_test(
+    name = "x_committer_test",
+    srcs = ["x_committer_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+    ],
+    deps = [
+        ":address_manager",
+        ":contract_deployer",
+        ":mock_data_storage",
+        ":x_committer",
+        "//common/test:test_main",
+    ],
+)
+
+cc_test(
+    name = "x_verifier_test",
+    srcs = ["x_verifier_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+        "//service/contract/executor/manager/test_data:kv.json",
+    ],
+    deps = [
+        ":address_manager",
+        ":contract_deployer",
+        ":mock_data_storage",
+        ":x_committer",
+        ":x_verifier",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "streaming_single_committer",
+    srcs = ["streaming_single_committer.cpp"],
+    hdrs = ["streaming_single_committer.h"],
+    deps = [
+        ":committer_context",
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        "//common/utils",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "streaming_dq_committer",
+    srcs = ["streaming_dq_committer.cpp"],
+    hdrs = ["streaming_dq_committer.h"],
+    deps = [
+        ":committer_context",
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":streaming_dq_controller",
+        "//common/utils",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_test(
+    name = "streaming_dq_committer_test",
+    srcs = ["streaming_dq_committer_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+        "//service/contract/executor/manager/test_data:kv.json",
+    ],
+    deps = [
+        ":address_manager",
+        ":contract_deployer",
+        ":mock_d_storage",
+        ":streaming_dq_committer",
+        "//common/test:test_main",
+    ],
+)
+
+cc_test(
+    name = "sequential_concurrency_committer_test",
+    srcs = ["sequential_concurrency_committer_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+    ],
+    deps = [
+        ":address_manager",
+        ":contract_deployer",
+        ":mock_data_storage",
+        ":sequential_concurrency_committer",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "streaming_controller",
+    srcs = ["streaming_controller.cpp"],
+    hdrs = ["streaming_controller.h"],
+    deps = [
+        ":concurrency_controller",
+        "//common:comm",
+        "//platform/common/queue:lock_free_queue",
+    ],
+)
+
+cc_library(
+    name = "streaming_committer",
+    srcs = ["streaming_committer.cpp"],
+    hdrs = ["streaming_committer.h"],
+    deps = [
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":local_state",
+        ":streaming_controller",
+        "//common/utils",
+        "//platform/common/queue:lock_free_queue",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "test_committer",
+    testonly = True,
+    srcs = ["test_committer.cpp"],
+    hdrs = ["test_committer.h"],
+    deps = [
+        ":contract_committer",
+        ":contract_executor",
+        ":global_state",
+        ":test_controller",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_library(
+    name = "contract_deployer",
+    srcs = ["contract_deployer.cpp"],
+    hdrs = ["contract_deployer.h"],
+    deps = [
+        ":address_manager",
+        ":concurrency_controller",
+        ":contract_committer",
+        ":global_state",
+    ],
+)
+
+cc_test(
+    name = "contract_deployer_test",
+    srcs = ["contract_deployer_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+    ],
+    deps = [
+        ":contract_deployer",
+        ":test_committer",
+        "//common/test:test_main",
+    ],
+)
+
+cc_library(
+    name = "contract_manager",
+    srcs = ["contract_manager.cpp"],
+    hdrs = ["contract_manager.h"],
+    deps = [
+        ":address_manager",
+        ":concurrency_controller",
+        ":contract_deployer",
+        ":global_state",
+        ":ooo_committer",
+        ":sequential_concurrency_committer",
+        ":streaming_committer",
+        ":streaming_dq_committer",
+        ":streaming_single_committer",
+        ":two_phase_committer",
+        ":two_phase_ooo_committer",
+        ":x_committer",
+        ":x_verifier",
+        "//common:comm",
+        "//service/contract/executor/common:utils",
+        "//service/contract/proto:func_params_cc_proto",
+    ],
+)
+
+cc_test(
+    name = "contract_manager_test",
+    srcs = ["contract_manager_test.cpp"],
+    data = [
+        "//service/contract/executor/manager/test_data:contract.json",
+    ],
+    deps = [
+        ":contract_manager",
+        "//common/test:test_main",
+    ],
+)
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.cpp
new file mode 100644
index 000000000..67a2281bd
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/address_manager.h"
+
+#include <glog/logging.h>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
+
+Address AddressManager::CreateRandomAddress() {
+  std::vector<uint8_t> raw(20);
+  std::generate(raw.begin(), raw.end(), []() { return rand(); });
+  Address address = eevm::from_big_endian(raw.data(), raw.size());
+  users_.insert(address);
+  return address;
+}
+
+bool AddressManager::CreateAddress(const Address& address) {
+  if (users_.find(address) != users_.end()) {
+    return false;
+  }
+  users_.insert(address);
+  return true;
+}
+
+bool AddressManager::Exist(const Address& address) {
+  return users_.find(address) != users_.end();
+}
+
+Address AddressManager::CreateContractAddress(const Address& owner) {
+  return eevm::generate_address(owner, 0u);
+}
+
+std::string AddressManager::AddressToHex(const Address& address) {
+  return eevm::to_hex_string(address);
+}
+
+Address AddressManager::HexToAddress(const std::string& address) {
+  return eevm::to_uint256(address);
+}
+
+uint256_t AddressManager::AddressToSHAKey(const Address& address) {
+  std::vector<uint8_t> code;
+  code.resize(64u);
+  eevm::to_big_endian(address, code.data());
+  // code[63]=1;
+  // LOG(ERROR)<<"code size:"<<code.size();
+
+  uint8_t h[32];
+  eevm::keccak_256(code.data(), static_cast<unsigned int>(code.size()), h);
+  // LOG(ERROR)<<"get h:"<<eevm::from_big_endian(h, sizeof(h));
+  return eevm::from_big_endian(h, sizeof(h));
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.h b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.h
new file mode 100644
index 000000000..c3aa11db2
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <set>
+
+#include "service/contract/executor/common/utils.h"
+
+namespace resdb {
+namespace contract {
+
+class AddressManager {
+ public:
+  AddressManager() {}
+
+  // Create an address holding a 20 byte value
+  Address CreateRandomAddress();
+  bool CreateAddress(const Address& address);
+  bool Exist(const Address& address);
+
+  static Address CreateContractAddress(const Address& owner);
+
+  static std::string AddressToHex(const Address& address);
+  static Address HexToAddress(const std::string& address);
+
+  static uint256_t AddressToSHAKey(const Address& address);
+
+ private:
+  std::set<Address> users_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/address_manager_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager_test.cpp
new file mode 100644
index 000000000..cb7d7454c
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/address_manager_test.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/address_manager.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+TEST(AddressManagerTest, CreateAddress) {
+  Address address = AddressManager().CreateRandomAddress();
+  std::array<uint8_t, 32> raw;
+  eevm::to_big_endian(address, raw.data());
+  Address m = eevm::from_big_endian(raw.data() + 12, raw.size() - 12);
+  EXPECT_EQ(m, address);
+}
+
+TEST(AddressManagerTest, CreateContractAddress) {
+  Address address = AddressManager().CreateRandomAddress();
+
+  Address contract_address = AddressManager::CreateContractAddress(address);
+
+  std::array<uint8_t, 32> raw;
+  eevm::to_big_endian(contract_address, raw.data());
+  Address m = eevm::from_big_endian(raw.data() + 12, raw.size() - 12);
+  EXPECT_EQ(m, contract_address);
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.cpp
new file mode 100644
index 000000000..0b9d4bd77
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/committer_context.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+ExecutionContext::ExecutionContext(const ContractExecuteInfo& info) {
+  info_ = std::make_unique<ContractExecuteInfo>(info);
+}
+
+const ContractExecuteInfo* ExecutionContext::GetContractExecuteInfo() const {
+  return info_.get();
+}
+
+ContractExecuteInfo* ExecutionContext::GetContractExecuteInfo() {
+  return info_.get();
+}
+
+void ExecutionContext::SetResult(std::unique_ptr<ExecuteResp> result) {
+  result_ = std::move(result);
+}
+
+bool ExecutionContext::IsRedo() { return is_redo_; }
+
+void ExecutionContext::SetRedo() { is_redo_++; }
+
+int ExecutionContext::RedoTime() { return is_redo_; }
+
+std::unique_ptr<ExecuteResp> ExecutionContext::FetchResult() {
+  return std::move(result_);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.h b/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.h
new file mode 100644
index 000000000..0a62a7fb7
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/committer_context.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "service/contract/executor/manager/contract_committer.h"
+
+namespace resdb {
+namespace contract {
+
+class ExecutionContext {
+ public:
+  ExecutionContext(const ContractExecuteInfo& info);
+  const ContractExecuteInfo* GetContractExecuteInfo() const;
+  ContractExecuteInfo* GetContractExecuteInfo();
+
+  void SetRedo();
+  bool IsRedo();
+  int RedoTime();
+
+  void SetResult(std::unique_ptr<ExecuteResp> result);
+  std::unique_ptr<ExecuteResp> FetchResult();
+
+ private:
+  int is_redo_ = 0;
+  std::unique_ptr<ExecuteResp> result_;
+  std::unique_ptr<ContractExecuteInfo> info_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.cpp
new file mode 100644
index 000000000..923617519
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.cpp
@@ -0,0 +1,16 @@
+#include "service/contract/executor/manager/concurrency_controller.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+ConcurrencyController::ConcurrencyController(DataStorage* storage)
+    : storage_(storage) {}
+
+const DataStorage* ConcurrencyController::GetStorage() const {
+  return storage_;
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.h b/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.h
new file mode 100644
index 000000000..a2ff27cef
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/concurrency_controller.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "service/contract/executor/manager/data_storage.h"
+
+namespace resdb {
+namespace contract {
+
+enum State {
+  LOAD = 0,
+  STORE = 1,
+  REMOVE = 2,
+};
+
+struct Data {
+  State state;
+  uint256_t data;
+  int64_t version;
+  uint256_t old_data;
+  Data() {}
+  Data(const State& state) : state(state) {}
+  Data(const State& state, const uint256_t& data, int64_t version = 0)
+      : state(state), data(data), version(version) {}
+  Data(const State& state, const uint256_t& data, int64_t version,
+       const uint256_t& old_data)
+      : state(state), data(data), version(version), old_data(old_data) {}
+  bool operator!=(const Data& d) const {
+    return d.state != this->state || d.data != this->data ||
+           d.version != this->version;
+  }
+};
+
+class ConcurrencyController {
+ public:
+  ConcurrencyController(DataStorage* storage);
+
+  typedef std::map<uint256_t, std::vector<Data>> ModifyMap;
+
+  virtual void PushCommit(int64_t commit_id,
+                          const ModifyMap& local_changes_) = 0;
+
+  const DataStorage* GetStorage() const;
+
+ protected:
+  DataStorage* storage_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_committer.h b/platform/consensus/ordering/thunderbolt/executor/manager/contract_committer.h
new file mode 100644
index 000000000..b6c874a0e
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_committer.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <thread>
+
+#include "absl/status/statusor.h"
+#include "eEVM/address.h"
+#include "eEVM/opcode.h"
+#include "service/contract/executor/common/contract_execute_info.h"
+#include "service/contract/executor/manager/contract_executor.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+/*
+struct ContractExecuteInfo {
+  eevm::Address caller_address;
+  eevm::Address contract_address;
+  std::string func_addr;
+  Params func_params;
+  int64_t commit_id;
+  uint64_t user_id;
+  ContractExecuteInfo(){}
+  ContractExecuteInfo(
+    eevm::Address caller_address,
+    eevm::Address contract_address,
+    std::string func_addr,
+    Params func_params,
+    int64_t commit_id): caller_address(caller_address),
+contract_address(contract_address), func_addr(func_addr),
+func_params(func_params), commit_id(commit_id){}
+};
+*/
+
+class ContractCommitter {
+ public:
+  ContractCommitter() = default;
+  virtual ~ContractCommitter() = default;
+
+  virtual std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& request) = 0;
+
+  virtual void AsyncExecContract(std::vector<ContractExecuteInfo>& request){};
+
+  virtual absl::StatusOr<std::string> ExecContract(
+      const Address& caller_address, const Address& contract_address,
+      const std::string& func_addr, const Params& func_param,
+      EVMState* state) = 0;
+
+  virtual void SetExecuteCallBack(
+      std::function<void(std::unique_ptr<ExecuteResp>)>){};
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.cpp
new file mode 100644
index 000000000..8a2ae4f9b
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.cpp
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_deployer.h"
+
+#include <glog/logging.h>
+
+#include "eEVM/processor.h"
+#include "service/contract/executor/manager/address_manager.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+std::string U256ToString(uint256_t v) { return eevm::to_hex_string(v); }
+
+void AppendArgToInput(std::vector<uint8_t>& code, const uint256_t& arg) {
+  const auto pre_size = code.size();
+  code.resize(pre_size + 32u);
+  eevm::to_big_endian(arg, code.data() + pre_size);
+  // LOG(ERROR)<<"add arg:"<<arg;
+}
+
+void AppendArgToInput(std::vector<uint8_t>& code, const std::string& arg) {
+  AppendArgToInput(code, eevm::to_uint256(arg));
+}
+
+}  // namespace
+
+ContractDeployer::ContractDeployer(ContractCommitter* committer,
+                                   GlobalState* gs)
+    : committer_(committer), gs_(gs) {}
+
+std::string ContractDeployer::GetFuncAddress(const Address& contract_address,
+                                             const std::string& func_name) {
+  return func_address_[contract_address][func_name];
+}
+
+void ContractDeployer::SetFuncAddress(const Address& contract_address,
+                                      const FuncInfo& func) {
+  func_address_[contract_address][func.func_name()] = func.hash();
+}
+
+Address ContractDeployer::DeployContract(const Address& owner_address,
+                                         const DeployInfo& deploy_info) {
+  const auto contract_address =
+      AddressManager::CreateContractAddress(owner_address);
+
+  auto contract_constructor = eevm::to_bytes(deploy_info.contract_bin());
+  for (const std::string& param : deploy_info.init_param()) {
+    AppendArgToInput(contract_constructor, param);
+  }
+
+  try {
+    auto contract = gs_->create(contract_address, 0u, contract_constructor);
+    absl::StatusOr<std::string> result =
+        committer_->ExecContract(owner_address, contract_address, "", {}, gs_);
+
+    if (result.ok()) {
+      // set the initialized class context code.
+      contract.acc.set_code(eevm::to_bytes(*result));
+
+      for (const auto& info : deploy_info.func_info()) {
+        SetFuncAddress(contract_address, info);
+      }
+      // LOG(ERROR)<<"contract create:"<<contract_address<<"
+      // addr:"<<contract.acc.get_address();
+      return contract.acc.get_address();
+    } else {
+      gs_->remove(contract_address);
+      return 0;
+    }
+  } catch (...) {
+    LOG(ERROR) << "Deploy throw expection";
+    return 0;
+  }
+}
+
+bool ContractDeployer::DeployContract(const Address& owner_address,
+                                      const DeployInfo& deploy_info,
+                                      const Address& contract_address) {
+  LOG(ERROR) << "deploy address:" << contract_address;
+  auto contract_constructor = eevm::to_bytes(deploy_info.contract_bin());
+  for (const std::string& param : deploy_info.init_param()) {
+    AppendArgToInput(contract_constructor, param);
+  }
+
+  try {
+    LOG(ERROR) << "deploy:" << (gs_ == nullptr);
+    auto contract = gs_->create(contract_address, 0u, contract_constructor);
+
+    LOG(ERROR) << "create:";
+    absl::StatusOr<std::string> result =
+        committer_->ExecContract(owner_address, contract_address, "", {}, gs_);
+
+    LOG(ERROR) << "deploy result:" << result.ok() << " code:" << *result;
+    if (result.ok()) {
+      // set the initialized class context code.
+      contract.acc.set_code(eevm::to_bytes(*result));
+
+      for (const auto& info : deploy_info.func_info()) {
+        SetFuncAddress(contract_address, info);
+      }
+      return true;
+    } else {
+      gs_->remove(contract_address);
+      return false;
+    }
+  } catch (...) {
+    LOG(ERROR) << "Deploy throw expection";
+    return false;
+  }
+}
+
+Address ContractDeployer::DeployContract(
+    const Address& owner_address, const nlohmann::json& contract_json,
+    const std::vector<uint256_t>& init_params) {
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json["bin"]);
+
+  for (auto& func : contract_json["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  for (const uint256_t& param : init_params) {
+    deploy_info.add_init_param(U256ToString(param));
+  }
+
+  return DeployContract(owner_address, deploy_info);
+}
+
+bool ContractDeployer::DeployContract(const Address& owner_address,
+                                      const nlohmann::json& contract_json,
+                                      const std::vector<uint256_t>& init_params,
+                                      const Address& contract_address) {
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json["bin"]);
+
+  for (auto& func : contract_json["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  for (const uint256_t& param : init_params) {
+    deploy_info.add_init_param(U256ToString(param));
+  }
+
+  return DeployContract(owner_address, deploy_info, contract_address);
+}
+
+absl::StatusOr<eevm::AccountState> ContractDeployer::GetContract(
+    const Address& address) {
+  if (!gs_->Exists(address)) {
+    return absl::InvalidArgumentError("Contract not exist.");
+  }
+
+  return gs_->get(address);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.h b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.h
new file mode 100644
index 000000000..6c6626b26
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+class ContractDeployer {
+ public:
+  ContractDeployer(ContractCommitter* committer, GlobalState* gs);
+
+ public:
+  Address DeployContract(const Address& owner_address,
+                         const DeployInfo& deploy_info);
+  bool DeployContract(const Address& owner_address,
+                      const DeployInfo& deploy_info,
+                      const Address& contract_address);
+
+  Address DeployContract(const Address& owner_address,
+                         const nlohmann::json& contract_json,
+                         const std::vector<uint256_t>& init_params);
+  bool DeployContract(const Address& owner_address,
+                      const nlohmann::json& contract_json,
+                      const std::vector<uint256_t>& init_params,
+                      const Address& contract_address);
+
+  absl::StatusOr<eevm::AccountState> GetContract(const Address& address);
+  std::string GetFuncAddress(const Address& contract_address,
+                             const std::string& func_name);
+
+ private:
+  void SetFuncAddress(const Address& contract_address, const FuncInfo& func);
+
+ private:
+  ContractCommitter* committer_;
+  GlobalState* gs_;
+  std::map<Address, std::map<std::string, std::string>> func_address_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer_test.cpp
new file mode 100644
index 000000000..4ce4426d4
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_deployer_test.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_deployer.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+#include "service/contract/executor/manager/address_manager.h"
+#include "service/contract/executor/manager/test_committer.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
+                             std::string(getenv("TEST_WORKSPACE")) +
+                             "/service/contract/executor/manager/";
+
+Address get_random_address() { return AddressManager().CreateRandomAddress(); }
+
+std::string U256ToString(uint256_t v) { return eevm::to_hex_string(v); }
+
+class ContractDeployerTest : public Test {
+ public:
+  ContractDeployerTest() : owner_address_(get_random_address()) {
+    storage_ = std::make_unique<DataStorage>();
+    gs_ = std::make_unique<GlobalState>(storage_.get());
+    execotor_ = std::make_unique<TestCommitter>(storage_.get(), gs_.get());
+
+    LOG(ERROR) << "owner:" << owner_address_;
+    std::string contract_path = test_dir + "test_data/contract.json";
+
+    std::ifstream contract_fstream(contract_path);
+    if (!contract_fstream) {
+      throw std::runtime_error(fmt::format(
+          "Unable to open contract definition file {}", contract_path));
+    }
+
+    const auto contracts_definition = nlohmann::json::parse(contract_fstream);
+    const auto all_contracts = contracts_definition["contracts"];
+    const auto contract_code = all_contracts["ERC20.sol:ERC20Token"];
+    contract_json_ = contract_code;
+  }
+
+ protected:
+  Address owner_address_;
+  nlohmann::json contract_json_;
+
+  std::unique_ptr<DataStorage> storage_;
+  std::unique_ptr<GlobalState> gs_;
+  std::unique_ptr<ContractCommitter> execotor_;
+};
+
+TEST_F(ContractDeployerTest, NoContract) {
+  ContractDeployer deployer(execotor_.get(), gs_.get());
+  auto account = deployer.GetContract(1234);
+  EXPECT_FALSE(account.ok());
+}
+
+TEST_F(ContractDeployerTest, DeployContract) {
+  ContractDeployer deployer(execotor_.get(), gs_.get());
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      deployer.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = deployer.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+}
+
+TEST_F(ContractDeployerTest, DeployContractFromJson) {
+  ContractDeployer deployer(execotor_.get(), gs_.get());
+
+  Address contract_address =
+      deployer.DeployContract(owner_address_, contract_json_, {1000});
+  EXPECT_GT(contract_address, 0);
+  auto account = deployer.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.cpp
new file mode 100644
index 000000000..c94d9e0ec
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_executor.h"
+
+//#include "common/utils/utils.h"
+
+#include "eEVM/processor.h"
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+void AppendArgToInput(std::vector<uint8_t>& code, const uint256_t& arg) {
+  const auto pre_size = code.size();
+  code.resize(pre_size + 32u);
+  eevm::to_big_endian(arg, code.data() + pre_size);
+}
+
+void AppendArgToInput(std::vector<uint8_t>& code, const std::string& arg) {
+  AppendArgToInput(code, eevm::to_uint256(arg));
+}
+
+absl::StatusOr<std::string> ContractExecutor::ExecContract(
+    const Address& caller_address, const Address& contract_address,
+    const std::string& func_addr, const Params& func_param, EVMState* state) {
+  std::vector<uint8_t> inputs;
+  if (!func_addr.empty()) {
+    inputs = eevm::to_bytes(func_addr);
+  }
+  for (const std::string& param : func_param.param()) {
+    AppendArgToInput(inputs, param);
+  }
+
+  auto result = Execute(caller_address, contract_address, inputs, state);
+
+  if (result.ok()) {
+    return eevm::to_hex_string(*result);
+  } else {
+    LOG(ERROR) << "execute fail:" << result.status();
+  }
+  return result.status();
+}
+
+absl::StatusOr<std::vector<uint8_t>> ContractExecutor::Execute(
+    const Address& caller_address, const Address& contract_address,
+    const std::vector<uint8_t>& input, EVMState* state) {
+  // Ignore any logs produced by this transaction
+  eevm::NullLogHandler ignore;
+  eevm::Transaction tx(caller_address, ignore);
+
+  // Record a trace to aid debugging
+  eevm::Trace tr;
+  eevm::Processor p(*state);
+
+  // Run the transaction
+  try {
+    const auto exec_result =
+        p.run(tx, caller_address, state->get(contract_address), input, 0u, &tr);
+
+    if (exec_result.er != eevm::ExitReason::returned) {
+      // Print the trace if nothing was returned
+      if (exec_result.er == eevm::ExitReason::threw) {
+        return absl::InternalError(
+            fmt::format("Execution error: {}", exec_result.exmsg));
+      }
+      return absl::InternalError("Deployment did not return");
+    }
+    return exec_result.output;
+  } catch (...) {
+    return absl::InternalError(fmt::format("Execution error:"));
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.h b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.h
new file mode 100644
index 000000000..eebb1c22c
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <thread>
+
+#include "absl/status/statusor.h"
+#include "eEVM/opcode.h"
+#include "service/contract/executor/common/contract_execute_info.h"
+#include "service/contract/executor/common/utils.h"
+#include "service/contract/executor/manager/concurrency_controller.h"
+#include "service/contract/executor/manager/evm_state.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+/*
+struct ExecuteResp {
+  int ret;
+  absl::Status state;
+  int64_t commit_id;
+  Address contract_address;
+    ConcurrencyController :: ModifyMap rws;
+  std::string result;
+  int retry_time = 0;
+  uint64_t user_id = 0;
+  double runtime = 0;
+};
+*/
+
+class ContractExecutor {
+ public:
+  ContractExecutor() = default;
+
+  ~ContractExecutor() = default;
+
+  absl::StatusOr<std::string> ExecContract(const Address& caller_address,
+                                           const Address& contract_address,
+                                           const std::string& func_addr,
+                                           const Params& func_param,
+                                           EVMState* state);
+
+  absl::StatusOr<std::vector<uint8_t>> Execute(
+      const Address& owner_address, const Address& contract_address,
+      const std::vector<uint8_t>& func_params, EVMState* state);
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor_test.cpp
new file mode 100644
index 000000000..1b35fd4f7
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_executor_test.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+#include "service/contract/executor/manager/address_manager.h"
+#include "service/contract/executor/manager/contract_manager.h"
+#include "service/contract/executor/manager/multi_contract_executor.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
+                             std::string(getenv("TEST_WORKSPACE")) +
+                             "/service/contract/executor/manager/";
+
+Address get_random_address() { return AddressManager().CreateRandomAddress(); }
+
+std::string U256ToString(uint256_t v) { return eevm::to_hex_string(v); }
+uint256_t HexToInt(const std::string& v) { return eevm::to_uint256(v); }
+
+uint256_t GetAddressHash(uint256_t address) {
+  std::vector<uint8_t> code;
+  code.resize(64u);
+  eevm::to_big_endian(address, code.data());
+  code[63] = 1;
+
+  uint8_t h[32];
+  eevm::keccak_256(code.data(), static_cast<unsigned int>(code.size()), h);
+  return eevm::from_big_endian(h, sizeof(h));
+}
+
+class MultiContractExecutorTest : public Test {
+ public:
+  MultiContractExecutorTest() : owner_address_(get_random_address()) {
+    std::string contract_path = test_dir + "test_data/contract.json";
+    LOG(ERROR) << "test dir:" << test_dir;
+
+    std::ifstream contract_fstream(contract_path);
+    if (!contract_fstream) {
+      throw std::runtime_error(fmt::format(
+          "Unable to open contract definition file {}", contract_path));
+    }
+
+    const auto contracts_definition = nlohmann::json::parse(contract_fstream);
+    const auto all_contracts = contracts_definition["contracts"];
+    const auto contract_code = all_contracts["ERC20.sol:ERC20Token"];
+    contract_json_ = contract_code;
+  }
+
+ protected:
+  Address owner_address_;
+  nlohmann::json contract_json_;
+};
+
+TEST_F(MultiContractExecutorTest, ExecContract) {
+  std::unique_ptr<DataStorage> storage = std::make_unique<DataStorage>();
+  DataStorage* storage_ptr = storage.get();
+  ContractManager manager(std::move(storage));
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+  Address transfer_receiver = get_random_address();
+  Address transfer_receiver2 = get_random_address();
+  LOG(ERROR) << "owner address:" << owner_address_;
+  LOG(ERROR) << "receive 1:" << transfer_receiver;
+  LOG(ERROR) << "receive 2:" << transfer_receiver2;
+
+  uint256_t owner_key = GetAddressHash(owner_address_);
+  uint256_t transfer_key = GetAddressHash(transfer_receiver);
+  uint256_t transfer2_key = GetAddressHash(transfer_receiver2);
+
+  // owner 1000
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(owner_address_));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    LOG(ERROR) << "result:" << *result;
+    EXPECT_EQ(HexToInt(*result), 1000);
+
+    EXPECT_EQ(storage_ptr->Load(owner_key).first, 1000);
+  }
+
+  /*
+    // receiver 0
+    {
+      Params func_params;
+      func_params.set_func_name("balanceOf(address)");
+      func_params.add_param(U256ToString(transfer_receiver));
+
+      auto result =
+          manager.ExecContract(owner_address_, contract_address, func_params);
+      EXPECT_EQ(HexToInt(*result), 0);
+
+      EXPECT_EQ(storage_ptr->Load(transfer_key).first, 0);
+    }
+
+    // transfer 400 to receiver
+    {
+      Params func_params;
+      func_params.set_func_name("transfer(address,uint256)");
+      func_params.add_param(U256ToString(transfer_receiver));
+      func_params.add_param(U256ToString(400));
+
+      auto result =
+          manager.ExecContract(owner_address_, contract_address, func_params);
+      EXPECT_EQ(HexToInt(*result), 1);
+
+      EXPECT_EQ(storage_ptr->Load(transfer_key).first, 400);
+      EXPECT_EQ(storage_ptr->Load(owner_key).first, 600);
+    }
+
+    // owner 600
+    {
+      Address caller = get_random_address();
+      Params func_params;
+      func_params.set_func_name("balanceOf(address)");
+      func_params.add_param(U256ToString(owner_address_));
+
+      auto result = manager.ExecContract(caller, contract_address, func_params);
+      EXPECT_EQ(HexToInt(*result), 600);
+
+      EXPECT_EQ(storage_ptr->Load(transfer_key).first, 400);
+      EXPECT_EQ(storage_ptr->Load(owner_key).first, 600);
+    }
+
+    // transfer 200 to receiver2 from receiver
+    {
+      Params func_params;
+      func_params.set_func_name("approve(address,uint256)");
+      func_params.add_param(U256ToString(transfer_receiver));
+      func_params.add_param(U256ToString(100));
+
+      auto result =
+          manager.ExecContract(transfer_receiver, contract_address,
+    func_params); EXPECT_EQ(HexToInt(*result), 1);
+
+      EXPECT_EQ(storage_ptr->Load(transfer2_key).first, 0);
+      EXPECT_EQ(storage_ptr->Load(transfer_key).first, 400);
+      EXPECT_EQ(storage_ptr->Load(owner_key).first, 600);
+    }
+    {
+      Params func_params;
+      func_params.set_func_name("transferFrom(address,address,uint256)");
+      func_params.add_param(U256ToString(transfer_receiver));
+      func_params.add_param(U256ToString(transfer_receiver2));
+      func_params.add_param(U256ToString(100));
+
+      auto result =
+          manager.ExecContract(transfer_receiver, contract_address,
+    func_params); EXPECT_EQ(HexToInt(*result), 1);
+
+      EXPECT_EQ(storage_ptr->Load(transfer2_key).first, 100);
+      EXPECT_EQ(storage_ptr->Load(transfer_key).first, 300);
+      EXPECT_EQ(storage_ptr->Load(owner_key).first, 600);
+    }
+    */
+}
+/*
+
+TEST_F(MultiContractExecutorTest, ExecMultiContractNoConflict) {
+
+  std::unique_ptr<DataStorage> storage = std::make_unique<DataStorage>();
+  DataStorage * storage_ptr = storage.get();
+  ContractManager manager(std::move(storage));
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+
+  Address transfer_receiver = get_random_address();
+  Address transfer_receiver2 = get_random_address();
+  Address transfer_receiver3 = get_random_address();
+
+  uint256_t owner_key = GetAddressHash(owner_address_);
+  uint256_t transfer_key = GetAddressHash(transfer_receiver);
+  uint256_t transfer2_key = GetAddressHash(transfer_receiver2);
+  uint256_t transfer3_key = GetAddressHash(transfer_receiver3);
+
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(400));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1);
+
+    EXPECT_EQ(storage_ptr->Load(transfer_key).first, 400);
+    EXPECT_EQ(storage_ptr->Load(owner_key).first, 600);
+  }
+
+  // transfer 200 to receiver2 from receiver
+  {
+    Params func_params;
+    func_params.set_func_name("approve(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(200));
+
+    auto result =
+        manager.ExecContract(transfer_receiver, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1);
+  }
+
+  std::vector<ContractExecuteInfo> info;
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver3));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address, "",
+func_params, 0));
+  }
+
+  {
+    Params func_params;
+    func_params.set_func_name("transferFrom(address,address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(transfer_receiver2));
+    func_params.add_param(U256ToString(200));
+
+    info.push_back(ContractExecuteInfo(transfer_receiver, contract_address, "",
+func_params, 0));
+  }
+  std::vector<std::unique_ptr<ExecuteResp>> resp = manager.ExecContract(info);
+  EXPECT_EQ(storage_ptr->Load(transfer2_key).first, 200);
+  EXPECT_EQ(storage_ptr->Load(transfer3_key).first, 100);
+
+  LOG(ERROR)<<"resp size:"<<resp.size();
+  EXPECT_EQ(resp.size(), 2);
+  EXPECT_EQ(resp[0]->ret, 0);
+  EXPECT_EQ(resp[1]->ret, 0);
+
+  EXPECT_EQ(HexToInt(resp[0]->result), 1);
+  EXPECT_EQ(HexToInt(resp[1]->result), 1);
+}
+
+TEST_F(MultiContractExecutorTest, ExecMultiContractHaveConflict) {
+
+  std::unique_ptr<DataStorage> storage = std::make_unique<DataStorage>();
+  DataStorage * storage_ptr = storage.get();
+  ContractManager manager(std::move(storage));
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+
+  Address transfer_receiver = get_random_address();
+  Address transfer_receiver2 = get_random_address();
+  Address transfer_receiver3 = get_random_address();
+
+  uint256_t owner_key = GetAddressHash(owner_address_);
+  uint256_t transfer_key = GetAddressHash(transfer_receiver);
+  uint256_t transfer2_key = GetAddressHash(transfer_receiver2);
+  uint256_t transfer3_key = GetAddressHash(transfer_receiver3);
+
+  std::vector<ContractExecuteInfo> info;
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address, "",
+func_params, 0));
+  }
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver2));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address, "",
+func_params, 0));
+  }
+
+  std::vector<std::unique_ptr<ExecuteResp>> resp = manager.ExecContract(info);
+  EXPECT_EQ(storage_ptr->Load(owner_key).first, 800);
+  EXPECT_EQ(storage_ptr->Load(transfer_key).first, 100);
+  EXPECT_EQ(storage_ptr->Load(transfer2_key).first, 100);
+
+  LOG(ERROR)<<"resp size:"<<resp.size();
+  EXPECT_EQ(resp.size(), 2);
+  EXPECT_EQ(resp[0]->ret, 0);
+  EXPECT_EQ(resp[1]->ret, 0);
+
+  EXPECT_EQ(HexToInt(resp[0]->result), 1);
+  EXPECT_EQ(HexToInt(resp[1]->result), 1);
+}
+*/
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.cpp
new file mode 100644
index 000000000..c6e397da1
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_manager.h"
+
+#include "service/contract/executor/manager/address_manager.h"
+#include "service/contract/executor/manager/two_phase_committer.h"
+//#include
+//"service/contract/executor/manager/sequential_concurrency_committer.h"
+#include <glog/logging.h>
+
+#include "eEVM/processor.h"
+#include "service/contract/executor/manager/ooo_committer.h"
+#include "service/contract/executor/manager/streaming_committer.h"
+#include "service/contract/executor/manager/streaming_dq_committer.h"
+#include "service/contract/executor/manager/streaming_single_committer.h"
+#include "service/contract/executor/manager/two_phase_ooo_committer.h"
+#include "service/contract/executor/manager/x_committer.h"
+#include "service/contract/executor/manager/x_verifier.h"
+
+namespace resdb {
+namespace contract {
+
+ContractManager::ContractManager(std::unique_ptr<DataStorage> storage,
+                                 int worker_num, Options op) {
+  storage_ = std::move(storage);
+  gs_ = std::make_unique<GlobalState>(storage_.get());
+
+  switch (op) {
+    case TwoPL:
+      committer_ = std::make_unique<TwoPhaseCommitter>(storage_.get(),
+                                                       gs_.get(), worker_num);
+      break;
+    case TwoPLOOO:
+      committer_ = std::make_unique<TwoPhaseOOOCommitter>(
+          storage_.get(), gs_.get(), worker_num);
+      break;
+    case OOO:
+      committer_ =
+          std::make_unique<OOOCommitter>(storage_.get(), gs_.get(), worker_num);
+      break;
+    case Streaming:
+      committer_ = std::make_unique<streaming::StreamingCommitter>(
+          storage_.get(), gs_.get(), 500, nullptr, worker_num);
+      break;
+    case SCC:
+      // committer_ =
+      // std::make_unique<SequentialConcurrencyCommitter>(storage_.get(),
+      // gs_.get(), worker_num);
+      break;
+    case SingleStreaming:
+      committer_ = std::make_unique<streaming::StreamingSingleCommitter>(
+          storage_.get(), gs_.get(), worker_num);
+      break;
+    case MultiStreaming:
+      committer_ = std::make_unique<streaming::StreamingDQCommitter>(
+          storage_.get(), gs_.get(), 1500, nullptr, worker_num);
+      break;
+    case XE:
+      committer_ =
+          std::make_unique<XCommitter>(storage_.get(), gs_.get(), worker_num);
+      break;
+    case XEO:
+      committer_ =
+          std::make_unique<XCommitter>(storage_.get(), gs_.get(), worker_num);
+      //((XCommitter*)committer_.get())->UseOCC();
+      break;
+  }
+
+  deployer_ = std::make_unique<ContractDeployer>(committer_.get(), gs_.get());
+
+  verifier_ =
+      std::make_unique<XVerifier>(storage_.get(), gs_.get(), worker_num);
+}
+
+void ContractManager::SetExecuteCallBack(
+    std::function<void(std::unique_ptr<ExecuteResp> resp)> func) {
+  committer_->SetExecuteCallBack(std::move(func));
+}
+
+Address ContractManager::DeployContract(const Address& owner_address,
+                                        const DeployInfo& deploy_info) {
+  return deployer_->DeployContract(owner_address, deploy_info);
+}
+
+bool ContractManager::DeployContract(const Address& owner_address,
+                                     const DeployInfo& deploy_info,
+                                     const Address& contract_address) {
+  return deployer_->DeployContract(owner_address, deploy_info,
+                                   contract_address);
+}
+
+absl::StatusOr<eevm::AccountState> ContractManager::GetContract(
+    const Address& address) {
+  return deployer_->GetContract(address);
+}
+
+std::vector<std::unique_ptr<ExecuteResp>> ContractManager::ExecContract(
+    std::vector<ContractExecuteInfo>& execute_info) {
+  std::map<std::string, std::set<int>> ct;
+  std::map<int, int> cct;
+  for (int i = 0; i < execute_info.size(); ++i) {
+    std::string func_addr =
+        deployer_->GetFuncAddress(execute_info[i].contract_address,
+                                  execute_info[i].func_params.func_name());
+    if (func_addr.empty()) {
+      LOG(ERROR) << "no fouction:" << execute_info[i].func_params.func_name();
+      execute_info[i].contract_address = 0;
+      continue;
+    }
+    execute_info[i].func_addr = func_addr;
+    execute_info[i].commit_id = i + 1;
+  }
+
+  return committer_->ExecContract(execute_info);
+}
+
+void ContractManager::AsyncExecContract(
+    std::vector<ContractExecuteInfo>& execute_info) {
+  std::map<std::string, std::set<int>> ct;
+  std::map<int, int> cct;
+  for (int i = 0; i < execute_info.size(); ++i) {
+    std::string func_addr =
+        deployer_->GetFuncAddress(execute_info[i].contract_address,
+                                  execute_info[i].func_params.func_name());
+    if (func_addr.empty()) {
+      LOG(ERROR) << "no fouction:" << execute_info[i].func_params.func_name();
+      execute_info[i].contract_address = 0;
+      continue;
+    }
+    execute_info[i].func_addr = func_addr;
+    execute_info[i].commit_id = i + 1;
+
+    /*
+    cct[i]=0;
+    if(execute_info[i].func_params.param_size()>0){
+      for(int j = 0; j < execute_info[i].func_params.param_size()-1; j++){
+        auto& p = execute_info[i].func_params.param(j);
+        //LOG(ERROR)<<"get idx:"<<i<<" param:"<<p;
+        ct[p].insert(i);
+      }
+    }
+    */
+  }
+
+  /*
+  for(auto it : ct){
+    if(it.second.size()>2){
+      for(auto id : it.second){
+        cct[id]=1;
+      }
+    }
+  }
+
+  int tot = 0, num = 0;
+  for(auto x : cct){
+    if(x.second==1)num++;
+    tot++;
+  }
+  LOG(ERROR)<<"tot:"<<tot<<" num:"<<num<<" p:"<<(double)num/tot;
+  */
+
+  committer_->AsyncExecContract(execute_info);
+}
+
+absl::StatusOr<std::string> ContractManager::ExecContract(
+    const Address& caller_address, const Address& contract_address,
+    const Params& func_param) {
+  std::string func_addr =
+      deployer_->GetFuncAddress(contract_address, func_param.func_name());
+  if (func_addr.empty()) {
+    LOG(ERROR) << "no fouction:" << func_param.func_name();
+    return absl::InvalidArgumentError("Func not exist.");
+  }
+
+  absl::StatusOr<std::string> result = committer_->ExecContract(
+      caller_address, contract_address, func_addr, func_param, gs_.get());
+  if (result.ok()) {
+    return *result;
+  }
+  return result.status();
+}
+
+bool ContractManager::VerifyContract(
+    std::vector<ContractExecuteInfo>& ordered_info,
+    std::vector<ConcurrencyController ::ModifyMap> rws_list) {
+  return true;
+  for (int i = 0; i < ordered_info.size(); ++i) {
+    std::string func_addr =
+        deployer_->GetFuncAddress(ordered_info[i].contract_address,
+                                  ordered_info[i].func_params.func_name());
+    if (func_addr.empty()) {
+      LOG(ERROR) << "no fouction:" << ordered_info[i].func_params.func_name();
+      ordered_info[i].contract_address = 0;
+      continue;
+    }
+    ordered_info[i].func_addr = func_addr;
+  }
+  return verifier_->VerifyContract(ordered_info, rws_list);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.h b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.h
new file mode 100644
index 000000000..ac19e5ffc
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "absl/status/statusor.h"
+#include "eEVM/opcode.h"
+#include "service/contract/executor/common/utils.h"
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/contract_deployer.h"
+#include "service/contract/executor/manager/contract_verifier.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+class ContractManager {
+ public:
+  enum Options {
+    TwoPL = 1,
+    SCC = 2,
+    OOO = 3,
+    TwoPLOOO = 4,
+    Streaming = 5,
+    SingleStreaming = 6,
+    MultiStreaming = 7,
+    XE = 8,
+    XEO = 9,
+  };
+  ContractManager(std::unique_ptr<DataStorage> storage, int worker_num = 2,
+                  Options op = TwoPL);
+
+ public:
+  Address DeployContract(const Address& owner_address,
+                         const DeployInfo& deploy_info);
+
+  bool DeployContract(const Address& owner_address,
+                      const DeployInfo& deploy_info,
+                      const Address& contract_address);
+
+  absl::StatusOr<eevm::AccountState> GetContract(const Address& address);
+
+  absl::StatusOr<std::string> ExecContract(const Address& caller_address,
+                                           const Address& contract_address,
+                                           const Params& func_param);
+
+  std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& execute_info);
+
+  void AsyncExecContract(std::vector<ContractExecuteInfo>& execute_info);
+
+  void SetExecuteCallBack(
+      std::function<void(std::unique_ptr<ExecuteResp> resp)> func);
+
+  bool VerifyContract(std::vector<ContractExecuteInfo>& ordered_info,
+                      std::vector<ConcurrencyController ::ModifyMap> rws_list);
+
+ private:
+  std::string GetFuncAddress(const Address& contract_address,
+                             const std::string& func_name);
+  void SetFuncAddress(const Address& contract_address, const FuncInfo& func);
+
+ private:
+  std::unique_ptr<DataStorage> storage_;
+  std::unique_ptr<GlobalState> gs_;
+  std::unique_ptr<ContractCommitter> committer_;
+  std::unique_ptr<ContractDeployer> deployer_;
+  std::unique_ptr<ContractVerifier> verifier_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager_test.cpp
new file mode 100644
index 000000000..8373ceef4
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_manager_test.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_manager.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+#include "service/contract/executor/manager/address_manager.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
+                             std::string(getenv("TEST_WORKSPACE")) +
+                             "/service/contract/executor/manager/";
+
+Address get_random_address() { return AddressManager().CreateRandomAddress(); }
+
+std::string U256ToString(uint256_t v) { return eevm::to_hex_string(v); }
+uint256_t HexToInt(const std::string& v) { return eevm::to_uint256(v); }
+
+class ContractManagerTest : public Test {
+ public:
+  ContractManagerTest() : owner_address_(get_random_address()) {
+    LOG(ERROR) << "owner:" << owner_address_;
+    std::string contract_path = test_dir + "test_data/contract.json";
+
+    std::ifstream contract_fstream(contract_path);
+    if (!contract_fstream) {
+      throw std::runtime_error(fmt::format(
+          "Unable to open contract definition file {}", contract_path));
+    }
+
+    const auto contracts_definition = nlohmann::json::parse(contract_fstream);
+    const auto all_contracts = contracts_definition["contracts"];
+    const auto contract_code = all_contracts["ERC20.sol:ERC20Token"];
+    contract_json_ = contract_code;
+  }
+
+ protected:
+  Address owner_address_;
+  nlohmann::json contract_json_;
+};
+
+TEST_F(ContractManagerTest, NoContract) {
+  ContractManager manager(std::make_unique<DataStorage>());
+  auto account = manager.GetContract(1234);
+  EXPECT_FALSE(account.ok());
+}
+
+TEST_F(ContractManagerTest, DeployContract) {
+  ContractManager manager(std::make_unique<DataStorage>());
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+}
+
+TEST_F(ContractManagerTest, InitContract) {
+  ContractManager manager(std::make_unique<DataStorage>());
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+  LOG(ERROR) << " deploy done:" << owner_address_;
+  Params func_params;
+  func_params.set_func_name("totalSupply()");
+  auto result =
+      manager.ExecContract(owner_address_, contract_address, func_params);
+  EXPECT_EQ(HexToInt(*result), 1000);
+}
+
+TEST_F(ContractManagerTest, ExecContract) {
+  ContractManager manager(std::make_unique<DataStorage>());
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+  Address transfer_receiver = get_random_address();
+  Address transfer_receiver2 = get_random_address();
+
+  // owner 1000
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(owner_address_));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1000);
+  }
+
+  // receiver 0
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(transfer_receiver));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 0);
+  }
+
+  // transfer 400 to receiver
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(400));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1);
+  }
+
+  // receiver 400
+  {
+    Address caller = get_random_address();
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(transfer_receiver));
+
+    auto result = manager.ExecContract(caller, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 400);
+  }
+  // owner 600
+  {
+    Address caller = get_random_address();
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(owner_address_));
+
+    auto result = manager.ExecContract(caller, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 600);
+  }
+
+  // transfer 200 to receiver2 from receiver
+  {
+    Params func_params;
+    func_params.set_func_name("approve(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(200));
+
+    auto result =
+        manager.ExecContract(transfer_receiver, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1);
+  }
+  {
+    Params func_params;
+    func_params.set_func_name("transferFrom(address,address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(transfer_receiver2));
+    func_params.add_param(U256ToString(200));
+
+    auto result =
+        manager.ExecContract(transfer_receiver, contract_address, func_params);
+    EXPECT_EQ(HexToInt(*result), 1);
+  }
+}
+
+TEST_F(ContractManagerTest, NoFunc) {
+  ContractManager manager(std::make_unique<DataStorage>());
+
+  DeployInfo deploy_info;
+  deploy_info.set_contract_bin(contract_json_["bin"]);
+  for (auto& func : contract_json_["hashes"].items()) {
+    FuncInfo* new_func = deploy_info.add_func_info();
+    new_func->set_func_name(func.key());
+    new_func->set_hash(func.value());
+  }
+
+  deploy_info.add_init_param(U256ToString(1000));
+
+  Address contract_address =
+      manager.DeployContract(owner_address_, deploy_info);
+  EXPECT_GT(contract_address, 0);
+  auto account = manager.GetContract(contract_address);
+  EXPECT_TRUE(account.ok());
+
+  // owner 1000
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf()");
+    func_params.add_param(U256ToString(owner_address_));
+
+    auto result =
+        manager.ExecContract(owner_address_, contract_address, func_params);
+    EXPECT_FALSE(result.ok());
+  }
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.cpp
new file mode 100644
index 000000000..451c0c3f4
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/contract_verifier.h"
+
+namespace resdb {
+namespace contract {
+
+ContractVerifier::ContractVerifier() {
+  executor_ = std::make_unique<ContractExecutor>();
+}
+
+ContractVerifier::~ContractVerifier() {}
+
+std::vector<std::unique_ptr<ExecuteResp>> ContractVerifier::ExecContract(
+    std::vector<ContractExecuteInfo>& request) {
+  return std::vector<std::unique_ptr<ExecuteResp>>();
+}
+
+absl::StatusOr<std::string> ContractVerifier::ExecContract(
+    const Address& caller_address, const Address& contract_address,
+    const std::string& func_addr, const Params& func_param, EVMState* state) {
+  return executor_->ExecContract(caller_address, contract_address, func_addr,
+                                 func_param, state);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.h b/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.h
new file mode 100644
index 000000000..04b88e950
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/contract_verifier.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "absl/status/statusor.h"
+#include "service/contract/executor/manager/committer_context.h"
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/contract_executor.h"
+
+namespace resdb {
+namespace contract {
+
+class ContractVerifier : public ContractCommitter {
+ public:
+  ContractVerifier();
+  virtual ~ContractVerifier();
+
+  virtual bool VerifyContract(
+      const std::vector<ContractExecuteInfo>& request_list,
+      const std::vector<ConcurrencyController ::ModifyMap>& rws_list) = 0;
+
+  std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& request) override;
+
+  absl::StatusOr<std::string> ExecContract(const Address& caller_address,
+                                           const Address& contract_address,
+                                           const std::string& func_addr,
+                                           const Params& func_param,
+                                           EVMState* state) override;
+
+ protected:
+  std::unique_ptr<ContractExecutor> executor_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.cpp
new file mode 100644
index 000000000..eade73c28
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.cpp
@@ -0,0 +1,162 @@
+#include "service/contract/executor/manager/d_storage.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+namespace {
+
+int GetHashKey(const uint256_t& address) {
+  // Get big-endian form
+  const uint8_t* bytes = intx::as_bytes(address);
+  // uint8_t arr[32] = {};
+  // memset(arr,0,sizeof(arr));
+  // intx::be::store(arr, address);
+  // const uint8_t* bytes = arr;
+  size_t sz = sizeof(address);
+  int v = 0;
+  for (int i = 0; i < sz; ++i) {
+    v += bytes[i];
+  }
+  return v % 1024;
+}
+
+void InternalReset(const uint256_t& key, const uint256_t& value,
+                   int64_t version,
+                   std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                   std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  (*db)[key] = std::make_pair(value, version);
+}
+
+int64_t InternalStore(const uint256_t& key, const uint256_t& value,
+                      std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                      std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  int64_t v = (*db)[key].second;
+  (*db)[key] = std::make_pair(value, v + 1);
+  // LOG(ERROR)<<"store key:"<<key<<" v:"<<v+1;
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> InternalLoad(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) return std::make_pair(0, 0);
+  return e->second;
+}
+
+bool InternalRemove(const uint256_t& key,
+                    std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                    std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) return false;
+  db->erase(e);
+  return true;
+}
+
+bool InternalExist(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  return db->find(key) != db->end();
+}
+
+int64_t InternalGetVersion(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  auto it = db->find(key);
+  if (it == db->end()) {
+    // LOG(ERROR)<<"get version key:"<<key<<" v:"<<0;
+    return 0;
+  }
+  // LOG(ERROR)<<"get version key:"<<key<<" v:"<<it->second.second;
+  return it->second.second;
+}
+
+}  // namespace
+
+int64_t D_Storage::Store(const uint256_t& key, const uint256_t& value,
+                         bool is_to_local_view) {
+  // LOG(ERROR)<<"store key:"<<key<<" value:"<<value<<"
+  // local:"<<is_to_local_view;
+  int idx = GetHashKey(key);
+  if (is_to_local_view) {
+    return InternalStore(key, value, &c_s_[idx], &mutex_[idx]);
+  } else {
+    return InternalStore(key, value, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+std::pair<uint256_t, int64_t> D_Storage::Load(const uint256_t& key,
+                                              bool is_local_view) const {
+  // LOG(ERROR)<<"load key:"<<key<<" local:"<<is_local_view;
+  int idx = GetHashKey(key);
+  if (is_local_view) {
+    auto ret = InternalLoad(key, &c_s_[idx], &mutex_[idx]);
+    if (ret.second == 0) {
+      // LOG(ERROR)<<"get from global:";
+      return InternalLoad(key, &g_s_[idx], &mutex_[idx]);
+    }
+    return ret;
+  } else {
+    return InternalLoad(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+bool D_Storage::Remove(const uint256_t& key, bool is_local) {
+  int idx = GetHashKey(key);
+  if (is_local) {
+    return InternalRemove(key, &c_s_[idx], &mutex_[idx]);
+  } else {
+    return InternalRemove(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+bool D_Storage::Exist(const uint256_t& key, bool is_local) const {
+  int idx = GetHashKey(key);
+  if (is_local) {
+    return InternalExist(key, &c_s_[idx], &mutex_[idx]);
+  } else {
+    return InternalExist(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+int64_t D_Storage::GetVersion(const uint256_t& key, bool is_local) const {
+  // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local;
+  int idx = GetHashKey(key);
+  if (is_local) {
+    int ret = InternalGetVersion(key, &c_s_[idx], &mutex_[idx]);
+    if (ret == 0) {
+      ret = InternalGetVersion(key, &g_s_[idx], &g_mutex_[idx]);
+      // LOG(ERROR)<<"get from global:"<<ret;
+    }
+    // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local<<" v:"<<ret;
+    return ret;
+  } else {
+    return InternalGetVersion(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+void D_Storage::Reset(const uint256_t& key, const uint256_t& value,
+                      int64_t version, bool is_local) {
+  // LOG(ERROR)<<"set key:"<<key<<" value:"<<value<<" local:"<<is_local<<"
+  // version:"<<version;
+  int idx = GetHashKey(key);
+  if (is_local) {
+    InternalReset(key, value, version, &c_s_[idx], &mutex_[idx]);
+  } else {
+    InternalReset(key, value, version, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.h
new file mode 100644
index 000000000..1ae1d775c
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/d_storage.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "eEVM/util.h"
+#include "service/contract/executor/manager/data_storage.h"
+
+namespace resdb {
+namespace contract {
+
+class D_Storage : public DataStorage {
+ public:
+  virtual int64_t Store(const uint256_t& key, const uint256_t& value,
+                        bool is_local);
+  virtual std::pair<uint256_t, int64_t> Load(const uint256_t& key,
+                                             bool is_from_local_view) const;
+  virtual bool Remove(const uint256_t& key, bool is_local);
+  virtual bool Exist(const uint256_t& key, bool is_local) const;
+
+  virtual int64_t GetVersion(const uint256_t& key, bool is_local) const;
+
+  virtual void Reset(const uint256_t& key, const uint256_t& value,
+                     int64_t version, bool is_local);
+
+ protected:
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > c_s_[1024];
+  mutable std::shared_mutex mutex_[1024];
+
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > g_s_[1024];
+  mutable std::shared_mutex g_mutex_[1024];
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.cpp
new file mode 100644
index 000000000..f1719209e
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.cpp
@@ -0,0 +1,72 @@
+#include "service/contract/executor/manager/data_storage.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+namespace {
+
+int GetHashKey(const uint256_t& address) {
+  // Get big-endian form
+  const uint8_t* bytes = intx::as_bytes(address);
+  // uint8_t arr[32] = {};
+  // memset(arr,0,sizeof(arr));
+  // intx::be::store(arr, address);
+  // const uint8_t* bytes = arr;
+  size_t sz = sizeof(address);
+  int v = 0;
+  for (int i = 0; i < sz; ++i) {
+    v += bytes[i];
+  }
+  return 0;
+  return v % 2048;
+}
+}  // namespace
+
+int64_t DataStorage::Store(const uint256_t& key, const uint256_t& value, bool) {
+  int idx = GetHashKey(key);
+  std::unique_lock lock(mutex_[idx]);
+  // LOG(ERROR)<<"store key:"<<key<<" value:"<<value;
+  int64_t v = s[key].second;
+  s[key] = std::make_pair(value, v + 1);
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> DataStorage::Load(const uint256_t& key,
+                                                bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  // LOG(ERROR)<<"load key:"<<key;
+  auto e = s.find(key);
+  if (e == s.end()) return std::make_pair(0, 0);
+  return e->second;
+}
+
+bool DataStorage::Remove(const uint256_t& key, bool) {
+  int idx = GetHashKey(key);
+  std::unique_lock lock(mutex_[idx]);
+  auto e = s.find(key);
+  if (e == s.end()) return false;
+  s.erase(e);
+  return true;
+}
+
+bool DataStorage::Exist(const uint256_t& key, bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  return s.find(key) != s.end();
+}
+
+int64_t DataStorage::GetVersion(const uint256_t& key, bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  auto it = s.find(key);
+  if (it == s.end()) {
+    return 0;
+  }
+  return it->second.second;
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.h
new file mode 100644
index 000000000..f3c72de0a
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/data_storage.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
+
+class DataStorage {
+ public:
+  DataStorage() = default;
+  virtual ~DataStorage() = default;
+
+  virtual int64_t Store(const uint256_t& key, const uint256_t& value,
+                        bool is_local = false);
+  virtual std::pair<uint256_t, int64_t> Load(const uint256_t& key,
+                                             bool is_local_view = false) const;
+  virtual bool Remove(const uint256_t& key, bool is_local = false);
+  virtual bool Exist(const uint256_t& key, bool is_local = false) const;
+
+  virtual int64_t GetVersion(const uint256_t& key, bool is_local = false) const;
+
+  virtual void Reset(const uint256_t& key, const uint256_t& value,
+                     int64_t version, bool is_local = false) {}
+  virtual void Flush(){};
+
+ protected:
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > s;
+  // std::map<uint256_t, std::pair<uint256_t,int64_t> > s[4096];
+  mutable std::shared_mutex mutex_[4096];
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/evm_state.h b/platform/consensus/ordering/thunderbolt/executor/manager/evm_state.h
new file mode 100644
index 000000000..b1897765b
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/evm_state.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "eEVM/globalstate.h"
+
+namespace resdb {
+namespace contract {
+
+class EVMState : public eevm::GlobalState {
+ public:
+  EVMState() = default;
+  virtual ~EVMState() = default;
+
+ protected:
+  const eevm::Block& get_current_block() override { return block_; }
+  uint256_t get_block_hash(uint8_t offset) override { return 0; }
+
+ private:
+  // Unused.
+  eevm::Block block_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/global_state.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/global_state.cpp
new file mode 100644
index 000000000..423980006
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/global_state.cpp
@@ -0,0 +1,46 @@
+#include "service/contract/executor/manager/global_state.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+using eevm::AccountState;
+using eevm::Address;
+using eevm::Code;
+using eevm::SimpleAccount;
+
+GlobalState::GlobalState(DataStorage* storage) : storage_(storage) {}
+
+bool GlobalState::Exists(const eevm::Address& addr) {
+  return accounts.find(addr) != accounts.cend();
+}
+
+void GlobalState::remove(const Address& addr) { accounts.erase(addr); }
+
+AccountState GlobalState::get(const Address& addr) {
+  const auto acc = accounts.find(addr);
+  if (acc != accounts.cend()) return acc->second;
+
+  return create(addr, 0, {});
+}
+
+AccountState GlobalState::create(const Address& addr, const uint256_t& balance,
+                                 const Code& code) {
+  Insert({SimpleAccount(addr, balance, code), GlobalView(storage_)});
+
+  return get(addr);
+}
+
+const eevm::SimpleAccount& GlobalState::GetAccount(const eevm::Address& addr) {
+  const auto acc = accounts.find(addr);
+  return acc->second.first;
+}
+
+void GlobalState::Insert(const StateEntry& p) {
+  const auto ib = accounts.insert(std::make_pair(p.first.get_address(), p));
+
+  assert(ib.second);
+}
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/global_state.h b/platform/consensus/ordering/thunderbolt/executor/manager/global_state.h
new file mode 100644
index 000000000..c3c9ca7f7
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/global_state.h
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "eEVM/simple/simpleaccount.h"
+#include "service/contract/executor/manager/evm_state.h"
+#include "service/contract/executor/manager/global_view.h"
+
+namespace resdb {
+namespace contract {
+
+class GlobalState : public EVMState {
+ public:
+  using StateEntry = std::pair<eevm::SimpleAccount, GlobalView>;
+
+ public:
+  GlobalState(DataStorage* storage);
+  virtual ~GlobalState() = default;
+
+  virtual void remove(const eevm::Address& addr) override;
+
+  // Get contract by contract address.
+  eevm::AccountState get(const eevm::Address& addr) override;
+
+  bool Exists(const eevm::Address& addr);
+
+  // Create an account for the contract, which the balance is 0.
+  eevm::AccountState create(const eevm::Address& addr, const uint256_t& balance,
+                            const eevm::Code& code) override;
+
+  const eevm::SimpleAccount& GetAccount(const eevm::Address& addr);
+
+ protected:
+  void Insert(const StateEntry& p);
+
+ private:
+  std::map<eevm::Address, StateEntry> accounts;
+  DataStorage* storage_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/global_view.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/global_view.cpp
new file mode 100644
index 000000000..5bd892496
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/global_view.cpp
@@ -0,0 +1,23 @@
+#include "service/contract/executor/manager/global_view.h"
+
+#include <glog/logging.h>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
+
+GlobalView::GlobalView(DataStorage* storage) : storage_(storage) {}
+
+void GlobalView::store(const uint256_t& key, const uint256_t& value) {
+  storage_->Store(key, value);
+}
+
+uint256_t GlobalView::load(const uint256_t& key) {
+  return storage_->Load(key).first;
+}
+
+bool GlobalView::remove(const uint256_t& key) { return storage_->Remove(key); }
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/global_view.h b/platform/consensus/ordering/thunderbolt/executor/manager/global_view.h
new file mode 100644
index 000000000..c54e27408
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/global_view.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <map>
+
+#include "eEVM/storage.h"
+#include "service/contract/executor/manager/data_storage.h"
+
+namespace resdb {
+namespace contract {
+
+class GlobalView : public eevm::Storage {
+ public:
+  GlobalView(DataStorage* storage);
+  virtual ~GlobalView() = default;
+
+  void store(const uint256_t& key, const uint256_t& value) override;
+  uint256_t load(const uint256_t& key) override;
+  bool remove(const uint256_t& key) override;
+
+ private:
+  DataStorage* storage_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.cpp
new file mode 100644
index 000000000..caabb0eed
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.cpp
@@ -0,0 +1,207 @@
+#include "service/contract/executor/manager/level_d_storage.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+namespace {
+
+void InternalReset(const uint256_t& key, const uint256_t& value,
+                   int64_t version,
+                   std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                   std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  (*db)[key] = std::make_pair(value, version);
+}
+
+int64_t InternalStore(const uint256_t& key, const uint256_t& value,
+                      std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                      std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  int64_t v = (*db)[key].second;
+  (*db)[key] = std::make_pair(value, v + 1);
+  // LOG(ERROR)<<"store key:"<<key<<" v:"<<v+1;
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> InternalLoad(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) return std::make_pair(0, 0);
+  return e->second;
+}
+
+bool InternalRemove(const uint256_t& key,
+                    std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                    std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) return false;
+  db->erase(e);
+  return true;
+}
+
+bool InternalExist(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  return db->find(key) != db->end();
+}
+
+int64_t InternalGetVersion(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  auto it = db->find(key);
+  if (it == db->end()) {
+    // LOG(ERROR)<<"get version key:"<<key<<" v:"<<0;
+    return 0;
+  }
+  // LOG(ERROR)<<"get version key:"<<key<<" v:"<<it->second.second;
+  return it->second.second;
+}
+
+std::string GetString(const uint256_t& key) { return ""; }
+
+uint256_t GetInt256(const std::string& value) { return 0; }
+
+std::string GetData(const uint256_t& value, int64_t version) {
+  std::string v_str = GetString(value);
+  std::string v((const char*)&version, sizeof(value));
+  v.append(v_str, v_str.size());
+  return v;
+}
+
+int64_t GetVersion(const std::string& value) {
+  int64_t v;
+  memcpy(&v, value.c_str(), sizeof(v));
+  return v;
+}
+
+uint256_t GetValue(const std::string& value) {
+  return GetInt256(std::string(value.c_str() + sizeof(int64_t),
+                               value.size() - sizeof(int64_t)));
+}
+
+int64_t InternalStore(const uint256_t& key, const uint256_t& value,
+                      ResLevelDB* db, std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  std::string old_value = db->GetValue(GetString(key));
+  int64_t v = GetVersion(old_value);
+  db->SetValue(GetString(key), GetData(value, v + 1));
+  // LOG(ERROR)<<"store key:"<<key<<" v:"<<v+1;
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> InternalLoad(const uint256_t& key, ResLevelDB* db,
+                                           std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  std::string value = db->GetValue(GetString(key));
+  return std::make_pair(GetValue(value), GetVersion(value));
+}
+
+bool InternalRemove(const uint256_t& key, ResLevelDB* db,
+                    std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  db->SetValue(GetString(key), "");
+  return true;
+}
+
+bool InternalExist(const uint256_t& key, ResLevelDB* db,
+                   std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  std::string value = db->GetValue(GetString(key));
+  return value.empty();
+}
+
+void InternalReset(const uint256_t& key, const uint256_t& value,
+                   int64_t version, ResLevelDB* db, std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  db->SetValue(GetString(key), GetData(value, version));
+}
+
+int64_t InternalGetVersion(const uint256_t& key, ResLevelDB* db,
+                           std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  std::string value = db->GetValue(GetString(key));
+  return GetVersion(value);
+}
+
+}  // namespace
+
+int64_t D_Storage::Store(const uint256_t& key, const uint256_t& value,
+                         bool is_to_local_view) {
+  // LOG(ERROR)<<"store key:"<<key<<" value:"<<value<<"
+  // local:"<<is_to_local_view;
+  if (is_to_local_view) {
+    return InternalStore(key, value, &c_s_, &mutex_);
+  } else {
+    return InternalStore(key, value, g_s_.get(), &g_mutex_);
+  }
+}
+
+std::pair<uint256_t, int64_t> D_Storage::Load(const uint256_t& key,
+                                              bool is_local_view) const {
+  // LOG(ERROR)<<"load key:"<<key<<" local:"<<is_local_view;
+  if (is_local_view) {
+    auto ret = InternalLoad(key, &c_s_, &mutex_);
+    if (ret.second == 0) {
+      // LOG(ERROR)<<"get from global:";
+      return InternalLoad(key, g_s_.get(), &mutex_);
+    }
+    return ret;
+  } else {
+    return InternalLoad(key, g_s_.get(), &g_mutex_);
+  }
+}
+
+bool D_Storage::Remove(const uint256_t& key, bool is_local) {
+  if (is_local) {
+    return InternalRemove(key, &c_s_, &mutex_);
+  } else {
+    return InternalRemove(key, g_s_.get(), &g_mutex_);
+  }
+}
+
+bool D_Storage::Exist(const uint256_t& key, bool is_local) const {
+  if (is_local) {
+    return InternalExist(key, &c_s_, &mutex_);
+  } else {
+    return InternalExist(key, g_s_.get(), &g_mutex_);
+  }
+}
+
+int64_t D_Storage::GetVersion(const uint256_t& key, bool is_local) const {
+  // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local;
+  if (is_local) {
+    int ret = InternalGetVersion(key, &c_s_, &mutex_);
+    if (ret == 0) {
+      ret = InternalGetVersion(key, g_s_.get(), &g_mutex_);
+      // LOG(ERROR)<<"get from global:"<<ret;
+    }
+    // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local<<" v:"<<ret;
+    return ret;
+  } else {
+    return InternalGetVersion(key, g_s_.get(), &g_mutex_);
+  }
+}
+
+void D_Storage::Reset(const uint256_t& key, const uint256_t& value,
+                      int64_t version, bool is_local) {
+  // LOG(ERROR)<<"set key:"<<key<<" value:"<<value<<" local:"<<is_local<<"
+  // version:"<<version;
+  if (is_local) {
+    InternalReset(key, value, version, &c_s_, &mutex_);
+  } else {
+    InternalReset(key, value, version, g_s_.get(), &g_mutex_);
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.h
new file mode 100644
index 000000000..89aba9b64
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/level_d_storage.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "eEVM/util.h"
+#include "service/contract/executor/manager/data_storage.h"
+#include "storage/res_leveldb.h"
+
+namespace resdb {
+namespace contract {
+
+class D_Storage : public DataStorage {
+ public:
+  virtual int64_t Store(const uint256_t& key, const uint256_t& value,
+                        bool is_local);
+  virtual std::pair<uint256_t, int64_t> Load(const uint256_t& key,
+                                             bool is_from_local_view) const;
+  virtual bool Remove(const uint256_t& key, bool is_local);
+  virtual bool Exist(const uint256_t& key, bool is_local) const;
+
+  virtual int64_t GetVersion(const uint256_t& key, bool is_local) const;
+
+  virtual void Reset(const uint256_t& key, const uint256_t& value,
+                     int64_t version, bool is_local);
+
+ protected:
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > c_s_;
+  mutable std::shared_mutex mutex_;
+
+  std::unique_ptr<ResLevelDB> g_s_;
+  mutable std::shared_mutex g_mutex_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.cpp
new file mode 100644
index 000000000..354f63cb9
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.cpp
@@ -0,0 +1,30 @@
+#include "service/contract/executor/manager/leveldb.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+LevelDB::LevelDB() {
+  db_ = std::make_unique<ResLevelDB>("./");
+  db_->SetBatchSize(10000);
+}
+
+void LevelDB::Flush() {
+  // LOG(ERROR)<<"flush";
+  for (const auto& it : s) {
+    std::string addr = eevm::to_hex_string(it.first);
+    std::string value = eevm::to_hex_string(it.second.first);
+    // LOG(ERROR)<<"addr:"<<addr<<" value:"<<value;
+    char* buf = new char[value.size() + sizeof(it.second.second)];
+    memcpy(buf, &it.second.second, sizeof(it.second.second));
+    memcpy(buf + sizeof(it.second.second), value.c_str(), value.size());
+
+    db_->SetValue(addr,
+                  std::string(buf, value.size() + sizeof(it.second.second)));
+    delete buf;
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.h b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.h
new file mode 100644
index 000000000..3442cf50e
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "eEVM/util.h"
+#include "service/contract/executor/manager/data_storage.h"
+#include "storage/res_leveldb.h"
+
+namespace resdb {
+namespace contract {
+
+class LevelDB : public DataStorage {
+ public:
+  LevelDB();
+  virtual ~LevelDB() = default;
+
+  virtual void Flush();
+
+ private:
+  std::unique_ptr<ResLevelDB> db_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.cpp
new file mode 100644
index 000000000..2e827e775
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.cpp
@@ -0,0 +1,203 @@
+
+#include "service/contract/executor/manager/leveldb_d_storage.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+namespace {
+
+int GetHashKey(const uint256_t& address) {
+  // Get big-endian form
+  const uint8_t* bytes = intx::as_bytes(address);
+  // uint8_t arr[32] = {};
+  // memset(arr,0,sizeof(arr));
+  // intx::be::store(arr, address);
+  // const uint8_t* bytes = arr;
+  size_t sz = sizeof(address);
+  int v = 0;
+  for (int i = 0; i < sz; ++i) {
+    v += bytes[i];
+  }
+  return v % 1024;
+}
+
+void Write(const uint256_t& key, const uint256_t& value, int version,
+           ResLevelDB* db) {
+  std::string addr = eevm::to_hex_string(key);
+
+  const uint8_t* bytes = intx::as_bytes(value);
+  size_t sz = sizeof(value);
+  db->SetValue(addr, std::string((const char*)bytes, sz));
+  return;
+}
+
+uint256_t Read(const uint256_t& key, ResLevelDB* db) {
+  std::string addr = eevm::to_hex_string(key);
+
+  std::string v = db->GetValue(addr);
+  if (v.empty()) {
+    return 0;
+  }
+
+  uint8_t tmp[32] = {};
+  memcpy(tmp, v.c_str(), 32);
+  return intx::le::load<uint256_t>(tmp);
+}
+
+void InternalReset(const uint256_t& key, const uint256_t& value,
+                   int64_t version,
+                   std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                   std::shared_mutex* mutex, ResLevelDB* storage) {
+  std::unique_lock lock(*mutex);
+  (*db)[key] = std::make_pair(value, version);
+  if (storage) {
+    Write(key, value, version, storage);
+  }
+}
+
+int64_t InternalStore(const uint256_t& key, const uint256_t& value,
+                      std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                      std::shared_mutex* mutex, ResLevelDB* storage) {
+  std::unique_lock lock(*mutex);
+  int64_t v = (*db)[key].second;
+  (*db)[key] = std::make_pair(value, v + 1);
+  if (storage) {
+    Write(key, value, v + 1, storage);
+  }
+  // LOG(ERROR)<<"store key:"<<key<<" v:"<<v+1;
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> InternalLoad(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex, ResLevelDB* storage) {
+  std::shared_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) {
+    if (storage) {
+      // LOG(ERROR)<<"load from db:";
+      return std::make_pair(Read(key, storage), 0);
+    }
+    return std::make_pair(0, 0);
+  }
+  return e->second;
+}
+
+bool InternalRemove(const uint256_t& key,
+                    std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+                    std::shared_mutex* mutex) {
+  std::unique_lock lock(*mutex);
+  auto e = db->find(key);
+  if (e == db->end()) return false;
+  db->erase(e);
+  return true;
+}
+
+bool InternalExist(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  return db->find(key) != db->end();
+}
+
+int64_t InternalGetVersion(
+    const uint256_t& key,
+    const std::map<uint256_t, std::pair<uint256_t, int64_t> >* db,
+    std::shared_mutex* mutex) {
+  std::shared_lock lock(*mutex);
+  auto it = db->find(key);
+  if (it == db->end()) {
+    // LOG(ERROR)<<"get version key:"<<key<<" v:"<<0;
+    return 0;
+  }
+  // LOG(ERROR)<<"get version key:"<<key<<" v:"<<it->second.second;
+  return it->second.second;
+}
+
+}  // namespace
+
+LevelDB_D_Storage ::LevelDB_D_Storage() {
+  db_ = std::make_unique<ResLevelDB>("./");
+}
+
+int64_t LevelDB_D_Storage::Store(const uint256_t& key, const uint256_t& value,
+                                 bool is_to_local_view) {
+  // LOG(ERROR)<<"store key:"<<key<<" value:"<<value<<"
+  // local:"<<is_to_local_view;
+  int idx = GetHashKey(key);
+  if (is_to_local_view) {
+    return InternalStore(key, value, &c_s_[idx], &mutex_[idx], nullptr);
+  } else {
+    return InternalStore(key, value, &g_s_[idx], &g_mutex_[idx], db_.get());
+  }
+}
+
+std::pair<uint256_t, int64_t> LevelDB_D_Storage::Load(
+    const uint256_t& key, bool is_local_view) const {
+  // LOG(ERROR)<<"load key:"<<key<<" local:"<<is_local_view;
+  int idx = GetHashKey(key);
+  if (is_local_view) {
+    auto ret = InternalLoad(key, &c_s_[idx], &mutex_[idx], nullptr);
+    if (ret.second == 0) {
+      // LOG(ERROR)<<"get from global:";
+      return InternalLoad(key, &g_s_[idx], &mutex_[idx], db_.get());
+    }
+    return ret;
+  } else {
+    return InternalLoad(key, &g_s_[idx], &g_mutex_[idx], db_.get());
+  }
+}
+
+bool LevelDB_D_Storage::Remove(const uint256_t& key, bool is_local) {
+  int idx = GetHashKey(key);
+  if (is_local) {
+    return InternalRemove(key, &c_s_[idx], &mutex_[idx]);
+  } else {
+    return InternalRemove(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+bool LevelDB_D_Storage::Exist(const uint256_t& key, bool is_local) const {
+  int idx = GetHashKey(key);
+  if (is_local) {
+    return InternalExist(key, &c_s_[idx], &mutex_[idx]);
+  } else {
+    return InternalExist(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+int64_t LevelDB_D_Storage::GetVersion(const uint256_t& key,
+                                      bool is_local) const {
+  // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local;
+  int idx = GetHashKey(key);
+  if (is_local) {
+    int ret = InternalGetVersion(key, &c_s_[idx], &mutex_[idx]);
+    if (ret == 0) {
+      ret = InternalGetVersion(key, &g_s_[idx], &g_mutex_[idx]);
+      // LOG(ERROR)<<"get from global:"<<ret;
+    }
+    // LOG(ERROR)<<"get version key:"<<key<<" islocal:"<<is_local<<" v:"<<ret;
+    return ret;
+  } else {
+    return InternalGetVersion(key, &g_s_[idx], &g_mutex_[idx]);
+  }
+}
+
+void LevelDB_D_Storage::Reset(const uint256_t& key, const uint256_t& value,
+                              int64_t version, bool is_local) {
+  // LOG(ERROR)<<"set key:"<<key<<" value:"<<value<<" local:"<<is_local<<"
+  // version:"<<version;
+  int idx = GetHashKey(key);
+  if (is_local) {
+    InternalReset(key, value, version, &c_s_[idx], &mutex_[idx], nullptr);
+  } else {
+    InternalReset(key, value, version, &g_s_[idx], &g_mutex_[idx], db_.get());
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.h
new file mode 100644
index 000000000..4d69165c1
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_d_storage.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "service/contract/executor/manager/data_storage.h"
+#include "storage/res_leveldb.h"
+
+namespace resdb {
+namespace contract {
+
+class LevelDB_D_Storage : public DataStorage {
+ public:
+  LevelDB_D_Storage();
+
+ public:
+  virtual int64_t Store(const uint256_t& key, const uint256_t& value,
+                        bool is_local);
+  virtual std::pair<uint256_t, int64_t> Load(const uint256_t& key,
+                                             bool is_from_local_view) const;
+  virtual bool Remove(const uint256_t& key, bool is_local);
+  virtual bool Exist(const uint256_t& key, bool is_local) const;
+
+  virtual int64_t GetVersion(const uint256_t& key, bool is_local) const;
+
+  virtual void Reset(const uint256_t& key, const uint256_t& value,
+                     int64_t version, bool is_local);
+
+ protected:
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > c_s_[1024];
+  mutable std::shared_mutex mutex_[1024];
+
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > g_s_[1024];
+  mutable std::shared_mutex g_mutex_[1024];
+
+  std::unique_ptr<ResLevelDB> db_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.cpp
new file mode 100644
index 000000000..d650b1e9d
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.cpp
@@ -0,0 +1,111 @@
+#include "service/contract/executor/manager/leveldb_storage.h"
+
+#include "glog/logging.h"
+
+namespace resdb {
+namespace contract {
+
+namespace {
+
+int GetHashKey(const uint256_t& address) {
+  // Get big-endian form
+  const uint8_t* bytes = intx::as_bytes(address);
+  // uint8_t arr[32] = {};
+  // memset(arr,0,sizeof(arr));
+  // intx::be::store(arr, address);
+  // const uint8_t* bytes = arr;
+  size_t sz = sizeof(address);
+  int v = 0;
+  for (int i = 0; i < sz; ++i) {
+    v += bytes[i];
+  }
+  return 0;
+  return v % 2048;
+}
+}  // namespace
+
+LevelDBStorage ::LevelDBStorage() { db_ = std::make_unique<ResLevelDB>("./"); }
+
+void LevelDBStorage::Write(const uint256_t& key, const uint256_t& value,
+                           int version) {
+  std::string addr = eevm::to_hex_string(key);
+
+  const uint8_t* bytes = intx::as_bytes(value);
+  size_t sz = sizeof(value);
+  db_->SetValue(addr, std::string((const char*)bytes, sz));
+  return;
+
+  // LOG(ERROR)<<"addr:"<<addr<<" value:"<<value;
+  char* buf = new char[sz + sizeof(version)];
+  memcpy(buf, &version, sizeof(version));
+  memcpy(buf + sizeof(value), bytes, sz);
+
+  db_->SetValue(addr, std::string(buf, sz + sizeof(version)));
+  LOG(ERROR) << "write db";
+  delete buf;
+}
+
+uint256_t LevelDBStorage::Read(const uint256_t& key) const {
+  std::string addr = eevm::to_hex_string(key);
+
+  std::string v = db_->GetValue(addr);
+  if (v.empty()) {
+    return 0;
+  }
+
+  uint8_t tmp[32] = {};
+  memcpy(tmp, v.c_str(), 32);
+  return intx::le::load<uint256_t>(tmp);
+}
+
+int64_t LevelDBStorage::Store(const uint256_t& key, const uint256_t& value,
+                              bool) {
+  int idx = GetHashKey(key);
+  std::unique_lock lock(mutex_[idx]);
+  // LOG(ERROR)<<"store key:"<<key<<" value:"<<value;
+  int64_t v = s[idx][key].second;
+  s[idx][key] = std::make_pair(value, v + 1);
+  Write(key, value, v + 1);
+  return v + 1;
+}
+
+std::pair<uint256_t, int64_t> LevelDBStorage::Load(const uint256_t& key,
+                                                   bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  // LOG(ERROR)<<"load key:"<<key;
+  auto e = s[idx].find(key);
+  if (e == s[idx].end()) {
+    uint256_t v = Read(key);
+    return std::make_pair(v, 0);
+  }
+  return e->second;
+}
+
+bool LevelDBStorage::Remove(const uint256_t& key, bool) {
+  int idx = GetHashKey(key);
+  std::unique_lock lock(mutex_[idx]);
+  auto e = s[idx].find(key);
+  if (e == s[idx].end()) return false;
+  s[idx].erase(e);
+  return true;
+}
+
+bool LevelDBStorage::Exist(const uint256_t& key, bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  return s[idx].find(key) != s[idx].end();
+}
+
+int64_t LevelDBStorage::GetVersion(const uint256_t& key, bool) const {
+  int idx = GetHashKey(key);
+  std::shared_lock lock(mutex_[idx]);
+  auto it = s[idx].find(key);
+  if (it == s[idx].end()) {
+    return 0;
+  }
+  return it->second.second;
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.h
new file mode 100644
index 000000000..822294c84
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/leveldb_storage.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include <map>
+#include <shared_mutex>
+
+#include "service/contract/executor/manager/data_storage.h"
+#include "storage/res_leveldb.h"
+
+namespace resdb {
+namespace contract {
+
+class LevelDBStorage : public DataStorage {
+ public:
+  LevelDBStorage();
+  virtual ~LevelDBStorage() = default;
+
+  virtual int64_t Store(const uint256_t& key, const uint256_t& value,
+                        bool is_local = false);
+  virtual std::pair<uint256_t, int64_t> Load(const uint256_t& key,
+                                             bool is_local_view = false) const;
+  virtual bool Remove(const uint256_t& key, bool is_local = false);
+  virtual bool Exist(const uint256_t& key, bool is_local = false) const;
+
+  virtual int64_t GetVersion(const uint256_t& key, bool is_local = false) const;
+
+  virtual void Reset(const uint256_t& key, const uint256_t& value,
+                     int64_t version, bool is_local = false) {}
+  virtual void Flush(){};
+
+ private:
+  void Write(const uint256_t& key, const uint256_t& value, int version);
+  uint256_t Read(const uint256_t& key) const;
+
+ protected:
+  std::map<uint256_t, std::pair<uint256_t, int64_t> > s[4096];
+  mutable std::shared_mutex mutex_[4096];
+  std::unique_ptr<ResLevelDB> db_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/local_state.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/local_state.cpp
new file mode 100644
index 000000000..2b3cd382c
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/local_state.cpp
@@ -0,0 +1,70 @@
+#include "service/contract/executor/manager/local_state.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+using eevm::AccountState;
+using eevm::Address;
+using eevm::Code;
+using eevm::SimpleAccount;
+
+LocalState::LocalState(ConcurrencyController* controller)
+    : controller_(controller) {}
+
+bool LocalState::Exists(const eevm::Address& addr) {
+  return accounts.find(addr) != accounts.cend();
+}
+
+void LocalState::remove(const Address& addr) { accounts.erase(addr); }
+
+AccountState LocalState::get(const Address& addr) {
+  const auto acc = accounts.find(addr);
+  if (acc != accounts.cend()) return acc->second;
+
+  return create(addr, 0, {});
+}
+
+AccountState LocalState::create(const Address& addr, const uint256_t& balance,
+                                const Code& code) {
+  Insert({SimpleAccount(addr, balance, code), LocalView(controller_, 0)});
+  return get(addr);
+}
+
+const eevm::SimpleAccount& LocalState::GetAccount(const eevm::Address& addr) {
+  const auto acc = accounts.find(addr);
+  return acc->second.first;
+}
+
+void LocalState::Set(const eevm::SimpleAccount& acc, int64_t commit_id) {
+  Insert({acc, LocalView(controller_, commit_id)});
+}
+
+void LocalState::Insert(const StateEntry& p) {
+  const auto ib = accounts.insert(std::make_pair(p.first.get_address(), p));
+
+  assert(ib.second);
+}
+
+bool LocalState::Flesh(const Address& addr, int commit_id) {
+  const auto acc = accounts.find(addr);
+  if (acc != accounts.cend()) {
+    acc->second.second.Flesh(commit_id);
+    return true;
+  }
+  return false;
+}
+
+/*
+  bool LocalState::Commit(const eevm::Address& addr) {
+    const auto acc = accounts.find(addr);
+    if (acc != accounts.cend()){
+      return acc->second.second.Commit();
+    }
+    return false;
+  }
+  */
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/local_state.h b/platform/consensus/ordering/thunderbolt/executor/manager/local_state.h
new file mode 100644
index 000000000..f98c34c07
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/local_state.h
@@ -0,0 +1,52 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "eEVM/simple/simpleaccount.h"
+#include "service/contract/executor/manager/concurrency_controller.h"
+#include "service/contract/executor/manager/evm_state.h"
+#include "service/contract/executor/manager/local_view.h"
+
+namespace resdb {
+namespace contract {
+
+class LocalState : public EVMState {
+ public:
+  using StateEntry = std::pair<eevm::SimpleAccount, LocalView>;
+
+ public:
+  LocalState(ConcurrencyController* controller);
+  virtual ~LocalState() = default;
+
+  virtual void remove(const eevm::Address& addr) override;
+
+  // Get contract by contract address.
+  eevm::AccountState get(const eevm::Address& addr) override;
+
+  bool Exists(const eevm::Address& addr);
+
+  // Flesh the local view to the controller with a commit id.
+  // Once all the contracts have fleshed their changes, they should call commit.
+  // Return false if contract not exists.
+  bool Flesh(const eevm::Address& addr, int commit_id);
+  // Commit the changes using the commit id from the flesh.
+  // bool Commit(const eevm::Address& addr);
+
+  // Create an account for the contract, which the balance is 0.
+  eevm::AccountState create(const eevm::Address& addr, const uint256_t& balance,
+                            const eevm::Code& code) override;
+
+  const eevm::SimpleAccount& GetAccount(const eevm::Address& addr);
+  void Set(const eevm::SimpleAccount& acc, int64_t commit_id);
+
+ protected:
+  void Insert(const StateEntry& p);
+
+ private:
+  std::map<eevm::Address, StateEntry> accounts;
+  ConcurrencyController* controller_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/local_view.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/local_view.cpp
new file mode 100644
index 000000000..601b55ff2
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/local_view.cpp
@@ -0,0 +1,77 @@
+#include "service/contract/executor/manager/local_view.h"
+
+#include <glog/logging.h>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
+
+LocalView::LocalView(ConcurrencyController* controller, int64_t commit_id)
+    : controller_(controller), commit_id_(commit_id) {}
+
+void LocalView::store(const uint256_t& key, const uint256_t& value) {
+  // LOG(ERROR)<<"========= store key:"<<key<<" value:"<<value;
+  auto it = local_changes_.find(key);
+  if (it == local_changes_.end()) {
+    // std::pair<uint256_t,int64_t> load_value =
+    // controller_->GetStorage()->Load(key, /*is_from_local=*/true);
+    local_changes_[key].push_back(Data(STORE, value, 0, 0));
+  } else {
+    const Data& data = local_changes_[key].back();
+    if (data.state == LOAD) {
+      local_changes_[key].push_back(Data(STORE, value, data.version + 1));
+    } else {
+      int64_t v = data.version;
+      local_changes_[key].pop_back();
+      local_changes_[key].push_back(Data(STORE, value, v));
+    }
+  }
+}
+
+uint256_t LocalView::load(const uint256_t& key) {
+  // LOG(ERROR)<<"load key:"<<key;
+  auto it = local_changes_.find(key);
+  if (it == local_changes_.end()) {
+    std::pair<uint256_t, int64_t> value =
+        controller_->GetStorage()->Load(key, /*is_from_local=*/true);
+    local_changes_[key].push_back(Data(LOAD, value.first, value.second));
+    return value.first;
+  }
+  return it->second.back().data;
+}
+
+bool LocalView::remove(const uint256_t& key) {
+  store(key, 0);
+  return true;
+
+  // local_changes_[key].push_back(Data(REMOVE));
+  auto it = local_changes_.find(key);
+  if (it == local_changes_.end()) {
+    std::pair<uint256_t, int64_t> load_value =
+        controller_->GetStorage()->Load(key, /*is_from_local=*/true);
+    local_changes_[key].push_back(
+        Data(REMOVE, 0, load_value.second, load_value.first));
+  } else {
+    const Data& data = local_changes_[key].back();
+    if (data.state == LOAD) {
+      local_changes_[key].push_back(Data(REMOVE, 0, data.version + 1));
+    } else {
+      int64_t v = data.version;
+      local_changes_[key].pop_back();
+      local_changes_[key].push_back(Data(REMOVE, 0, v));
+    }
+  }
+
+  return true;
+}
+
+void LocalView::Flesh(int64_t commit_id) {
+  commit_id_ = commit_id;
+  // LOG(ERROR)<<"commit push:"<<commit_id;
+  controller_->PushCommit(commit_id, local_changes_);
+  local_changes_.clear();
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/local_view.h b/platform/consensus/ordering/thunderbolt/executor/manager/local_view.h
new file mode 100644
index 000000000..047d487d3
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/local_view.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <map>
+
+#include "eEVM/storage.h"
+#include "service/contract/executor/manager/concurrency_controller.h"
+
+namespace resdb {
+namespace contract {
+
+class LocalView : public eevm::Storage {
+ public:
+  LocalView(ConcurrencyController* controller, int64_t commit_id);
+  virtual ~LocalView() = default;
+
+  void store(const uint256_t& key, const uint256_t& value) override;
+  uint256_t load(const uint256_t& key) override;
+  bool remove(const uint256_t& key) override;
+
+  // for 2PL, once it is done, all the commit will be pushed to
+  // the controller to judge if it can be committed.
+  // During the flesh, all the changes will be removed.
+  void Flesh(int64_t commit_id);
+  // Commit the changes. If there is a conflict, return false.
+  // Make sure all other committers have pushed their changes before calling
+  // Commit.
+  // bool Commit();
+  // Remove all the changes.
+  // void Abort();
+
+ private:
+  ConcurrencyController* controller_;
+  int64_t commit_id_;
+  std::map<uint256_t, std::vector<Data>> local_changes_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/local_view_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/local_view_test.cpp
new file mode 100644
index 000000000..017f2b6de
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/local_view_test.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/local_view.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include "service/contract/executor/manager/two_phase_controller.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+uint256_t HexToInt(const std::string& v) { return eevm::to_uint256(v); }
+
+TEST(LocalViewTest, ViewChange) {
+  DataStorage storage;
+  uint256_t address1 = HexToInt("0x123");
+
+  storage.Store(address1, 2000);
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  TwoPhaseController controller(&storage);
+
+  LocalView view(&controller, 0);
+
+  EXPECT_EQ(view.load(address1), 2000);
+  view.store(address1, 3000);
+  EXPECT_EQ(view.load(address1), 3000);
+
+  // storage still contains 2000
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+}
+
+TEST(LocalViewTest, CommitChange) {
+  DataStorage storage;
+  uint256_t address1 = HexToInt("0x123");
+
+  storage.Store(address1, 2000);
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  TwoPhaseController controller(&storage);
+
+  LocalView view(&controller, 0);
+
+  EXPECT_EQ(view.load(address1), 2000);
+  view.store(address1, 3000);
+  EXPECT_EQ(view.load(address1), 3000);
+
+  // storage still contains 2000
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  view.Flesh(0);
+  EXPECT_TRUE(controller.Commit(0));
+  // Save to real storage.
+  EXPECT_EQ(storage.Load(address1).first, 3000);
+}
+
+TEST(LocalViewTest, CommitConflict) {
+  DataStorage storage;
+  uint256_t address1 = HexToInt("0x123");
+
+  storage.Store(address1, 2000);
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  TwoPhaseController controller(&storage);
+
+  LocalView view1(&controller, 0);
+  LocalView view2(&controller, 1);
+
+  EXPECT_EQ(view1.load(address1), 2000);
+  view1.store(address1, 3000);
+  EXPECT_EQ(view1.load(address1), 3000);
+
+  // storage still contains 2000
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  EXPECT_EQ(view2.load(address1), 2000);
+  view2.store(address1, 4000);
+  EXPECT_EQ(view2.load(address1), 4000);
+
+  // storage still contains 2000
+  EXPECT_EQ(storage.Load(address1).first, 2000);
+
+  view1.Flesh(0);
+  view2.Flesh(1);
+
+  EXPECT_FALSE(controller.Commit(1));
+  EXPECT_TRUE(controller.Commit(0));
+
+  // Save to real storage.
+  EXPECT_EQ(storage.Load(address1).first, 3000);
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/mock_d_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/mock_d_storage.h
new file mode 100644
index 000000000..aa38fa511
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/mock_d_storage.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "gmock/gmock.h"
+#include "service/contract/executor/manager/d_storage.h"
+
+namespace resdb {
+namespace contract {
+
+class MockDStorage : public D_Storage {
+ public:
+  typedef std::pair<uint256_t, int64_t> LoadType;
+
+  MOCK_METHOD(int64_t, Store,
+              (const uint256_t& key, const uint256_t& value, bool), (override));
+  MOCK_METHOD(bool, Remove, (const uint256_t&, bool), (override));
+  MOCK_METHOD(bool, Exist, (const uint256_t&, bool), (const, override));
+  MOCK_METHOD(int64_t, GetVersion, (const uint256_t&, bool), (const, override));
+  MOCK_METHOD(LoadType, Load, (const uint256_t&, bool), (const, override));
+  MOCK_METHOD(void, Reset, (const uint256_t&, const uint256_t&, int64_t, bool),
+              (override));
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/mock_data_storage.h b/platform/consensus/ordering/thunderbolt/executor/manager/mock_data_storage.h
new file mode 100644
index 000000000..1876f7142
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/mock_data_storage.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include "gmock/gmock.h"
+#include "service/contract/executor/manager/data_storage.h"
+
+namespace resdb {
+namespace contract {
+
+class MockStorage : public DataStorage {
+ public:
+  typedef std::pair<uint256_t, int64_t> LoadType;
+
+  MOCK_METHOD(int64_t, Store,
+              (const uint256_t& key, const uint256_t& value, bool), (override));
+  MOCK_METHOD(bool, Remove, (const uint256_t&, bool), (override));
+  MOCK_METHOD(bool, Exist, (const uint256_t&, bool), (const, override));
+  MOCK_METHOD(int64_t, GetVersion, (const uint256_t&, bool), (const, override));
+  MOCK_METHOD(LoadType, Load, (const uint256_t&, bool), (const, override));
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.cpp
new file mode 100644
index 000000000..a60c66e27
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/ooo_committer.h"
+
+#include "eEVM/processor.h"
+#include "glog/logging.h"
+#include "service/contract/executor/manager/local_state.h"
+
+namespace resdb {
+namespace contract {
+
+OOOCommitter::OOOCommitter(DataStorage* storage, GlobalState* global_state,
+                           int worker_num)
+    : gs_(global_state), worker_num_(worker_num) {
+  controller_ = std::make_unique<OOOController>(storage);
+  executor_ = std::make_unique<ContractExecutor>();
+  is_stop_ = false;
+
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_.push_back(std::thread([&]() {
+      while (!is_stop_) {
+        auto request = request_queue_.Pop();
+        if (request == nullptr) {
+          continue;
+        }
+        LocalState local_state(controller_.get());
+        local_state.Set(gs_->GetAccount(request->contract_address),
+                        request->commit_id);
+
+        std::unique_ptr<ExecuteResp> resp = std::make_unique<ExecuteResp>();
+        auto ret = ExecContract(request->caller_address,
+                                request->contract_address, request->func_addr,
+                                request->func_params, &local_state);
+        resp->state = ret.status();
+        resp->contract_address = request->contract_address;
+        resp->commit_id = request->commit_id;
+        resp->user_id = request->user_id;
+        if (ret.ok()) {
+          resp->ret = 0;
+          resp->result = *ret;
+        } else {
+          resp->ret = -1;
+        }
+        resp_queue_.Push(std::move(resp));
+      }
+    }));
+  }
+}
+
+OOOCommitter::~OOOCommitter() {
+  is_stop_ = true;
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_[i].join();
+  }
+}
+
+std::vector<std::unique_ptr<ExecuteResp>> OOOCommitter::ExecContract(
+    std::vector<ContractExecuteInfo>& requests) {
+  int process_num = requests.size();
+  std::vector<std::unique_ptr<ExecuteResp>> resp_list;
+
+  std::set<int64_t> commits;
+  resp_list.resize(process_num);
+
+  for (auto& request : requests) {
+    request_queue_.Push(std::make_unique<ContractExecuteInfo>(request));
+  }
+
+  while (process_num) {
+    auto resp = resp_queue_.Pop();
+    if (resp == nullptr) {
+      continue;
+    }
+    int64_t resp_commit_id = resp->commit_id;
+    resp_list[resp->commit_id - 1] = std::move(resp);
+    process_num--;
+  }
+
+  return resp_list;
+}
+
+absl::StatusOr<std::string> OOOCommitter::ExecContract(
+    const Address& caller_address, const Address& contract_address,
+    const std::string& func_addr, const Params& func_param, EVMState* state) {
+  return executor_->ExecContract(caller_address, contract_address, func_addr,
+                                 func_param, state);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.h b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.h
new file mode 100644
index 000000000..ddf15fdce
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_committer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <future>
+#include <shared_mutex>
+
+#include "absl/status/statusor.h"
+#include "eEVM/opcode.h"
+#include "platform/common/queue/lock_free_queue.h"
+#include "service/contract/executor/common/utils.h"
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/contract_executor.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/executor/manager/ooo_controller.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+class OOOCommitter : public ContractCommitter {
+ public:
+  OOOCommitter(DataStorage* storage, GlobalState* global_state,
+               int worker_num = 2);
+
+  ~OOOCommitter();
+
+  std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& request) override;
+
+  absl::StatusOr<std::string> ExecContract(const Address& caller_address,
+                                           const Address& contract_address,
+                                           const std::string& func_addr,
+                                           const Params& func_param,
+                                           EVMState* state);
+
+ private:
+  std::unique_ptr<OOOController> controller_;
+  std::unique_ptr<ContractExecutor> executor_;
+  GlobalState* gs_;
+  std::vector<std::thread> workers_;
+  std::atomic<bool> is_stop_;
+
+  LockFreeQueue<ContractExecuteInfo> request_queue_;
+  LockFreeQueue<ExecuteResp> resp_queue_;
+
+  const int worker_num_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.cpp
new file mode 100644
index 000000000..b9be8e61e
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.cpp
@@ -0,0 +1,36 @@
+#include "service/contract/executor/manager/ooo_controller.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+OOOController::OOOController(DataStorage* storage)
+    : ConcurrencyController(storage) {}
+
+OOOController::~OOOController() {}
+
+void OOOController::PushCommit(int64_t commit_id,
+                               const ModifyMap& local_changes) {
+  for (const auto& it : local_changes) {
+    bool done = false;
+    for (int i = it.second.size() - 1; i >= 0 && !done; --i) {
+      const auto& op = it.second[i];
+      switch (op.state) {
+        case LOAD:
+          break;
+        case STORE:
+          storage_->Store(it.first, op.data);
+          done = true;
+          break;
+        case REMOVE:
+          storage_->Remove(it.first);
+          done = true;
+          break;
+      }
+    }
+  }
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.h b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.h
new file mode 100644
index 000000000..449fbc4c2
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/ooo_controller.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include "service/contract/executor/manager/concurrency_controller.h"
+
+namespace resdb {
+namespace contract {
+
+class OOOController : public ConcurrencyController {
+ public:
+  OOOController(DataStorage* storage);
+  ~OOOController();
+
+  virtual void PushCommit(int64_t commit_id, const ModifyMap& local_changes);
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.cpp
new file mode 100644
index 000000000..708880238
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.cpp
@@ -0,0 +1,267 @@
+#include "service/contract/executor/manager/sequential_cc_controller.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+SequentialCCController::SequentialCCController(DataStorage* storage)
+    : ConcurrencyController(storage) {
+  for (int i = 0; i < window_size_; ++i) {
+    is_redo_.push_back(false);
+  }
+
+  Clear();
+  last_commit_id_ = 0;
+}
+
+SequentialCCController::~SequentialCCController() {}
+
+void SequentialCCController::Clear() {
+  last_commit_id_ = 0;
+
+  changes_list_.resize(window_size_);
+  for (int i = 0; i < window_size_; ++i) {
+    changes_list_[i].clear();
+    is_redo_[i] = false;
+  }
+  for (int i = 0; i < 1024; ++i) {
+    commit_list_[i].clear();
+  }
+  m_list_.clear();
+}
+
+std::vector<int64_t>& SequentialCCController::GetRedo() { return redo_; }
+
+int SequentialCCController::GetHashKey(const uint256_t& address) {
+  // Get big-endian form
+  uint8_t arr[32] = {};
+  memset(arr, 0, sizeof(arr));
+  intx::be::store(arr, address);
+  uint32_t v = 0;
+  for (int i = 0; i < 32; ++i) {
+    v += arr[i];
+  }
+  return v % 128;
+}
+
+void SequentialCCController::SetCallback(CallBack call_back) {
+  call_back_ = call_back;
+}
+
+void SequentialCCController::RedoCommit(int64_t commit_id, int flag) {
+  if (is_redo_[commit_id]) {
+    return;
+  }
+  is_redo_[commit_id] = true;
+  redo_.push_back(commit_id);
+}
+
+void SequentialCCController::PushCommit(int64_t commit_id,
+                                        const ModifyMap& local_changes) {
+  if (commit_id <= last_commit_id_) {
+    // assert(!changes_list_[commit_id].empty());
+    changes_list_[commit_id] = local_changes;
+    // assert(Commit(commit_id));
+    return;
+  }
+
+  {
+    changes_list_[commit_id] = local_changes;
+    /*
+    for(const auto& it : local_changes){
+      int hash_idx = GetHashKey(it.first);
+      //LOG(ERROR)<<"address:"<<it.first<<" idx:"<<hash_idx;
+      std::unique_lock lock(mutexs_[hash_idx]);
+      //LOG(ERROR)<<"load idx:"<<hash_idx;
+      auto& commit_set = commit_list_[hash_idx][it.first];
+      commit_set.insert(commit_id);
+    }
+    */
+  }
+}
+
+bool SequentialCCController::Commit(int64_t commit_id) {
+  if (commit_id > last_commit_id_) {
+    const auto& local_changes = changes_list_[commit_id];
+    for (const auto& it : local_changes) {
+      int hash_idx = GetHashKey(it.first);
+      // LOG(ERROR)<<"address:"<<it.first<<" idx:"<<hash_idx;
+      // std::unique_lock lock(mutexs_[hash_idx]);
+      // LOG(ERROR)<<"load idx:"<<hash_idx;
+      auto& commit_set = commit_list_[hash_idx][it.first];
+      commit_set.push_back(commit_id);
+      // commit_set.insert(commit_id);
+    }
+  }
+
+  redo_.clear();
+  bool ret = CommitInternal(commit_id);
+  if (commit_id == last_commit_id_ + 1) {
+    last_commit_id_++;
+  }
+  return ret;
+}
+
+bool SequentialCCController::CommitInternal(int64_t commit_id) {
+  if (!CheckCommit(commit_id)) {
+    return false;
+  }
+  const auto& change_set = changes_list_[commit_id];
+  if (change_set.empty()) {
+    LOG(ERROR) << " no commit id record found:" << commit_id;
+    return false;
+  }
+  std::set<int64_t> new_commit_ids;
+  for (const auto& it : change_set) {
+    bool done = false;
+    const uint256_t& address = it.first;
+    int64_t new_v = 0;
+    for (int i = it.second.size() - 1; i >= 0 && !done; --i) {
+      const auto& op = it.second[i];
+      switch (op.state) {
+        case LOAD:
+          break;
+        case STORE:
+          // LOG(ERROR)<<"commit:"<<it.first<<" data:"<<op.data<<" commit
+          // id:"<<commit_id;
+          new_v = storage_->Store(it.first, op.data);
+          done = true;
+          break;
+        case REMOVE:
+          // LOG(ERROR)<<"remove:"<<it.first<<" data:";
+          storage_->Remove(it.first);
+          done = true;
+          break;
+      }
+    }
+    int64_t next_commit_id = Remove(address, commit_id, new_v);
+    // if(next_commit_id> 0){
+    if (next_commit_id > 0 && next_commit_id <= last_commit_id_) {
+      new_commit_ids.insert(next_commit_id);
+    }
+    if (done && next_commit_id > last_commit_id_) {
+      if (IsRead(address, next_commit_id)) {
+        new_commit_ids.insert(next_commit_id);
+      }
+    }
+  }
+  Remove(commit_id);
+  for (int64_t redo_commit : new_commit_ids) {
+    RedoCommit(redo_commit, 1);
+  }
+  return true;
+}
+
+bool SequentialCCController::CheckFirstCommit(const uint256_t& address,
+                                              int64_t commit_id) {
+  int idx = GetHashKey(address);
+  // std::shared_lock lock(mutexs_[idx]);
+  // LOG(ERROR)<<"load idx:"<<idx;
+  // std::shared_lock lock(mutex_);
+  if (commit_list_[idx].find(address) == commit_list_[idx].end()) {
+    LOG(ERROR) << "no address:" << commit_id << " add:" << address;
+    return false;
+  }
+  const auto& commit_set = commit_list_[idx][address];
+  // assert(*commit_set.begin()>0);
+
+  if (commit_set.front() < commit_id) {
+    // if(*commit_set.begin() < commit_id){
+    // not the first candidate
+    // LOG(ERROR)<<"still have dep. commit id:"<<commit_id<<"
+    // dep:"<<*commit_list_[address].begin();
+    return false;
+  }
+  // assert(*commit_set.begin() == commit_id);
+  return true;
+}
+
+bool SequentialCCController::IsRead(const uint256_t& address,
+                                    int64_t commit_id) {
+  const auto& change_set = changes_list_[commit_id];
+  if (change_set.empty()) {
+    LOG(ERROR) << " no commit id record found:" << commit_id;
+    // assert(!change_set.empty());
+    return false;
+  }
+
+  for (const auto& it : change_set) {
+    if (it.first != address) {
+      continue;
+    }
+    for (auto& op : it.second) {
+      if (op.state == LOAD) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool SequentialCCController::CheckCommit(int64_t commit_id) {
+  const auto& change_set = changes_list_[commit_id];
+  if (change_set.empty()) {
+    LOG(ERROR) << " no commit id record found:" << commit_id;
+    // assert(!change_set.empty());
+    return false;
+  }
+
+  for (const auto& it : change_set) {
+    const uint256_t& address = it.first;
+    if (!CheckFirstCommit(it.first, commit_id)) {
+      return false;
+    }
+
+    for (auto& op : it.second) {
+      if (op.state == LOAD) {
+        uint64_t v = storage_->GetVersion(address);
+        if (op.version != v) {
+          // LOG(ERROR)<<"check load:"<<address<<" version:"<<v<<" data
+          // v:"<<op.version<<" commit id:"<<commit_id<<"
+          // mlist:"<<m_list_[it.first];
+          RedoCommit(commit_id, 0);
+          return false;
+        }
+      }
+    }
+  }
+  return true;
+}
+
+const ConcurrencyController::ModifyMap* SequentialCCController::GetChangeList(
+    int64_t commit_id) {
+  // read lock
+  return &changes_list_[commit_id];
+}
+
+void SequentialCCController::Remove(int64_t commit_id) {
+  changes_list_[commit_id].clear();
+}
+
+int64_t SequentialCCController::Remove(const uint256_t& address,
+                                       int64_t commit_id, uint64_t v) {
+  int idx = GetHashKey(address);
+  // std::unique_lock lock(mutex_);
+  // std::unique_lock lock(mutexs_[idx]);
+  // LOG(ERROR)<<"load idx:"<<idx;
+  if (commit_list_[idx].find(address) == commit_list_[idx].end()) {
+    LOG(ERROR) << " remove address:" << address << " commit id:" << commit_id
+               << " not exist";
+  }
+  // assert(commit_list_.find(address) != commit_list_.end());
+
+  auto& it = commit_list_[idx][address];
+  // assert(*it.begin() == commit_id);
+  it.pop_front();
+  // it.erase(it.begin());
+  // LOG(ERROR)<<"update address:"<<address<<" mlist:"<<m_list_[address];
+  if (it.empty()) {
+    commit_list_[idx].erase(commit_list_[idx].find(address));
+    return -1;
+  }
+  return it.front();
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.h b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.h
new file mode 100644
index 000000000..9d0ee1ec5
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <deque>
+#include <set>
+#include <shared_mutex>
+#include <thread>
+
+#include "platform/common/queue/lock_free_queue.h"
+#include "service/contract/executor/manager/concurrency_controller.h"
+
+namespace resdb {
+namespace contract {
+
+class SequentialCCController : public ConcurrencyController {
+ public:
+  struct CallBack {
+    std::function<void(int64_t, int)> redo_callback = nullptr;
+    std::function<void(int64_t)> committed_callback = nullptr;
+  };
+
+  SequentialCCController(DataStorage* storage);
+  ~SequentialCCController();
+
+  void SetCallback(CallBack call_back);
+
+  virtual void PushCommit(int64_t commit_id, const ModifyMap& local_changes_);
+  bool Commit(int64_t commit_id);
+  std::vector<int64_t>& GetRedo();
+
+  void Clear();
+
+ private:
+  bool CommitInternal(int64_t commit_id);
+  bool CheckCommit(int64_t commit_id);
+  bool CheckFirstCommit(const uint256_t& address, int64_t commit_id);
+
+  const ModifyMap* GetChangeList(int64_t commit_id);
+  int64_t Remove(const uint256_t& address, int64_t commit_id, uint64_t v);
+  void Remove(int64_t commit_id);
+
+  std::function<void(int64_t)> GetCommitCallBack(int64_t commit_id);
+  std::function<void(int64_t, int)> GetRedoCallBack(int64_t commit_id);
+
+  void CommitDone(int64_t commit_id);
+  void RedoCommit(int64_t commit_id, int flag);
+
+  int GetHashKey(const uint256_t& address);
+
+  bool IsRead(const uint256_t& address, int64_t commit_id);
+
+ private:
+  const int window_size_ = 1000;
+  mutable std::shared_mutex mutex_, mutexs_[1024];
+
+  std::map<uint256_t, int64_t> first_commit_;
+  std::atomic<int64_t> last_commit_id_;
+
+  std::vector<ModifyMap> changes_list_;
+  std::map<uint256_t, std::deque<int64_t> > commit_list_[1024];
+  // std::map<uint256_t, std::set<int64_t> > commit_list_[1024];
+  std::map<uint256_t, uint64_t> m_list_;
+
+  std::vector<bool> is_redo_;
+  CallBack call_back_;
+
+  std::vector<int64_t> redo_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller_test.cpp
new file mode 100644
index 000000000..9224873ac
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_cc_controller_test.cpp
@@ -0,0 +1,1011 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/sequential_cc_controller.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <future>
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Test;
+
+uint256_t HexToInt(const std::string& v) { return eevm::to_uint256(v); }
+
+void GetData(const std::string& addr, const DataStorage& storage,
+             ConcurrencyController::ModifyMap& changes) {
+  changes[HexToInt(addr)].push_back(Data(LOAD,
+                                         storage.Load(HexToInt(addr)).first,
+                                         storage.Load(HexToInt(addr)).second));
+}
+
+void SetData(const std::string& addr, int value,
+             ConcurrencyController::ModifyMap& changes) {
+  changes[HexToInt(addr)].push_back(Data(STORE, value));
+}
+
+TEST(ContractDagManagerTest, PushOneCommit) {
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t) {
+    LOG(ERROR) << "committed";
+    done.set_value(true);
+  };
+
+  int64_t commit_id = 1;
+
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+  controller.SetCallback(call_back);
+
+  SequentialCCController::ModifyMap changes;
+  GetData("0x123", storage, changes);
+  SetData("0x124", 1000, changes);
+
+  controller.PushCommit(commit_id, changes);
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 0);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 1000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommit) {
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t) {
+    LOG(ERROR) << "committed";
+    committed_num++;
+    if (committed_num == 2) {
+      done.set_value(true);
+    }
+  };
+
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+  controller.SetCallback(call_back);
+
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+
+    SetData("0x123", 3000, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 1000, changes);
+    SetData("0x124", 2000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 3000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 4000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitRAWBlock) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    if (committed1_done == 1 && redo_num == 1) {
+      done.set_value(true);
+    }
+    LOG(ERROR) << "redo:" << commit_id;
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x123", storage, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 1000, changes);
+    SetData("0x124", 2000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 2000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitRAWRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 1) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+    SequentialCCController::ModifyMap changes;
+
+    GetData("0x123", storage, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x123", storage, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 1000, changes);
+    SetData("0x124", 2000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 4000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitRAWRedo2) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 1) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x122", storage, changes);
+    GetData("0x123", storage, changes);
+    SetData("0x124", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x122", storage, changes);
+    GetData("0x123", storage, changes);
+    SetData("0x124", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 1000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 2000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 5000);
+}
+
+TEST(ContractDagManagerTest, ThreeOOOCommitRAWRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+  std::set<int64_t> done_list;
+  int redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    done_list.insert(commit_id);
+    if (done_list.size() == 3 && redo_num == 1) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 3);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    SequentialCCController::ModifyMap changes;
+
+    GetData("0x121", storage, changes);
+    GetData("0x122", storage, changes);
+    GetData("0x123", storage, changes);
+    SetData("0x125", 8000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  };
+
+  controller.SetCallback(call_back);
+
+  {
+    int64_t commit_id = 3;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x121", storage, changes);
+    GetData("0x122", storage, changes);
+    GetData("0x123", storage, changes);
+    SetData("0x125", 8000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 5000, changes);
+    SetData("0x124", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x122", 5000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x125")).first, 8000);
+}
+
+TEST(ContractDagManagerTest, ThreeOOOCommitRAW2Redo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+  std::set<int64_t> done_list;
+  int redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    LOG(ERROR) << "commit:" << commit_id;
+    done_list.insert(commit_id);
+    if (done_list.size() == 3 && redo_num == 2) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    redo_num++;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    SequentialCCController::ModifyMap changes;
+
+    if (commit_id == 3) {
+      GetData("0x120", storage, changes);
+      GetData("0x122", storage, changes);
+      SetData("0x125", 8000, changes);
+    } else if (commit_id == 2) {
+      GetData("0x121", storage, changes);
+      SetData("0x123", 5000, changes);
+      SetData("0x120", 5000, changes);
+    }
+    controller.PushCommit(commit_id, changes);
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 3;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x120", storage, changes);
+    GetData("0x122", storage, changes);
+    SetData("0x125", 8000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x121", storage, changes);
+    SetData("0x123", 5000, changes);
+    SetData("0x120", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x121", 5000, changes);
+    SetData("0x122", 5000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+  EXPECT_EQ(storage.Load(HexToInt("0x125")).first, 8000);
+}
+
+TEST(ContractDagManagerTest, ThreeRAW2Redo3list) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+  storage.Store(HexToInt("0x125"), 5000);
+  storage.Store(HexToInt("0x126"), 6000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+  std::set<int64_t> done_list;
+  int redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    done_list.insert(commit_id);
+    if (done_list.size() == 3 && redo_num == 2) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    redo_num++;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    SequentialCCController::ModifyMap changes;
+
+    if (commit_id == 3) {
+      GetData("0x120", storage, changes);
+      GetData("0x122", storage, changes);
+      SetData("0x125", 8000, changes);
+    } else if (commit_id == 2) {
+      GetData("0x121", storage, changes);
+      SetData("0x123", 5000, changes);
+      SetData("0x120", 5000, changes);
+    }
+    controller.PushCommit(commit_id, changes);
+  };
+  controller.SetCallback(call_back);
+
+  {
+    int64_t commit_id = 3;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x126", storage, changes);
+    GetData("0x121", storage, changes);
+    SetData("0x125", 8000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x121", storage, changes);
+    SetData("0x123", 5000, changes);
+    SetData("0x120", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x121", 5000, changes);
+    SetData("0x122", 5000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+  EXPECT_EQ(storage.Load(HexToInt("0x125")).first, 8000);
+  EXPECT_EQ(storage.Load(HexToInt("0x126")).first, 6000);
+}
+
+TEST(ContractDagManagerTest, TwoOOORAWRedoAfterNew) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int redo_num = 0;
+  std::set<int64_t> done_list;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    done_list.insert(commit_id);
+    if (done_list.size() == 3 && redo_num == 1) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    if (commit_id == 2) {
+      {
+        int64_t new_commit_id = 3;
+
+        SequentialCCController::ModifyMap changes;
+        GetData("0x120", storage, changes);
+        SetData("0x121", 4000, changes);
+
+        controller.PushCommit(new_commit_id, changes);
+      }
+
+      SequentialCCController::ModifyMap changes;
+      GetData("0x122", storage, changes);
+      SetData("0x124", 2000, changes);
+      controller.PushCommit(commit_id, changes);
+    }
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x122", storage, changes);
+    SetData("0x124", 2000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x122", 1000, changes);
+    SetData("0x124", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 0000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 4000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 3000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 2000);
+}
+
+TEST(ContractDagManagerTest, TwoOOORAWRedoAfterNewConflict) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int redo_num = 0;
+  std::set<int64_t> done_list;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    done_list.insert(commit_id);
+    if (done_list.size() == 3 && redo_num == 2) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    redo_num++;
+    LOG(ERROR) << "redo:" << commit_id;
+
+    if (commit_id == 2) {
+      {
+        int64_t new_commit_id = 3;
+
+        SequentialCCController::ModifyMap changes;
+        GetData("0x124", storage, changes);
+        SetData("0x121", 4000, changes);
+
+        controller.PushCommit(new_commit_id, changes);
+      }
+
+      SequentialCCController::ModifyMap changes;
+      GetData("0x122", storage, changes);
+      SetData("0x124", 2000, changes);
+      controller.PushCommit(commit_id, changes);
+    } else if (commit_id == 3) {
+      SequentialCCController::ModifyMap changes;
+      GetData("0x124", storage, changes);
+      SetData("0x121", 4000, changes);
+
+      controller.PushCommit(commit_id, changes);
+    }
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x122", storage, changes);
+    SetData("0x124", 2000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x122", 1000, changes);
+    SetData("0x124", 5000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 0000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 4000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 3000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 2000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitRAWNoRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x122"), 2000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 0) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x122", storage, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 1000, changes);
+    SetData("0x124", 4000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 2000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 4000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitWAWNoRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 0) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x122", 3000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 2000, changes);
+    SetData("0x124", 1000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 0000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 3000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 2000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitWARNoRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 0) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    SetData("0x123", 5000, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x123", storage, changes);
+    SetData("0x124", 1000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 0000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 2000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 5000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+}
+
+TEST(ContractDagManagerTest, PushTwoOOOCommitRARNoRedo) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    if (commit_id == 1) {
+      committed1_done = 1;
+    }
+    if (commit_id == 2) {
+      committed2_done = 1;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num == 0) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x123", storage, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x123", storage, changes);
+    SetData("0x124", 1000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x120")).first, 0000);
+  EXPECT_EQ(storage.Load(HexToInt("0x121")).first, 1000);
+  EXPECT_EQ(storage.Load(HexToInt("0x122")).first, 2000);
+  EXPECT_EQ(storage.Load(HexToInt("0x123")).first, 3000);
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+}
+
+TEST(ContractDagManagerTest, ReadAndWriteSameAddress) {
+  DataStorage storage;
+  SequentialCCController controller(&storage);
+
+  storage.Store(HexToInt("0x120"), 0000);
+  storage.Store(HexToInt("0x121"), 1000);
+  storage.Store(HexToInt("0x122"), 2000);
+  storage.Store(HexToInt("0x123"), 3000);
+  storage.Store(HexToInt("0x124"), 4000);
+
+  std::promise<bool> done;
+  std::future<bool> done_future = done.get_future();
+
+  int committed1_done = 0, committed2_done = 0, redo_num = 0;
+  SequentialCCController::CallBack call_back;
+  call_back.committed_callback = [&](int64_t commit_id) {
+    LOG(ERROR) << "commit id ====:" << commit_id;
+    if (commit_id == 1) {
+      committed1_done++;
+    }
+    if (commit_id == 2) {
+      committed2_done++;
+    }
+    if (committed1_done == 1 && committed2_done == 1 && redo_num >= 1) {
+      done.set_value(true);
+    }
+  };
+
+  call_back.redo_callback = [&](int64_t commit_id) {
+    EXPECT_EQ(commit_id, 2);
+    redo_num = 1;
+    LOG(ERROR) << "redo:" << commit_id;
+    SequentialCCController::ModifyMap changes;
+    GetData("0x124", storage, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  };
+
+  controller.SetCallback(call_back);
+  {
+    int64_t commit_id = 2;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x124", storage, changes);
+    SetData("0x124", 6000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  {
+    int64_t commit_id = 1;
+
+    SequentialCCController::ModifyMap changes;
+    GetData("0x124", storage, changes);
+    SetData("0x124", 1000, changes);
+
+    controller.PushCommit(commit_id, changes);
+  }
+
+  done_future.get();
+  EXPECT_EQ(storage.Load(HexToInt("0x124")).first, 6000);
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.cpp
new file mode 100644
index 000000000..282dd0f9c
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/sequential_concurrency_committer.h"
+
+#include <queue>
+
+#include "common/utils/utils.h"
+#include "eEVM/processor.h"
+#include "glog/logging.h"
+#include "service/contract/executor/manager/local_state.h"
+
+namespace resdb {
+namespace contract {
+
+/*
+ExecutionContext::ExecutionContext(const ContractExecuteInfo & info ) {
+  info_ = std::make_unique<ContractExecuteInfo>(info);
+}
+
+const ContractExecuteInfo * ExecutionContext::GetContractExecuteInfo() const {
+  return info_.get();
+}
+
+void ExecutionContext::SetResult(std::unique_ptr<ExecuteResp> result) {
+  result_ = std::move(result);
+}
+
+bool ExecutionContext::IsRedo() {
+  return is_redo_;
+}
+
+void ExecutionContext::SetRedo(){
+  is_redo_ = true;
+}
+
+std::unique_ptr<ExecuteResp> ExecutionContext::FetchResult() {
+  return std::move(result_);
+}
+*/
+
+ExecutionState* SequentialConcurrencyCommitter::GetExecutionState() {
+  return &execution_state_;
+}
+
+SequentialConcurrencyCommitter::SequentialConcurrencyCommitter(
+    DataStorage* storage, GlobalState* global_state, int worker_num)
+    : storage_(storage), gs_(global_state), worker_num_(worker_num) {
+  controller_ = std::make_unique<SequentialCCController>(storage);
+  executor_ = std::make_unique<ContractExecutor>();
+  is_stop_ = false;
+
+  SequentialCCController::CallBack callback;
+  callback.redo_callback =
+      std::bind(&SequentialConcurrencyCommitter::RedoCallBack, this,
+                std::placeholders::_1, std::placeholders::_2);
+  callback.committed_callback =
+      std::bind(&SequentialConcurrencyCommitter::CommitCallBack, this,
+                std::placeholders::_1);
+
+  controller_->SetCallback(callback);
+
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_.push_back(std::thread([&]() {
+      while (!is_stop_) {
+        auto request_ptr = request_queue_.Pop();
+        if (request_ptr == nullptr) {
+          continue;
+        }
+        ExecutionContext* request = *request_ptr;
+
+        LocalState local_state(controller_.get());
+        local_state.Set(
+            gs_->GetAccount(
+                request->GetContractExecuteInfo()->contract_address),
+            request->GetContractExecuteInfo()->commit_id);
+
+        std::unique_ptr<ExecuteResp> resp = std::make_unique<ExecuteResp>();
+        auto ret = ExecContract(
+            request->GetContractExecuteInfo()->caller_address,
+            request->GetContractExecuteInfo()->contract_address,
+            request->GetContractExecuteInfo()->func_addr,
+            request->GetContractExecuteInfo()->func_params, &local_state);
+        resp->state = ret.status();
+        resp->contract_address =
+            request->GetContractExecuteInfo()->contract_address;
+        resp->commit_id = request->GetContractExecuteInfo()->commit_id;
+        resp->user_id = request->GetContractExecuteInfo()->user_id;
+        if (ret.ok()) {
+          resp->ret = 0;
+          resp->result = *ret;
+          if (request->IsRedo()) {
+            resp->retry_time = 1;
+            //    request->SetResult(std::move(resp));
+          }
+          local_state.Flesh(request->GetContractExecuteInfo()->contract_address,
+                            request->GetContractExecuteInfo()->commit_id);
+        } else {
+          resp->ret = -1;
+        }
+        // if(!request->IsRedo()){
+        resp_queue_.Push(std::move(resp));
+        //}
+      }
+    }));
+  }
+}
+
+SequentialConcurrencyCommitter::~SequentialConcurrencyCommitter() {
+  is_stop_ = true;
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_[i].join();
+  }
+}
+
+void SequentialConcurrencyCommitter::AddTask(
+    int64_t commit_id, std::unique_ptr<ExecutionContext> context) {
+  context_list_[commit_id] = std::move(context);
+}
+
+void SequentialConcurrencyCommitter::RemoveTask(int64_t commit_id) {
+  context_list_.erase(context_list_.find(commit_id));
+}
+
+ExecutionContext* SequentialConcurrencyCommitter::GetTaskContext(
+    int64_t commit_id) {
+  return context_list_[commit_id].get();
+}
+
+void SequentialConcurrencyCommitter::CommitCallBack(int64_t commit_id) {}
+
+void SequentialConcurrencyCommitter::RedoCallBack(int64_t commit_id, int flag) {
+}
+
+std::vector<std::unique_ptr<ExecuteResp>>
+SequentialConcurrencyCommitter::ExecContract(
+    std::vector<ContractExecuteInfo>& requests) {
+  execution_state_.commit_time = 0;
+  execution_state_.redo_time = 0;
+
+  int process_num = requests.size();
+  std::vector<std::unique_ptr<ExecuteResp>> resp_list;
+
+  std::set<int64_t> commits;
+  int id = 1;
+  resp_list.resize(process_num);
+  for (auto& request : requests) {
+    resp_list[id - 1] = nullptr;
+    request.commit_id = id++;
+    auto context = std::make_unique<ExecutionContext>(request);
+    AddTask(request.commit_id, std::move(context));
+    commits.insert(request.commit_id);
+  }
+
+  controller_->Clear();
+  for (auto& request : requests) {
+    auto context_ptr = GetTaskContext(request.commit_id);
+    request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+  }
+
+  auto cur_it = commits.begin();
+  std::queue<int64_t> redo_list;
+  while (process_num) {
+    auto resp = resp_queue_.Pop();
+    if (resp == nullptr) {
+      continue;
+    }
+    int64_t resp_commit_id = resp->commit_id;
+    // LOG(ERROR)<<"recv :"<<resp_commit_id<<" process num:"<<process_num;
+    resp_list[resp->commit_id - 1] = std::move(resp);
+    if (cur_it == commits.end() || resp_commit_id < *cur_it) {
+      bool ret = controller_->Commit(resp_commit_id);
+      std::vector<int64_t> list = controller_->GetRedo();
+      for (int64_t next_id : list) {
+        bool ret = controller_->Commit(next_id);
+        if (!ret) {
+          // redo_list.push(next_id);
+          auto context_ptr = GetTaskContext(next_id);
+          context_ptr->SetRedo();
+          request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+        }
+      }
+      assert(ret);
+      process_num--;
+    }
+    while (cur_it != commits.end() && resp_list[*cur_it - 1] != nullptr) {
+      int64_t commit_id = *cur_it;
+      bool ret = controller_->Commit(commit_id);
+      cur_it++;
+      if (!ret) {
+        resp_list[commit_id - 1] = nullptr;
+        if (controller_->GetRedo().size()) {
+          // redo_list.push(commit_id);
+
+          auto context_ptr = GetTaskContext(commit_id);
+          context_ptr->SetRedo();
+          request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+        }
+      } else {
+        process_num--;
+        std::vector<int64_t> list = controller_->GetRedo();
+        for (int64_t next_id : list) {
+          resp_list[next_id - 1] = nullptr;
+          // redo_list.push(next_id);
+          auto context_ptr = GetTaskContext(next_id);
+          context_ptr->SetRedo();
+          request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+        }
+      }
+    }
+  }
+
+  for (auto& request : requests) {
+    RemoveTask(request.commit_id);
+  }
+
+  storage_->Flush();
+
+  return resp_list;
+}
+
+absl::StatusOr<std::string> SequentialConcurrencyCommitter::ExecContract(
+    const Address& caller_address, const Address& contract_address,
+    const std::string& func_addr, const Params& func_param, EVMState* state) {
+  return executor_->ExecContract(caller_address, contract_address, func_addr,
+                                 func_param, state);
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.h b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.h
new file mode 100644
index 000000000..fc2d1e57e
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#pragma once
+
+#include <future>
+#include <shared_mutex>
+
+#include "absl/status/statusor.h"
+#include "eEVM/opcode.h"
+#include "platform/common/queue/lock_free_queue.h"
+#include "service/contract/executor/common/utils.h"
+#include "service/contract/executor/manager/committer_context.h"
+#include "service/contract/executor/manager/contract_committer.h"
+#include "service/contract/executor/manager/contract_executor.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/executor/manager/sequential_cc_controller.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+
+/*
+class ExecutionContext {
+public:
+  ExecutionContext(const ContractExecuteInfo & info ) ;
+  const ContractExecuteInfo * GetContractExecuteInfo() const;
+
+  void SetRedo();
+  bool IsRedo();
+
+  void SetResult(std::unique_ptr<ExecuteResp> result);
+  std::unique_ptr<ExecuteResp> FetchResult();
+
+  private:
+    bool is_redo_ = false;
+    std::unique_ptr<ExecuteResp> result_;
+    std::unique_ptr<ContractExecuteInfo> info_;
+};
+*/
+
+struct ExecutionState {
+  std::atomic<int> commit_time;
+  int redo_time = 0;
+};
+
+class SequentialConcurrencyCommitter : public ContractCommitter {
+ public:
+  SequentialConcurrencyCommitter(DataStorage* storage,
+                                 GlobalState* global_state, int worker_num = 2);
+
+  ~SequentialConcurrencyCommitter();
+
+  std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& request) override;
+
+  absl::StatusOr<std::string> ExecContract(const Address& caller_address,
+                                           const Address& contract_address,
+                                           const std::string& func_addr,
+                                           const Params& func_param,
+                                           EVMState* state);
+
+  ExecutionState* GetExecutionState();
+
+ private:
+  void AddTask(int64_t commit_id, std::unique_ptr<ExecutionContext> comtext);
+  void RemoveTask(int64_t commit_id);
+  ExecutionContext* GetTaskContext(int64_t commit_id);
+
+  void CommitCallBack(int64_t commit_id);
+  void RedoCallBack(int64_t commit_id, int flag);
+
+ private:
+  std::unique_ptr<SequentialCCController> controller_;
+  std::unique_ptr<ContractExecutor> executor_;
+  DataStorage* storage_;
+  GlobalState* gs_;
+  std::vector<std::thread> workers_;
+  std::atomic<bool> is_stop_;
+
+  LockFreeQueue<ExecutionContext*> request_queue_;
+  LockFreeQueue<ExecuteResp> resp_queue_;
+
+  std::map<int64_t, std::unique_ptr<ExecutionContext>> context_list_;
+
+  const int worker_num_;
+  ExecutionState execution_state_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer_test.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer_test.cpp
new file mode 100644
index 000000000..4f7e57f38
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/sequential_concurrency_committer_test.cpp
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/sequential_concurrency_committer.h"
+
+#include <glog/logging.h>
+#include <gtest/gtest.h>
+
+#include <fstream>
+
+#include "service/contract/executor/manager/address_manager.h"
+#include "service/contract/executor/manager/contract_deployer.h"
+#include "service/contract/executor/manager/global_state.h"
+#include "service/contract/executor/manager/mock_data_storage.h"
+#include "service/contract/proto/func_params.pb.h"
+
+namespace resdb {
+namespace contract {
+namespace {
+
+using ::testing::Invoke;
+using ::testing::Test;
+
+const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
+                             std::string(getenv("TEST_WORKSPACE")) +
+                             "/service/contract/executor/manager/";
+
+Address get_random_address() { return AddressManager().CreateRandomAddress(); }
+
+std::string U256ToString(uint256_t v) { return eevm::to_hex_string(v); }
+uint256_t HexToInt(const std::string& v) { return eevm::to_uint256(v); }
+
+class SequentialConcurrencyCommitterTest : public Test {
+ public:
+  SequentialConcurrencyCommitterTest() : owner_address_(get_random_address()) {
+    std::string contract_path = test_dir + "test_data/contract.json";
+
+    std::ifstream contract_fstream(contract_path);
+    if (!contract_fstream) {
+      throw std::runtime_error(fmt::format(
+          "Unable to open contract definition file {}", contract_path));
+    }
+
+    const auto contracts_definition = nlohmann::json::parse(contract_fstream);
+    const auto all_contracts = contracts_definition["contracts"];
+    const auto contract_code = all_contracts["ERC20.sol:ERC20Token"];
+    storage_ = std::make_unique<MockStorage>();
+    contract_json_ = contract_code;
+
+    EXPECT_CALL(*storage_, Load)
+        .WillRepeatedly(
+            Invoke([&](const uint256_t& address) { return data_[address]; }));
+
+    EXPECT_CALL(*storage_, Store)
+        .WillRepeatedly(
+            Invoke([&](const uint256_t& key, const uint256_t& value) {
+              int v = data_[key].second;
+              data_[key] = std::make_pair(value, v + 1);
+            }));
+
+    EXPECT_CALL(*storage_, GetVersion)
+        .WillRepeatedly(
+            Invoke([&](const uint256_t& key) { return data_[key].second; }));
+
+    Init();
+  }
+
+  void Init() {
+    gs_ = std::make_unique<GlobalState>(storage_.get());
+
+    committer_ = std::make_unique<SequentialConcurrencyCommitter>(
+        storage_.get(), gs_.get());
+
+    contract_address_ = AddressManager::CreateContractAddress(owner_address_);
+    deployer_ = std::make_unique<ContractDeployer>(committer_.get(), gs_.get());
+    contract_address_ =
+        deployer_->DeployContract(owner_address_, contract_json_, {1000});
+  }
+
+  std::vector<std::unique_ptr<ExecuteResp>> ExecContract(
+      std::vector<ContractExecuteInfo>& execute_info) {
+    for (int i = 0; i < execute_info.size(); ++i) {
+      std::string func_addr =
+          deployer_->GetFuncAddress(execute_info[i].contract_address,
+                                    execute_info[i].func_params.func_name());
+      if (func_addr.empty()) {
+        LOG(ERROR) << "no fouction:" << execute_info[i].func_params.func_name();
+        execute_info[i].contract_address = 0;
+        continue;
+      }
+      execute_info[i].func_addr = func_addr;
+      execute_info[i].commit_id = i + 1;
+    }
+    return committer_->ExecContract(execute_info);
+  }
+
+ protected:
+  Address owner_address_;
+  Address contract_address_;
+  nlohmann::json contract_json_;
+  std::unique_ptr<MockStorage> storage_;
+  std::unique_ptr<GlobalState> gs_;
+  std::unique_ptr<SequentialConcurrencyCommitter> committer_;
+  std::map<uint256_t, std::pair<uint256_t, int>> data_;
+  std::unique_ptr<ContractDeployer> deployer_;
+};
+
+TEST_F(SequentialConcurrencyCommitterTest, ExecContract) {
+  // owner 1000
+  std::vector<ContractExecuteInfo> info;
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(owner_address_));
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address_, "",
+                                       func_params, 0));
+  }
+
+  {
+    std::vector<std::unique_ptr<ExecuteResp>> resp = ExecContract(info);
+    EXPECT_EQ(resp.size(), 1);
+    EXPECT_EQ(resp[0]->ret, 0);
+  }
+}
+
+// get a
+// a->b
+TEST_F(SequentialConcurrencyCommitterTest, TwoTxnNoConflict) {
+  Address transfer_receiver = get_random_address();
+
+  // owner 1000
+  std::vector<ContractExecuteInfo> info;
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param(U256ToString(owner_address_));
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address_, "",
+                                       func_params, 0));
+  }
+
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address_, "",
+                                       func_params, 0));
+  }
+
+  {
+    std::vector<std::unique_ptr<ExecuteResp>> resp = ExecContract(info);
+    EXPECT_EQ(resp.size(), 2);
+    EXPECT_EQ(resp[0]->ret, 0);
+    EXPECT_EQ(HexToInt(resp[0]->result), 1000);
+    EXPECT_EQ(resp[1]->ret, 0);
+    EXPECT_EQ(HexToInt(resp[1]->result), 1);
+  }
+  // LOG(ERROR)<<"commit time:"<<committer_->GetExecutionState()->commit_time<<"
+  // redo time:"<<committer_->GetExecutionState()->redo_time;
+  EXPECT_EQ(committer_->GetExecutionState()->commit_time, 2);
+  EXPECT_EQ(committer_->GetExecutionState()->redo_time, 0);
+}
+
+// a->b
+// a->b
+TEST_F(SequentialConcurrencyCommitterTest, TwoTxnConflict) {
+  Address transfer_receiver = get_random_address();
+  Address transfer_receiver2 = get_random_address();
+
+  bool start = false;
+  std::map<uint256_t, int> load_time;
+  EXPECT_CALL(*storage_, Load)
+      .WillRepeatedly(Invoke([&](const uint256_t& address) {
+        if (start) {
+          load_time[address]++;
+        }
+        return data_[address];
+      }));
+
+  EXPECT_CALL(*storage_, Store)
+      .WillRepeatedly(Invoke([&](const uint256_t& key, const uint256_t& value) {
+        if (start) {
+          bool done = false;
+          while (!done) {
+            for (auto it : load_time) {
+              if (it.second > 1) {
+                done = true;
+                break;
+              }
+            }
+          }
+        }
+        int v = data_[key].second;
+        data_[key] = std::make_pair(value, v + 1);
+      }));
+
+  Init();
+  start = true;
+
+  // owner 1000
+  std::vector<ContractExecuteInfo> info;
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address_, "",
+                                       func_params, 0));
+  }
+  {
+    Params func_params;
+    func_params.set_func_name("transfer(address,uint256)");
+    func_params.add_param(U256ToString(transfer_receiver2));
+    func_params.add_param(U256ToString(100));
+
+    info.push_back(ContractExecuteInfo(owner_address_, contract_address_, "",
+                                       func_params, 0));
+  }
+
+  {
+    std::vector<std::unique_ptr<ExecuteResp>> resp = ExecContract(info);
+    EXPECT_EQ(resp.size(), 2);
+    EXPECT_EQ(resp[0]->ret, 0);
+    EXPECT_EQ(HexToInt(resp[0]->result), 1);
+    EXPECT_EQ(resp[1]->ret, 0);
+    EXPECT_EQ(HexToInt(resp[1]->result), 1);
+  }
+  EXPECT_EQ(committer_->GetExecutionState()->commit_time, 2);
+  EXPECT_EQ(committer_->GetExecutionState()->redo_time, 1);
+}
+
+}  // namespace
+}  // namespace contract
+}  // namespace resdb
diff --git a/platform/consensus/ordering/thunderbolt/executor/manager/streaming_committer.cpp b/platform/consensus/ordering/thunderbolt/executor/manager/streaming_committer.cpp
new file mode 100644
index 000000000..fb6c8232d
--- /dev/null
+++ b/platform/consensus/ordering/thunderbolt/executor/manager/streaming_committer.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2019-2022 ExpoLab, UC Davis
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "service/contract/executor/manager/streaming_committer.h"
+
+#include <future>
+#include <queue>
+
+#include "common/utils/utils.h"
+#include "eEVM/processor.h"
+#include "glog/logging.h"
+#include "service/contract/executor/manager/local_state.h"
+
+namespace resdb {
+namespace contract {
+namespace streaming {
+
+ExecutionContext::ExecutionContext(const ContractExecuteInfo& info) {
+  info_ = std::make_unique<ContractExecuteInfo>(info);
+}
+
+const ContractExecuteInfo* ExecutionContext::GetContractExecuteInfo() const {
+  return info_.get();
+}
+
+void ExecutionContext::SetResult(std::unique_ptr<ExecuteResp> result) {
+  result_ = std::move(result);
+}
+
+bool ExecutionContext::IsRedo() { return is_redo_; }
+
+void ExecutionContext::SetRedo() { is_redo_++; }
+
+int ExecutionContext::RedoTime() { return is_redo_; }
+
+std::unique_ptr<ExecuteResp> ExecutionContext::FetchResult() {
+  return std::move(result_);
+}
+
+ExecutionState* StreamingCommitter::GetExecutionState() {
+  return &execution_state_;
+}
+
+StreamingCommitter::StreamingCommitter(
+    DataStorage* storage, GlobalState* global_state, int window_size,
+    std::function<void(std::unique_ptr<ExecuteResp>)> call_back, int worker_num)
+    : storage_(storage),
+      gs_(global_state),
+      worker_num_(worker_num),
+      window_size_(window_size),
+      call_back_(call_back) {
+  controller_ = std::make_unique<StreamingController>(storage, window_size * 2);
+  executor_ = std::make_unique<ContractExecutor>();
+
+  resp_list_.resize(window_size_);
+  is_done_.resize(window_size_);
+  for (int i = 0; i < window_size_; ++i) {
+    is_done_[i] = false;
+    resp_list_[i] = nullptr;
+  }
+
+  first_id_ = 0;
+  last_id_ = 1;
+  is_stop_ = false;
+  id_ = 1;
+
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_.push_back(std::thread([&]() {
+      while (!is_stop_) {
+        auto request_ptr = request_queue_.Pop();
+        if (request_ptr == nullptr) {
+          continue;
+        }
+        ExecutionContext* request = *request_ptr;
+
+        LocalState local_state(controller_.get());
+        local_state.Set(
+            gs_->GetAccount(
+                request->GetContractExecuteInfo()->contract_address),
+            request->GetContractExecuteInfo()->commit_id);
+
+        std::unique_ptr<ExecuteResp> resp = std::make_unique<ExecuteResp>();
+        auto ret = ExecContract(
+            request->GetContractExecuteInfo()->caller_address,
+            request->GetContractExecuteInfo()->contract_address,
+            request->GetContractExecuteInfo()->func_addr,
+            request->GetContractExecuteInfo()->func_params, &local_state);
+        resp->state = ret.status();
+        resp->contract_address =
+            request->GetContractExecuteInfo()->contract_address;
+        resp->commit_id = request->GetContractExecuteInfo()->commit_id;
+        resp->user_id = request->GetContractExecuteInfo()->user_id;
+        // LOG(ERROR)<<"=========   get resp commit
+        // id:"<<request->GetContractExecuteInfo()->commit_id<<" param:"<<
+        // request->GetContractExecuteInfo()->func_params.DebugString();
+        if (ret.ok()) {
+          resp->ret = 0;
+          resp->result = *ret;
+          if (request->IsRedo()) {
+            resp->retry_time = request->RedoTime();
+            //    request->SetResult(std::move(resp));
+          }
+          local_state.Flesh(request->GetContractExecuteInfo()->contract_address,
+                            request->GetContractExecuteInfo()->commit_id);
+        } else {
+          LOG(ERROR) << "commit :" << resp->commit_id << " fail";
+          resp->ret = -1;
+          assert(resp->ret >= 0);
+        }
+        resp_queue_.Push(std::move(resp));
+      }
+    }));
+  }
+
+  response_ = std::thread([&]() {
+    while (!is_stop_) {
+      ResponseProcess();
+    }
+  });
+}
+
+void StreamingCommitter::SetExecuteCallBack(
+    std::function<void(std::unique_ptr<ExecuteResp>)> func) {
+  call_back_ = std::move(func);
+}
+
+StreamingCommitter::~StreamingCommitter() {
+  is_stop_ = true;
+  for (int i = 0; i < worker_num_; ++i) {
+    workers_[i].join();
+  }
+  if (response_.joinable()) {
+    response_.join();
+  }
+}
+
+void StreamingCommitter::AddTask(int64_t commit_id,
+                                 std::unique_ptr<ExecutionContext> context) {
+  context_list_[commit_id % window_size_] = std::move(context);
+}
+
+void StreamingCommitter::RemoveTask(int64_t commit_id) {
+  context_list_.erase(context_list_.find(commit_id));
+}
+
+ExecutionContext* StreamingCommitter::GetTaskContext(int64_t commit_id) {
+  return context_list_[commit_id % window_size_].get();
+}
+
+void StreamingCommitter::CallBack(uint64_t commit_id) {
+  int idx = commit_id % window_size_;
+  if (call_back_) {
+    call_back_(std::move(resp_list_[idx]));
+  } else {
+    resp_list_[idx] = nullptr;
+  }
+  is_done_[idx] = true;
+
+  // LOG(ERROR)<<"current commit done call back commit id:"<<commit_id<<"
+  // idx:"<<idx<<" first id:"<<first_id_;
+  bool need_notify = false;
+  while (first_id_ < last_id_ && is_done_[(first_id_ + 1) % window_size_]) {
+    is_done_[(first_id_ + 1) % window_size_] = false;
+    first_id_++;
+    // LOG(ERROR)<<"commit:"<<first_id_;
+    need_notify = true;
+  }
+
+  if (need_notify) {
+    std::lock_guard<std::mutex> lk(mutex_);
+    cv_.notify_all();
+  }
+  // LOG(ERROR)<<"call back done:"<<first_id_<<" last id:"<<last_id_;
+}
+
+bool StreamingCommitter::WaitNext() {
+  while (!is_stop_) {
+    int timeout_ms = 10000;
+    std::unique_lock<std::mutex> lk(mutex_);
+    cv_.wait_for(lk, std::chrono::microseconds(timeout_ms),
+                 [&] { return id_ - first_id_ < window_size_; });
+    if (id_ - first_id_ < window_size_) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool StreamingCommitter::WaitAll() {
+  while (!is_stop_) {
+    int timeout_ms = 10000;
+    std::unique_lock<std::mutex> lk(mutex_);
+    cv_.wait_for(lk, std::chrono::microseconds(timeout_ms), [&] {
+      return first_id_ > 0 && first_id_ % 500 == 0;
+      // return id_ - first_id_<window_size_;
+    });
+    if (id_ - first_id_ < window_size_) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void StreamingCommitter::ResponseProcess() {
+  auto resp = resp_queue_.Pop();
+  if (resp == nullptr) {
+    return;
+  }
+  int64_t resp_commit_id = resp->commit_id;
+  int idx = resp->commit_id % window_size_;
+  // LOG(ERROR)<<"recv :"<<resp_commit_id<<" idx:"<<idx;
+  resp_list_[idx] = std::move(resp);
+
+  if (resp_commit_id < last_id_) {
+    std::queue<int64_t> q;
+    q.push(resp_commit_id);
+    while (!q.empty()) {
+      int64_t next_id = q.front();
+      q.pop();
+
+      // LOG(ERROR)<<"!!!!!! commit retry:"<<next_id;
+      bool ret = controller_->Commit(next_id);
+      if (!ret) {
+        // LOG(ERROR)<<"retry:"<<next_id;
+        auto context_ptr = GetTaskContext(next_id);
+        // LOG(ERROR)<<"redo:"<<next_id;
+        context_ptr->SetRedo();
+        request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+      } else {
+        CallBack(next_id);
+      }
+      std::vector<int64_t> next_commit = controller_->GetRedo();
+      for (int64_t new_next : next_commit) {
+        if (next_id == new_next) {
+          continue;
+        }
+        q.push(new_next);
+        // LOG(ERROR)<<"get retry next:"<<new_next;
+      }
+    }
+  }
+  while (resp_list_[last_id_ % window_size_] != nullptr) {
+    int idx = last_id_ % window_size_;
+    int64_t current_commit_id = resp_list_[idx]->commit_id;
+    // LOG(ERROR)<<" !!!!! commit new resp:"<<current_commit_id;
+    bool ret = controller_->Commit(current_commit_id);
+    if (!ret) {
+      // LOG(ERROR)<<"redo size:"<<controller_->GetRedo().size();
+      if (controller_->GetRedo().size()) {
+        assert(controller_->GetRedo()[0] == current_commit_id);
+        // redo_list.push(commit_id);
+        // LOG(ERROR)<<"commit redo:"<<current_commit_id;
+        auto context_ptr = GetTaskContext(current_commit_id);
+        context_ptr->SetRedo();
+        request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+      }
+    } else {
+      std::vector<int64_t> list = controller_->GetRedo();
+      assert(list.empty());
+      // LOG(ERROR)<<"commit done:"<<ret<<" last_id_:"<<last_id_<<" commit
+      // id:"<<current_commit_id<<" redo list:"<<list.size();
+      for (int64_t next_id : list) {
+        resp_list_[next_id % window_size_] = nullptr;
+        // redo_list.push(next_id);
+        // LOG(ERROR)<<"redo:"<<next_id;
+        auto context_ptr = GetTaskContext(next_id);
+        context_ptr->SetRedo();
+        request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+      }
+      CallBack(current_commit_id);
+    }
+    last_id_++;
+  }
+}
+
+void StreamingCommitter::AsyncExecContract(
+    std::vector<ContractExecuteInfo>& requests) {
+  for (auto& request : requests) {
+    if (!WaitNext()) {
+      return;
+    }
+
+    int cur_idx = id_ % window_size_;
+    assert(id_ >= last_id_);
+
+    request.commit_id = id_++;
+    auto context = std::make_unique<ExecutionContext>(request);
+    auto context_ptr = context.get();
+
+    // LOG(ERROR)<<"execute:"<<request.commit_id<<" id:"<<id_<<" first
+    // id:"<<first_id_<<" last id:"<<last_id_<<" window:"<<window_size_<<"
+    // cur_idx:"<<cur_idx;
+    assert(resp_list_[cur_idx] == nullptr);
+
+    AddTask(cur_idx, std::move(context));
+    request_queue_.Push(std::make_unique<ExecutionContext*>(context_ptr));
+  }
+
+  return;
+}
+
+absl::StatusOr<std::string> StreamingCommitter::ExecContract(
... 41748 lines suppressed ...