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

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


The following commit(s) were added to refs/heads/master by this push:
     new aa54deb7 Support SmartContract with Key-Value (#171)
aa54deb7 is described below

commit aa54deb779e568a5adc84e3dad6e00a87fd6480f
Author: cjcchen <[email protected]>
AuthorDate: Fri Feb 14 15:45:09 2025 +0800

    Support SmartContract with Key-Value (#171)
    
    * add poe
    
    * add
    
    * update workflo
    
    * add log
    
    * change github name
    
    * change img files
    
    * fix workflow
    
    * fix communicator
    
    * rm log
    
    * add base fairdag
    
    * add fairdag
    
    * add hs
    
    * add hs
    
    * add ooohs
    
    * add tusk
    
    * add rcc
    
    * add rcc
    
    * add config
    
    * add cassandra
    
    * add cassandra
    
    * add prepare
    
    * add prepare
    
    * add cass 256
    
    * add ooowq
    
    * rcc done
    
    * done
    
    * rcc done
    
    * add
    
    * add fair
    
    * add cass
    
    * add poe
    
    * fix execution response
    
    * remove smallbank
    
    * fix performance script
    
    * add fairdag rl
    
    * add graph
    
    * add fair
    
    * add
    
    * done
    
    * done
    
    * done
    
    * fix build
    
    * add perf
    
    * linear poe
    
    * add
    
    * update
    
    * fix
    
    * update
    
    * update
    
    * update
    
    * update
    
    * add log
    
    * revert
    
    * revert
    
    * rm
    
    * fix
    
    * add storage
    
    * add sm in kv
    
    * add kv cmd for sm
    
    * update
    
    * add contact kv
    
    * format
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * merge master
    
    * add license
    
    * fix build
    
    * add boost
    
    * add deps
    
    ---------
    
    Co-authored-by: Ubuntu <[email protected]>
    Co-authored-by: Ubuntu <[email protected]>
    Co-authored-by: Ubuntu <[email protected]>
    Co-authored-by: Ubuntu <[email protected]>
    Co-authored-by: junchao <junchao@localhost>
---
 WORKSPACE                                          |   2 +-
 executor/common/transaction_manager.cpp            |  44 +++
 executor/common/transaction_manager.h              |  10 +
 executor/contract/executor/BUILD                   |   1 +
 executor/contract/executor/contract_executor.cpp   |  55 +++-
 executor/contract/executor/contract_executor.h     |   6 +-
 .../contract/executor/contract_executor_test.cpp   | 266 +++++++++++++++++-
 executor/contract/executor/test_data/contract.json |  18 +-
 executor/contract/executor/test_data/token.json    |  13 +
 executor/contract/manager/BUILD                    |  36 +++
 executor/contract/manager/contract_manager.cpp     |  14 +-
 executor/contract/manager/contract_manager.h       |   9 +-
 .../contract/manager/contract_manager_test.cpp     |  13 +-
 .../contract/manager/evm_state.h                   |  57 ++--
 executor/contract/manager/global_state.cpp         |  87 ++++++
 executor/contract/manager/global_state.h           |  63 +++++
 .../contract/manager/global_view.cpp               |  49 ++--
 .../contract/manager/global_view.h                 |  58 ++--
 executor/kv/BUILD                                  |   1 +
 executor/kv/kv_executor.cpp                        |  67 ++++-
 executor/kv/kv_executor.h                          |   6 +
 interface/contract/contract_client.cpp             |  13 -
 interface/contract/contract_client.h               |   1 -
 interface/kv/BUILD                                 |  14 +
 interface/{contract => kv}/contract_client.cpp     |  71 +++--
 interface/{contract => kv}/contract_client.h       |   8 +-
 platform/config/resdb_config.cpp                   |   5 +-
 platform/config/resdb_config.h                     |  15 +-
 .../consensus/execution/transaction_executor.cpp   | 309 +++++++++++++++++++--
 .../consensus/execution/transaction_executor.h     |  49 +++-
 platform/networkstrate/replica_communicator.cpp    |  91 +++++-
 platform/networkstrate/replica_communicator.h      |  15 +-
 platform/proto/resdb.proto                         |   1 +
 proto/contract/rpc.proto                           |  19 +-
 proto/kv/kv.proto                                  |   2 +
 service/contract/BUILD                             |   1 +
 service/contract/contract_service.cpp              |   4 +-
 .../tools/contract/api_tools/contract_tools.cpp    | 115 ++++----
 .../tools/contract/api_tools/create.js             |  35 +--
 .../tools/contract/api_tools/deploy.js             |  38 +--
 .../contract/api_tools/example_contract/token.json |  16 +-
 .../contract/api_tools/example_contract/token.sol  |  14 +
 .../tools/contract/api_tools/execute.js            |  39 +--
 .../service_tools/start_contract_service.sh        |   3 +
 service/tools/kv/api_tools/BUILD                   |  12 +
 .../api_tools/contract_service_tools.cpp}          | 129 +++++----
 .../tools/kv/api_tools/create.js                   |  34 +--
 .../tools/kv/api_tools/deploy.js                   |  38 +--
 .../tools/kv/api_tools/example_contract/compile.sh |  21 ++
 .../tools/kv/api_tools/example_contract/token.json |  13 +
 .../api_tools/example_contract/token.sol           |  14 +
 .../tools/kv/api_tools/execute.js                  |  39 +--
 .../tools/kv/api_tools/get_balance.js              |  35 +--
 .../tools/kv/api_tools/set_balance.js              |  36 +--
 54 files changed, 1529 insertions(+), 595 deletions(-)

diff --git a/WORKSPACE b/WORKSPACE
index 93a66164..0b898a36 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -177,7 +177,7 @@ http_archive(
 http_archive(
     name = "pybind11_bazel",
     strip_prefix = "pybind11_bazel-2.11.1.bzl.1",
-    urls = 
["https://github.com/pybind/pybind11_bazel/archive/refs/tags/v2.11.1.bzl.1.zip";],
+    urls = 
["https://github.com/pybind/pybind11_bazel/archive/refs/tags/v2.11.1.bzl.1.zip";]
 )
 
 http_archive(
diff --git a/executor/common/transaction_manager.cpp 
b/executor/common/transaction_manager.cpp
index 036f9619..74df05c9 100644
--- a/executor/common/transaction_manager.cpp
+++ b/executor/common/transaction_manager.cpp
@@ -35,6 +35,50 @@ std::unique_ptr<std::string> TransactionManager::ExecuteData(
   return std::make_unique<std::string>();
 }
 
+std::unique_ptr<google::protobuf::Message> TransactionManager::ParseData(
+    const std::string& data) {
+  return nullptr;
+}
+
+std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>
+TransactionManager::Prepare(const BatchUserRequest& request) {
+  std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>
+      batch_response = std::make_unique<
+          std::vector<std::unique_ptr<google::protobuf::Message>>>();
+  {
+    for (auto& sub_request : request.user_requests()) {
+      std::unique_ptr<google::protobuf::Message> response =
+          ParseData(sub_request.request().data());
+      batch_response->push_back(std::move(response));
+    }
+    // LOG(ERROR)<<"prepare data size:"<<batch_response.size();
+  }
+
+  return batch_response;
+}
+
+std::unique_ptr<std::string> TransactionManager::ExecuteRequest(
+    const google::protobuf::Message& request) {
+  return nullptr;
+}
+
+std::vector<std::unique_ptr<std::string>> TransactionManager::ExecuteBatchData(
+    const std::vector<std::unique_ptr<google::protobuf::Message>>& requests) {
+  // LOG(ERROR)<<"execute data:"<<requests.size();
+  std::vector<std::unique_ptr<std::string>> ret;
+  {
+    for (auto& sub_request : requests) {
+      std::unique_ptr<std::string> response = ExecuteRequest(*sub_request);
+      if (response == nullptr) {
+        response = std::make_unique<std::string>();
+      }
+      ret.push_back(std::move(response));
+    }
+  }
+  return ret;
+}
+
+
 std::unique_ptr<BatchUserResponse> TransactionManager::ExecuteBatch(
     const BatchUserRequest& request) {
   std::unique_ptr<BatchUserResponse> batch_response =
diff --git a/executor/common/transaction_manager.h 
b/executor/common/transaction_manager.h
index 16e1a58d..b1d564ac 100644
--- a/executor/common/transaction_manager.h
+++ b/executor/common/transaction_manager.h
@@ -40,6 +40,11 @@ class TransactionManager {
   virtual std::unique_ptr<BatchUserResponse> ExecuteBatch(
       const BatchUserRequest& request);
 
+  std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>
+  Prepare(const BatchUserRequest& request);
+
+  std::vector<std::unique_ptr<std::string>> ExecuteBatchData(
+      const std::vector<std::unique_ptr<google::protobuf::Message>>& requests);
   virtual std::unique_ptr<std::string> ExecuteData(const std::string& request);
 
   bool IsOutOfOrder();
@@ -48,6 +53,11 @@ class TransactionManager {
 
   virtual Storage* GetStorage() { return nullptr; };
 
+ protected:
+  virtual std::unique_ptr<google::protobuf::Message> ParseData(
+      const std::string& data);
+  virtual std::unique_ptr<std::string> ExecuteRequest(
+      const google::protobuf::Message& request);
  private:
   bool is_out_of_order_ = false;
   bool need_response_ = true;
diff --git a/executor/contract/executor/BUILD b/executor/contract/executor/BUILD
index c6e40c65..dfffaf15 100644
--- a/executor/contract/executor/BUILD
+++ b/executor/contract/executor/BUILD
@@ -40,6 +40,7 @@ cc_test(
     tags = ["manual"],
     deps = [
         ":contract_executor",
+        "//chain/storage:memory_db",
         "//common/test:test_main",
     ],
 )
diff --git a/executor/contract/executor/contract_executor.cpp 
b/executor/contract/executor/contract_executor.cpp
index ad1c6057..99f6f205 100644
--- a/executor/contract/executor/contract_executor.cpp
+++ b/executor/contract/executor/contract_executor.cpp
@@ -24,8 +24,8 @@
 namespace resdb {
 namespace contract {
 
-ContractTransactionManager::ContractTransactionManager(void)
-    : contract_manager_(std::make_unique<ContractManager>()),
+ContractTransactionManager::ContractTransactionManager(Storage * storage)
+    : contract_manager_(std::make_unique<ContractManager>(storage)),
       address_manager_(std::make_unique<AddressManager>()) {}
 
 std::unique_ptr<std::string> ContractTransactionManager::ExecuteData(
@@ -37,32 +37,42 @@ std::unique_ptr<std::string> 
ContractTransactionManager::ExecuteData(
     LOG(ERROR) << "parse data fail";
     return nullptr;
   }
-
   int ret = 0;
-  if (request.cmd() == Request::CREATE_ACCOUNT) {
+  if (request.cmd() == contract::Request::CREATE_ACCOUNT) {
     absl::StatusOr<Account> account_or = CreateAccount();
     if (account_or.ok()) {
       response.mutable_account()->Swap(&(*account_or));
+    LOG(ERROR)<<" create count:"<<response.account().DebugString();
     } else {
       ret = -1;
     }
-  } else if (request.cmd() == Request::DEPLOY) {
+  } else if (request.cmd() == contract::Request::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) {
+  } else if (request.cmd() == contract::Request::EXECUTE) {
     auto res_or = Execute(request);
     if (res_or.ok()) {
       response.set_res(*res_or);
     } else {
       ret = -1;
     }
-  } else if (request.cmd() == Request::ADD_ADDRESS) {  // New command handling
-    absl::Status status = AddAddress(request);
-    if (!status.ok()) {
+  } else if (request.cmd() == resdb::contract::Request::GETBALANCE) {
+    auto res_or = GetBalance(request);
+    if (res_or.ok()) {
+      response.set_res(*res_or);
+    } else {
+      ret = -1;
+    }
+
+  } else if (request.cmd() == resdb::contract::Request::SETBALANCE) {
+    auto res_or = SetBalance(request);
+    if (res_or.ok()) {
+      response.set_res("1");
+    } else {
       ret = -1;
     }
   }
@@ -85,12 +95,6 @@ absl::StatusOr<Account> 
ContractTransactionManager::CreateAccount() {
   return account;
 }
 
-absl::Status ContractTransactionManager::AddAddress(const Request& request) {
-  Address address = AddressManager::HexToAddress(request.external_address());
-  address_manager_->AddExternalAddress(address);
-  return absl::OkStatus();
-}
-
 absl::StatusOr<Contract> ContractTransactionManager::Deploy(
     const Request& request) {
   Address caller_address =
@@ -128,5 +132,26 @@ absl::StatusOr<std::string> 
ContractTransactionManager::Execute(
       request.func_params());
 }
 
+absl::StatusOr<std::string> ContractTransactionManager::GetBalance(
+    const Request& request) {
+
+  Address account =
+      AddressManager::HexToAddress(request.account());
+  return contract_manager_->GetBalance(account);
+}
+
+absl::StatusOr<std::string> ContractTransactionManager::SetBalance(
+    const Request& request) {
+
+  Address account =
+      AddressManager::HexToAddress(request.account());
+  Address balance =
+      AddressManager::HexToAddress(request.balance());
+  int ret = contract_manager_->SetBalance(account, balance);
+  return std::to_string(ret);
+}
+
+
+
 }  // namespace contract
 }  // namespace resdb
diff --git a/executor/contract/executor/contract_executor.h 
b/executor/contract/executor/contract_executor.h
index a5002598..489f822f 100644
--- a/executor/contract/executor/contract_executor.h
+++ b/executor/contract/executor/contract_executor.h
@@ -31,7 +31,7 @@ namespace contract {
 
 class ContractTransactionManager : public TransactionManager {
  public:
-  ContractTransactionManager(void);
+  ContractTransactionManager(Storage * storage);
   virtual ~ContractTransactionManager() = default;
 
   std::unique_ptr<std::string> ExecuteData(const std::string& request) 
override;
@@ -40,7 +40,9 @@ class ContractTransactionManager : public TransactionManager {
   absl::StatusOr<Account> CreateAccount();
   absl::StatusOr<Contract> Deploy(const Request& request);
   absl::StatusOr<std::string> Execute(const Request& request);
-  absl::Status AddAddress(const Request& request);
+
+  absl::StatusOr<std::string> GetBalance(const Request& request);
+  absl::StatusOr<std::string> SetBalance(const Request& request);
 
  private:
   std::unique_ptr<ContractManager> contract_manager_;
diff --git a/executor/contract/executor/contract_executor_test.cpp 
b/executor/contract/executor/contract_executor_test.cpp
index b8b63aec..8f7d44de 100644
--- a/executor/contract/executor/contract_executor_test.cpp
+++ b/executor/contract/executor/contract_executor_test.cpp
@@ -19,6 +19,8 @@
 
 #include "executor/contract/executor/contract_executor.h"
 
+#include "chain/storage/memory_db.h"
+
 #include <glog/logging.h>
 #include <gtest/gtest.h>
 
@@ -29,10 +31,11 @@ namespace contract {
 namespace {
 
 using ::testing::Test;
+using resdb::storage::MemoryDB;
 
 const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
                              std::string(getenv("TEST_WORKSPACE")) +
-                             "/service/contract/executor/service/";
+                             "/executor/contract/executor/";
 
 std::string ToString(const Request& request) {
   std::string ret;
@@ -42,8 +45,9 @@ std::string ToString(const Request& request) {
 
 class ContractTransactionManagerTest : public Test {
  public:
-  ContractTransactionManagerTest() {
+  ContractTransactionManagerTest() : executor_(&db_)  {
     std::string contract_path = test_dir + "test_data/contract.json";
+    contract_name_ = "token.sol:Token";
 
     std::ifstream contract_fstream(contract_path);
     if (!contract_fstream) {
@@ -109,8 +113,49 @@ class ContractTransactionManagerTest : public Test {
     }
   }
 
+  absl::StatusOr<uint256_t> GetBalance(const std::string& account_address) {
+    Request request;
+    Response response;
+
+    request.set_account(account_address);
+    request.set_cmd(Request::GETBALANCE);
+
+    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.");
+    }
+  }
+
+  absl::StatusOr<std::string> SetBalance(const std::string& account_address, 
const std::string& balance) {
+    Request request;
+    Response response;
+
+    request.set_account(account_address);
+    request.set_balance(balance);
+    request.set_cmd(Request::SETBALANCE);
+
+    std::unique_ptr<std::string> ret = 
executor_.ExecuteData(ToString(request));
+    EXPECT_TRUE(ret != nullptr);
+
+    response.ParseFromString(*ret);
+
+    if (response.ret() == 0) {
+      return response.res();
+    } else {
+      return absl::InternalError("DeployFail.");
+    }
+  }
+
  protected:
+  std::string contract_name_;
   nlohmann::json contracts_json_;
+  MemoryDB db_;
   ContractTransactionManager executor_;
 };
 
@@ -119,7 +164,7 @@ TEST_F(ContractTransactionManagerTest, ExecContract) {
   Account account = CreateAccount();
   EXPECT_FALSE(account.address().empty());
 
-  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_name = contract_name_;
   std::string contract_code = contracts_json_[contract_name]["bin"];
   nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
 
@@ -203,7 +248,7 @@ TEST_F(ContractTransactionManagerTest, DeployFail) {
   Account account = CreateAccount();
   EXPECT_FALSE(account.address().empty());
 
-  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_name = contract_name_;
   std::string contract_code = contracts_json_[contract_name]["bin"];
   nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
 
@@ -228,7 +273,7 @@ TEST_F(ContractTransactionManagerTest, NoFunc) {
   Account account = CreateAccount();
   EXPECT_FALSE(account.address().empty());
 
-  std::string contract_name = "ERC20.sol:ERC20Token";
+  std::string contract_name = contract_name_;
   std::string contract_code = contracts_json_[contract_name]["bin"];
   nlohmann::json func_hashes = contracts_json_[contract_name]["hashes"];
 
@@ -259,6 +304,217 @@ TEST_F(ContractTransactionManagerTest, NoFunc) {
   }
 }
 
+TEST_F(ContractTransactionManagerTest, GetFromKV) {
+  // create an account.
+  Account account = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+
+  std::string contract_name = contract_name_;
+  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);
+
+    {
+      auto result = GetBalance(account.address());
+    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);
+
+    {
+      auto result = GetBalance(transfer_receiver.address());
+      EXPECT_EQ(*result, 400);
+    }
+  }
+
+  {
+
+    {
+      auto result = SetBalance(account.address(), "1000");
+      EXPECT_EQ(*result, "1");
+    }
+    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, 1000);
+
+    {
+      auto result = GetBalance(account.address());
+      EXPECT_EQ(*result, 1000);
+    }
+  }
+}
+
+TEST_F(ContractTransactionManagerTest, GetFromKV2) {
+  // create an account.
+  Account account = CreateAccount();
+  EXPECT_FALSE(account.address().empty());
+
+  std::string contract_name = contract_name_;
+  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("0x1be8e78d765a2e63339fc99a66320db73158a35a");
+
+    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("0x1be8e78d765a2e63339fc99a66320db73158a35a");
+    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);
+
+    {
+      auto result = GetBalance(account.address());
+    EXPECT_EQ(*result, 600);
+    }
+  }
+
+  // receiver 400
+  {
+    Params func_params;
+    func_params.set_func_name("balanceOf(address)");
+    func_params.add_param("0x1be8e78d765a2e63339fc99a66320db73158a35a");
+
+    auto result =
+        Execute(account.address(), contract.contract_address(), func_params);
+    EXPECT_EQ(*result, 400);
+
+    {
+      auto result = GetBalance("0x1be8e78d765a2e63339fc99a66320db73158a35a");
+      EXPECT_EQ(*result, 400);
+    }
+  }
+
+}
+
+
+
 }  // namespace
 }  // namespace contract
 }  // namespace resdb
diff --git a/executor/contract/executor/test_data/contract.json 
b/executor/contract/executor/test_data/contract.json
index e9c0d972..eaeaa36f 100644
--- a/executor/contract/executor/test_data/contract.json
+++ b/executor/contract/executor/test_data/contract.json
@@ -1,19 +1,13 @@
 {
-  "contracts":
-  {
-    "ERC20.sol:ERC20Token":
-    {
-      "bin": 
"608060405234801561001057600080fd5b506040516104423803806104428339818101604052602081101561003357600080fd5b50516000818155338152600160205260409020556103ec806100566000396000f3fe608060405234801561001057600080fd5b506004361061007e577c01000000000000000000000000000000000000000000000000000000006000350463095ea7b3811461008357806318160ddd146100c357806323b872dd146100dd57806370a0823114610113578063a9059cbb14610139578063dd62ed3e14610165575b600080fd5b6100af6004803603604081101561009957600080fd
 [...]
-      "hashes":
-      {
-        "allowance(address,address)": "dd62ed3e",
-        "approve(address,uint256)": "095ea7b3",
+  "contracts": {
+    "token.sol:Token": {
+      "bin": 
"6080604052348015600f57600080fd5b506040516103f83803806103f8833981016040819052602c916040565b336000908152602081905260409020556058565b600060208284031215605157600080fd5b5051919050565b610391806100676000396000f3fe608060405234801561001057600080fd5b506004361061005d577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610062578063a5f2a1521461009e578063a9059cbb146100c1575b600080fd5b61008b610070366004610284565b600160a060020a03166000908152602081905260409020
 [...]
+      "hashes": {
         "balanceOf(address)": "70a08231",
-        "totalSupply()": "18160ddd",
         "transfer(address,uint256)": "a9059cbb",
-        "transferFrom(address,address,uint256)": "23b872dd"
+        "transferTo(address,address,uint256)": "a5f2a152"
       }
     }
   },
-  "version": "0.5.16+commit.9c3226ce.Linux.g++"
+  "version": "0.8.28+commit.7893614a.Linux.g++"
 }
diff --git a/executor/contract/executor/test_data/token.json 
b/executor/contract/executor/test_data/token.json
new file mode 100644
index 00000000..eaeaa36f
--- /dev/null
+++ b/executor/contract/executor/test_data/token.json
@@ -0,0 +1,13 @@
+{
+  "contracts": {
+    "token.sol:Token": {
+      "bin": 
"6080604052348015600f57600080fd5b506040516103f83803806103f8833981016040819052602c916040565b336000908152602081905260409020556058565b600060208284031215605157600080fd5b5051919050565b610391806100676000396000f3fe608060405234801561001057600080fd5b506004361061005d577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610062578063a5f2a1521461009e578063a9059cbb146100c1575b600080fd5b61008b610070366004610284565b600160a060020a03166000908152602081905260409020
 [...]
+      "hashes": {
+        "balanceOf(address)": "70a08231",
+        "transfer(address,uint256)": "a9059cbb",
+        "transferTo(address,address,uint256)": "a5f2a152"
+      }
+    }
+  },
+  "version": "0.8.28+commit.7893614a.Linux.g++"
+}
diff --git a/executor/contract/manager/BUILD b/executor/contract/manager/BUILD
index f1d26925..ee570c37 100644
--- a/executor/contract/manager/BUILD
+++ b/executor/contract/manager/BUILD
@@ -33,6 +33,7 @@ cc_library(
     deps = [
         ":address_manager",
         ":utils",
+        ":global_state",
         "//common:comm",
         "//proto/contract:func_params_cc_proto",
     ],
@@ -47,6 +48,7 @@ cc_test(
     tags = ["manual"],
     deps = [
         ":contract_manager",
+        "//chain/storage:memory_db",
         "//common/test:test_main",
     ],
 )
@@ -69,3 +71,37 @@ cc_test(
         "//common/test:test_main",
     ],
 )
+
+cc_library(
+    name = "global_view",
+    srcs = ["global_view.cpp"],
+    hdrs = ["global_view.h"],
+    deps = [
+        ":utils",
+        "//chain/storage:storage",
+        "//common:comm",
+    ],
+)
+
+
+cc_library(
+    name = "evm_state",
+    hdrs = ["evm_state.h"],
+    deps = [
+        ":utils",
+        "//common:comm",
+    ],
+)
+
+
+cc_library(
+    name = "global_state",
+    srcs = ["global_state.cpp"],
+    hdrs = ["global_state.h"],
+    deps = [
+        ":evm_state",
+        ":global_view",
+        "//common:comm",
+    ],
+)
+
diff --git a/executor/contract/manager/contract_manager.cpp 
b/executor/contract/manager/contract_manager.cpp
index 426a0b8a..862fc7e5 100644
--- a/executor/contract/manager/contract_manager.cpp
+++ b/executor/contract/manager/contract_manager.cpp
@@ -36,8 +36,8 @@ void AppendArgToInput(std::vector<uint8_t>& code, const 
std::string& arg) {
   AppendArgToInput(code, eevm::to_uint256(arg));
 }
 
-ContractManager::ContractManager() {
-  gs_ = std::make_unique<eevm::SimpleGlobalState>();
+ContractManager::ContractManager(Storage* storage) {
+  gs_ = std::make_unique<GlobalState>(storage);
 }
 
 std::string ContractManager::GetFuncAddress(const Address& contract_address,
@@ -84,7 +84,7 @@ Address ContractManager::DeployContract(const Address& 
owner_address,
 
 absl::StatusOr<eevm::AccountState> ContractManager::GetContract(
     const Address& address) {
-  if (!gs_->exists(address)) {
+  if (!gs_->Exists(address)) {
     return absl::InvalidArgumentError("Contract not exist.");
   }
 
@@ -144,5 +144,13 @@ absl::StatusOr<std::vector<uint8_t>> 
ContractManager::Execute(
   }
 }
 
+std::string ContractManager::GetBalance(const Address& account) {
+  return gs_->GetBalance(account);
+}
+
+int ContractManager::SetBalance(const Address& account, const uint256_t& 
balance) {
+  return gs_->SetBalance(account, balance);
+}
+
 }  // namespace contract
 }  // namespace resdb
diff --git a/executor/contract/manager/contract_manager.h 
b/executor/contract/manager/contract_manager.h
index 7e250aa6..d5347fae 100644
--- a/executor/contract/manager/contract_manager.h
+++ b/executor/contract/manager/contract_manager.h
@@ -22,7 +22,9 @@
 #include "absl/status/statusor.h"
 #include "eEVM/opcode.h"
 #include "eEVM/simple/simpleglobalstate.h"
+#include "chain/storage/storage.h"
 #include "executor/contract/manager/utils.h"
+#include "executor/contract/manager/global_state.h"
 #include "proto/contract/func_params.pb.h"
 
 namespace resdb {
@@ -30,7 +32,7 @@ namespace contract {
 
 class ContractManager {
  public:
-  ContractManager();
+  ContractManager(Storage* storage);
 
  public:
   Address DeployContract(const Address& owner_address,
@@ -42,6 +44,9 @@ class ContractManager {
                                            const Address& contract_address,
                                            const Params& func_param);
 
+  std::string GetBalance(const Address& account);
+  int SetBalance(const Address& account, const uint256_t& balance);
+
  private:
   std::string GetFuncAddress(const Address& contract_address,
                              const std::string& func_name);
@@ -52,7 +57,7 @@ class ContractManager {
       const std::vector<uint8_t>& func_para);
 
  private:
-  std::unique_ptr<eevm::SimpleGlobalState> gs_;
+  std::unique_ptr<GlobalState> gs_;
   std::map<Address, std::map<std::string, std::string>> func_address_;
 };
 
diff --git a/executor/contract/manager/contract_manager_test.cpp 
b/executor/contract/manager/contract_manager_test.cpp
index 32540bd4..db36d188 100644
--- a/executor/contract/manager/contract_manager_test.cpp
+++ b/executor/contract/manager/contract_manager_test.cpp
@@ -25,12 +25,14 @@
 #include <fstream>
 
 #include "executor/contract/manager/address_manager.h"
+#include "chain/storage/memory_db.h"
 
 namespace resdb {
 namespace contract {
 namespace {
 
 using ::testing::Test;
+using resdb::storage::MemoryDB;
 
 const std::string test_dir = std::string(getenv("TEST_SRCDIR")) + "/" +
                              std::string(getenv("TEST_WORKSPACE")) +
@@ -61,16 +63,17 @@ class ContractManagerTest : public Test {
  protected:
   Address owner_address_;
   nlohmann::json contract_json_;
+  MemoryDB db_;
 };
 
 TEST_F(ContractManagerTest, NoContract) {
-  ContractManager manager;
+  ContractManager manager(&db_);
   auto account = manager.GetContract(1234);
   EXPECT_FALSE(account.ok());
 }
 
 TEST_F(ContractManagerTest, DeployContract) {
-  ContractManager manager;
+  ContractManager manager(&db_);
 
   DeployInfo deploy_info;
   deploy_info.set_contract_bin(contract_json_["bin"]);
@@ -90,7 +93,7 @@ TEST_F(ContractManagerTest, DeployContract) {
 }
 
 TEST_F(ContractManagerTest, InitContract) {
-  ContractManager manager;
+  ContractManager manager(&db_);
 
   DeployInfo deploy_info;
   deploy_info.set_contract_bin(contract_json_["bin"]);
@@ -116,7 +119,7 @@ TEST_F(ContractManagerTest, InitContract) {
 }
 
 TEST_F(ContractManagerTest, ExecContract) {
-  ContractManager manager;
+  ContractManager manager(&db_);
 
   DeployInfo deploy_info;
   deploy_info.set_contract_bin(contract_json_["bin"]);
@@ -217,7 +220,7 @@ TEST_F(ContractManagerTest, ExecContract) {
 }
 
 TEST_F(ContractManagerTest, NoFunc) {
-  ContractManager manager;
+  ContractManager manager(&db_);
 
   DeployInfo deploy_info;
   deploy_info.set_contract_bin(contract_json_["bin"]);
diff --git a/proto/contract/rpc.proto b/executor/contract/manager/evm_state.h
similarity index 53%
copy from proto/contract/rpc.proto
copy to executor/contract/manager/evm_state.h
index 8df1dd40..26fe199e 100644
--- a/proto/contract/rpc.proto
+++ b/executor/contract/manager/evm_state.h
@@ -17,36 +17,27 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
-}
+
+#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/executor/contract/manager/global_state.cpp 
b/executor/contract/manager/global_state.cpp
new file mode 100644
index 00000000..77ff82d3
--- /dev/null
+++ b/executor/contract/manager/global_state.cpp
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#include "executor/contract/manager/global_state.h"
+
+#include <glog/logging.h>
+
+namespace resdb {
+namespace contract {
+
+using eevm::AccountState;
+using eevm::Address;
+using eevm::Code;
+using eevm::SimpleAccount;
+
+
+uint256_t AccountToAddress(const eevm::Address& account) {
+    std::vector<uint8_t> code;
+    code.resize(64);
+    std::fill(code.begin(), code.end(), 0);
+    eevm::to_big_endian(account, code.data());
+
+    uint8_t h[32];
+    eevm::keccak_256(code.data(), static_cast<unsigned int>(64), h);
+    return eevm::from_big_endian(h, sizeof(h));
+}
+
+GlobalState::GlobalState(resdb::Storage* 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);
+}
+
+std::string GlobalState::GetBalance(const eevm::Address& account) {
+  return storage_->GetValue(eevm::to_hex_string(AccountToAddress(account)));
+}
+
+int GlobalState::SetBalance(const eevm::Address& account, const uint256_t& 
balance) {
+  return storage_->SetValue(eevm::to_hex_string(AccountToAddress(account)), 
eevm::to_hex_string(balance));
+}
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/executor/contract/manager/global_state.h 
b/executor/contract/manager/global_state.h
new file mode 100644
index 00000000..0320e35e
--- /dev/null
+++ b/executor/contract/manager/global_state.h
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#pragma once
+
+#include "eEVM/simple/simpleaccount.h"
+#include "executor/contract/manager/evm_state.h"
+#include "executor/contract/manager/global_view.h"
+
+namespace resdb {
+namespace contract {
+
+class GlobalState : public EVMState {
+ public:
+  using StateEntry = std::pair<eevm::SimpleAccount, GlobalView>;
+
+ public:
+  GlobalState(resdb::Storage* 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);
+
+  std::string GetBalance(const eevm::Address& account);
+  int SetBalance(const eevm::Address& account, const uint256_t& balance);
+
+ protected:
+  void Insert(const StateEntry& p);
+
+ private:
+  std::map<eevm::Address, StateEntry> accounts;
+  resdb::Storage* storage_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/proto/contract/rpc.proto 
b/executor/contract/manager/global_view.cpp
similarity index 53%
copy from proto/contract/rpc.proto
copy to executor/contract/manager/global_view.cpp
index 8df1dd40..0fbbbef2 100644
--- a/proto/contract/rpc.proto
+++ b/executor/contract/manager/global_view.cpp
@@ -17,36 +17,27 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
 
+#include "executor/contract/manager/global_view.h"
+
+#include <glog/logging.h>
+
+#include "eEVM/util.h"
+
+namespace resdb {
+namespace contract {
 
+GlobalView::GlobalView(resdb::Storage* storage) : storage_(storage) {}
 
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+void GlobalView::store(const uint256_t& key, const uint256_t& value) {
+  storage_->SetValue(eevm::to_hex_string(key), eevm::to_hex_string(value));
 }
+
+uint256_t GlobalView::load(const uint256_t& key) {
+  return eevm::to_uint256(storage_->GetValue(eevm::to_hex_string(key)));
+}
+
+bool GlobalView::remove(const uint256_t& key) { return true; }
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/proto/contract/rpc.proto b/executor/contract/manager/global_view.h
similarity index 52%
copy from proto/contract/rpc.proto
copy to executor/contract/manager/global_view.h
index 8df1dd40..6fdfc583 100644
--- a/proto/contract/rpc.proto
+++ b/executor/contract/manager/global_view.h
@@ -17,36 +17,28 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
-}
+#pragma once
+
+#include <map>
+
+#include "eEVM/storage.h"
+#include "chain/storage/storage.h"
+
+namespace resdb {
+namespace contract {
+
+class GlobalView : public eevm::Storage {
+ public:
+  GlobalView(resdb::Storage* 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:
+  resdb::Storage* storage_;
+};
+
+}  // namespace contract
+}  // namespace resdb
diff --git a/executor/kv/BUILD b/executor/kv/BUILD
index 09f75c24..d8a47bcf 100644
--- a/executor/kv/BUILD
+++ b/executor/kv/BUILD
@@ -30,6 +30,7 @@ cc_library(
         "//executor/common:transaction_manager",
         "//platform/config:resdb_config_utils",
         "//proto/kv:kv_cc_proto",
+        "//executor/contract/executor:contract_executor",
     ],
 )
 
diff --git a/executor/kv/kv_executor.cpp b/executor/kv/kv_executor.cpp
index 742253b0..cf294174 100644
--- a/executor/kv/kv_executor.cpp
+++ b/executor/kv/kv_executor.cpp
@@ -18,13 +18,72 @@
  */
 
 #include "executor/kv/kv_executor.h"
+#include "executor/contract/executor/contract_executor.h"
 
 #include <glog/logging.h>
 
 namespace resdb {
 
 KVExecutor::KVExecutor(std::unique_ptr<Storage> storage)
-    : storage_(std::move(storage)) {}
+    : storage_(std::move(storage)) {
+    contract_manager_ = 
std::make_unique<resdb::contract::ContractTransactionManager>(storage_.get());
+}
+
+std::unique_ptr<google::protobuf::Message> KVExecutor::ParseData(
+    const std::string& request) {
+  std::unique_ptr<KVRequest> kv_request = std::make_unique<KVRequest>();
+  if (!kv_request->ParseFromString(request)) {
+    LOG(ERROR) << "parse data fail";
+    return nullptr;
+  }
+  return kv_request;
+}
+
+std::unique_ptr<std::string> KVExecutor::ExecuteRequest(
+    const google::protobuf::Message& request) {
+  KVResponse kv_response;
+  const KVRequest& kv_request = dynamic_cast<const KVRequest&>(request);
+  // LOG(ERROR)<<"execute request:";
+
+  if (kv_request.cmd() == KVRequest::SET) {
+    Set(kv_request.key(), kv_request.value());
+  } else if (kv_request.cmd() == KVRequest::GET) {
+    kv_response.set_value(Get(kv_request.key()));
+  } else if (kv_request.cmd() == KVRequest::GETALLVALUES) {
+    kv_response.set_value(GetAllValues());
+  } else if (kv_request.cmd() == KVRequest::GETRANGE) {
+    kv_response.set_value(GetRange(kv_request.key(), kv_request.value()));
+  } else if (kv_request.cmd() == KVRequest::SET_WITH_VERSION) {
+    SetWithVersion(kv_request.key(), kv_request.value(), kv_request.version());
+  } else if (kv_request.cmd() == KVRequest::GET_WITH_VERSION) {
+    GetWithVersion(kv_request.key(), kv_request.version(),
+                   kv_response.mutable_value_info());
+  } else if (kv_request.cmd() == KVRequest::GET_ALL_ITEMS) {
+    GetAllItems(kv_response.mutable_items());
+  } else if (kv_request.cmd() == KVRequest::GET_KEY_RANGE) {
+    GetKeyRange(kv_request.min_key(), kv_request.max_key(),
+                kv_response.mutable_items());
+  } else if (kv_request.cmd() == KVRequest::GET_HISTORY) {
+    GetHistory(kv_request.key(), kv_request.min_version(),
+               kv_request.max_version(), kv_response.mutable_items());
+  } else if (kv_request.cmd() == KVRequest::GET_TOP) {
+    GetTopHistory(kv_request.key(), kv_request.top_number(),
+                  kv_response.mutable_items());
+  }
+  else if(!kv_request.smart_contract_request().empty()){
+    std::unique_ptr<std::string> resp = 
contract_manager_->ExecuteData(kv_request.smart_contract_request());
+    if(resp != nullptr){
+      kv_response.set_smart_contract_response(*resp);
+    }
+  }
+
+  std::unique_ptr<std::string> resp_str = std::make_unique<std::string>();
+  if (!kv_response.SerializeToString(resp_str.get())) {
+    return nullptr;
+  }
+
+  return resp_str;
+}
 
 std::unique_ptr<std::string> KVExecutor::ExecuteData(
     const std::string& request) {
@@ -61,6 +120,12 @@ std::unique_ptr<std::string> KVExecutor::ExecuteData(
     GetTopHistory(kv_request.key(), kv_request.top_number(),
                   kv_response.mutable_items());
   }
+  else if(!kv_request.smart_contract_request().empty()){
+    std::unique_ptr<std::string> resp = 
contract_manager_->ExecuteData(kv_request.smart_contract_request());
+    if(resp != nullptr){
+      kv_response.set_smart_contract_response(*resp);
+    }
+  }
 
   std::unique_ptr<std::string> resp_str = std::make_unique<std::string>();
   if (!kv_response.SerializeToString(resp_str.get())) {
diff --git a/executor/kv/kv_executor.h b/executor/kv/kv_executor.h
index 0fda88ae..fef12597 100644
--- a/executor/kv/kv_executor.h
+++ b/executor/kv/kv_executor.h
@@ -36,6 +36,10 @@ class KVExecutor : public TransactionManager {
 
   std::unique_ptr<std::string> ExecuteData(const std::string& request) 
override;
 
+  std::unique_ptr<google::protobuf::Message> ParseData(
+      const std::string& request) override;
+  std::unique_ptr<std::string> ExecuteRequest(
+      const google::protobuf::Message& kv_request) override;
  protected:
   virtual void Set(const std::string& key, const std::string& value);
   std::string Get(const std::string& key);
@@ -54,6 +58,8 @@ class KVExecutor : public TransactionManager {
 
  private:
   std::unique_ptr<Storage> storage_;
+
+  std::unique_ptr<TransactionManager> contract_manager_;
 };
 
 }  // namespace resdb
diff --git a/interface/contract/contract_client.cpp 
b/interface/contract/contract_client.cpp
index 77dec83f..2d8b2e98 100644
--- a/interface/contract/contract_client.cpp
+++ b/interface/contract/contract_client.cpp
@@ -43,19 +43,6 @@ absl::StatusOr<Account> ContractClient::CreateAccount() {
   return response.account();
 }
 
-absl::Status ContractClient::AddExternalAddress(
-    const std::string& external_address) {
-  Request request;
-  Response response;
-  request.set_cmd(Request::ADD_ADDRESS);
-  request.set_external_address(external_address);
-  int ret = SendRequest(request, &response);
-  if (ret != 0 || response.ret() != 0) {
-    return absl::InternalError("Add address failed.");
-  }
-  return absl::OkStatus();
-}
-
 absl::StatusOr<Contract> ContractClient::DeployContract(
     const std::string& caller_address, const std::string& contract_name,
     const std::string& contract_path,
diff --git a/interface/contract/contract_client.h 
b/interface/contract/contract_client.h
index 944e71e6..7b0c5aed 100644
--- a/interface/contract/contract_client.h
+++ b/interface/contract/contract_client.h
@@ -32,7 +32,6 @@ class ContractClient : public TransactionConstructor {
   ContractClient(const ResDBConfig& config);
 
   absl::StatusOr<Account> CreateAccount();
-  absl::Status AddExternalAddress(const std::string& external_address);
   absl::StatusOr<Contract> DeployContract(
       const std::string& caller_address, const std::string& contract_name,
       const std::string& contract_path,
diff --git a/interface/kv/BUILD b/interface/kv/BUILD
index e90fb9ef..aad894e0 100644
--- a/interface/kv/BUILD
+++ b/interface/kv/BUILD
@@ -27,3 +27,17 @@ cc_library(
         "//proto/kv:kv_cc_proto",
     ],
 )
+
+cc_library(
+    name = "contract_client",
+    srcs = ["contract_client.cpp"],
+    hdrs = ["contract_client.h"],
+    deps = [
+        "//common:json",
+        "//interface/rdbc:transaction_constructor",
+        "//proto/contract:account_cc_proto",
+        "//proto/contract:contract_cc_proto",
+        "//proto/contract:rpc_cc_proto",
+        "//proto/kv:kv_cc_proto",
+    ],
+)
diff --git a/interface/contract/contract_client.cpp 
b/interface/kv/contract_client.cpp
similarity index 73%
copy from interface/contract/contract_client.cpp
copy to interface/kv/contract_client.cpp
index 77dec83f..26259eb9 100644
--- a/interface/contract/contract_client.cpp
+++ b/interface/kv/contract_client.cpp
@@ -17,14 +17,14 @@
  * under the License.
  */
 
-#include "interface/contract/contract_client.h"
+#include "interface/kv/contract_client.h"
 
 #include <glog/logging.h>
 
 #include <fstream>
 #include <nlohmann/json.hpp>
 
-#include "proto/contract/rpc.pb.h"
+#include "proto/kv/kv.pb.h"
 
 namespace resdb {
 namespace contract {
@@ -36,26 +36,13 @@ absl::StatusOr<Account> ContractClient::CreateAccount() {
   Request request;
   Response response;
   request.set_cmd(Request::CREATE_ACCOUNT);
-  int ret = SendRequest(request, &response);
+  int ret = SendRequestInternal(request, &response);
   if (ret != 0 || response.ret() != 0) {
     return absl::InternalError("Account not exist.");
   }
   return response.account();
 }
 
-absl::Status ContractClient::AddExternalAddress(
-    const std::string& external_address) {
-  Request request;
-  Response response;
-  request.set_cmd(Request::ADD_ADDRESS);
-  request.set_external_address(external_address);
-  int ret = SendRequest(request, &response);
-  if (ret != 0 || response.ret() != 0) {
-    return absl::InternalError("Add address failed.");
-  }
-  return absl::OkStatus();
-}
-
 absl::StatusOr<Contract> ContractClient::DeployContract(
     const std::string& caller_address, const std::string& contract_name,
     const std::string& contract_path,
@@ -101,7 +88,7 @@ absl::StatusOr<Contract> ContractClient::DeployContract(
 
   request.set_cmd(Request::DEPLOY);
   LOG(ERROR) << "send request:" << request.DebugString();
-  int ret = SendRequest(request, &response);
+  int ret = SendRequestInternal(request, &response);
   if (ret != 0 || response.ret() != 0) {
     return absl::InternalError("Deploy contract fail.");
   }
@@ -122,13 +109,61 @@ absl::StatusOr<std::string> 
ContractClient::ExecuteContract(
   }
 
   request.set_cmd(Request::EXECUTE);
+
   LOG(ERROR) << "send request:" << request.DebugString();
-  int ret = SendRequest(request, &response);
+  int ret = SendRequestInternal(request, &response);
+  if (ret != 0 || response.ret() != 0) {
+    return absl::InternalError("Deploy contract fail.");
+  }
+  return response.res();
+}
+  
+
+absl::StatusOr<std::string> ContractClient::GetBalance(const std::string& 
address) {
+  Request request;
+  Response response;
+  request.set_account(address);
+
+  request.set_cmd(Request::GETBALANCE);
+
+  int ret = SendRequestInternal(request, &response);
   if (ret != 0 || response.ret() != 0) {
     return absl::InternalError("Deploy contract fail.");
   }
   return response.res();
 }
 
+absl::StatusOr<std::string> ContractClient::SetBalance(const std::string& 
address, const std::string& balance) {
+  Request request;
+  Response response;
+  request.set_account(address);
+  request.set_balance(balance);
+
+  request.set_cmd(Request::SETBALANCE);
+
+  int ret = SendRequestInternal(request, &response);
+  if (ret != 0 || response.ret() != 0) {
+    return absl::InternalError("Deploy contract fail.");
+  }
+  return response.res();
+}
+
+int ContractClient::SendRequestInternal(const Request& request, Response * 
response) {
+  KVRequest kv_request;
+  request.SerializeToString(kv_request.mutable_smart_contract_request());
+  KVResponse kv_response;
+
+  int ret = SendRequest(kv_request, &kv_response);
+  if (ret != 0) {
+    return ret;
+  }
+  printf("get response from sm\n");
+  
+  response->ParseFromString(kv_response.smart_contract_response());
+  return 0;
+}
+
+
+
 }  // namespace contract
 }  // namespace resdb
diff --git a/interface/contract/contract_client.h 
b/interface/kv/contract_client.h
similarity index 83%
copy from interface/contract/contract_client.h
copy to interface/kv/contract_client.h
index 944e71e6..7df166ef 100644
--- a/interface/contract/contract_client.h
+++ b/interface/kv/contract_client.h
@@ -22,6 +22,7 @@
 #include "interface/rdbc/transaction_constructor.h"
 #include "proto/contract/account.pb.h"
 #include "proto/contract/contract.pb.h"
+#include "proto/contract/rpc.pb.h"
 
 namespace resdb {
 namespace contract {
@@ -32,7 +33,6 @@ class ContractClient : public TransactionConstructor {
   ContractClient(const ResDBConfig& config);
 
   absl::StatusOr<Account> CreateAccount();
-  absl::Status AddExternalAddress(const std::string& external_address);
   absl::StatusOr<Contract> DeployContract(
       const std::string& caller_address, const std::string& contract_name,
       const std::string& contract_path,
@@ -42,6 +42,12 @@ class ContractClient : public TransactionConstructor {
       const std::string& caller_address, const std::string& contract_address,
       const std::string& func_name,
       const std::vector<std::string>& func_params);
+
+  absl::StatusOr<std::string> GetBalance(const std::string& address);
+  absl::StatusOr<std::string> SetBalance(const std::string& address, const 
std::string& balance);
+
+  private:
+  int SendRequestInternal(const resdb::contract::Request& request, 
resdb::contract::Response* response);
 };
 
 }  // namespace contract
diff --git a/platform/config/resdb_config.cpp b/platform/config/resdb_config.cpp
index 4c3ff954..23129a25 100644
--- a/platform/config/resdb_config.cpp
+++ b/platform/config/resdb_config.cpp
@@ -76,6 +76,9 @@ ResDBConfig::ResDBConfig(const ResConfigData& config_data,
   if (config_data_.tcp_batch_num() == 0) {
     config_data_.set_tcp_batch_num(100);
   }
+  if (config_data_.max_process_txn() == 0) {
+    config_data_.set_max_process_txn(64);
+  }
 }
 
 void ResDBConfig::SetConfigData(const ResConfigData& config_data) {
@@ -177,7 +180,7 @@ void ResDBConfig::SetSignatureVerifierEnabled(bool 
enable_sv) {
 }
 
 // Performance setting
-bool ResDBConfig::IsPerformanceRunning() {
+bool ResDBConfig::IsPerformanceRunning() const {
   return is_performance_running_ || GetConfigData().is_performance_running();
 }
 
diff --git a/platform/config/resdb_config.h b/platform/config/resdb_config.h
index fb56a9dd..9867c6d5 100644
--- a/platform/config/resdb_config.h
+++ b/platform/config/resdb_config.h
@@ -94,7 +94,7 @@ class ResDBConfig {
   void SetSignatureVerifierEnabled(bool enable_sv);
 
   // Performance setting
-  bool IsPerformanceRunning();
+  bool IsPerformanceRunning() const;
   void RunningPerformance(bool);
 
   bool IsTestMode() const;
@@ -135,15 +135,18 @@ class ResDBConfig {
   bool signature_verifier_enabled_ = true;
   bool is_performance_running_ = false;
   bool is_test_mode_ = false;
-  uint32_t max_process_txn_ = 2048;
   uint32_t client_batch_wait_time_ms_ = 100;  // milliseconds, 0.1s
-  uint32_t client_batch_num_ = 100;
   uint64_t viewchange_commit_timeout_ms_ =
       60000;  // default 60s to change viewchange
 
-  uint32_t worker_num_ = 64;
-  uint32_t input_worker_num_ = 1;
-  uint32_t output_worker_num_ = 1;
+
+  // This is the default settings.
+  // change these parameters in the configuration.
+  uint32_t max_process_txn_ = 64;
+  uint32_t worker_num_ = 16;
+  uint32_t input_worker_num_ = 5;
+  uint32_t output_worker_num_ = 5;
+  uint32_t client_batch_num_ = 100;
 };
 
 }  // namespace resdb
diff --git a/platform/consensus/execution/transaction_executor.cpp 
b/platform/consensus/execution/transaction_executor.cpp
index fd24da3a..a62e55f5 100644
--- a/platform/consensus/execution/transaction_executor.cpp
+++ b/platform/consensus/execution/transaction_executor.cpp
@@ -20,6 +20,7 @@
 #include "platform/consensus/execution/transaction_executor.h"
 
 #include <glog/logging.h>
+#include "common/utils/utils.h"
 
 namespace resdb {
 
@@ -35,9 +36,19 @@ TransactionExecutor::TransactionExecutor(
       execute_queue_("execute"),
       stop_(false),
       duplicate_manager_(nullptr) {
+
+  memset(blucket_, 0, sizeof(blucket_));
   global_stats_ = Stats::GetGlobalStats();
   ordering_thread_ = std::thread(&TransactionExecutor::OrderMessage, this);
-  execute_thread_ = std::thread(&TransactionExecutor::ExecuteMessage, this);
+  for (int i = 0; i < execute_thread_num_; ++i) {
+    execute_thread_.push_back(
+        std::thread(&TransactionExecutor::ExecuteMessage, this));
+  }
+
+  for (int i = 0; i < 1; ++i) {
+    prepare_thread_.push_back(
+        std::thread(&TransactionExecutor::PrepareMessage, this));
+  }
 
   if (transaction_manager_ && transaction_manager_->IsOutOfOrder()) {
     execute_OOO_thread_ =
@@ -48,13 +59,55 @@ TransactionExecutor::TransactionExecutor(
 
 TransactionExecutor::~TransactionExecutor() { Stop(); }
 
+void TransactionExecutor::RegisterExecute(int64_t seq) {
+  if (execute_thread_num_ == 1) return;
+  int idx = seq % blucket_num_;
+  std::unique_lock<std::mutex> lk(mutex_);
+  // LOG(ERROR)<<"register seq:"<<seq<<" bluck:"<<blucket_[idx];
+  assert(!blucket_[idx] || !(blucket_[idx] ^ 3));
+  blucket_[idx] = 1;
+  // LOG(ERROR)<<"register seq:"<<seq;
+}
+
+void TransactionExecutor::WaitForExecute(int64_t seq) {
+  if (execute_thread_num_ == 1) return;
+  int pre_idx = (seq - 1 + blucket_num_) % blucket_num_;
+
+  while (!IsStop()) {
+    std::unique_lock<std::mutex> lk(mutex_);
+    cv_.wait_for(lk, std::chrono::milliseconds(10000), [&] {
+      return ((blucket_[pre_idx] & 2) || !blucket_[pre_idx]);
+    });
+    if ((blucket_[pre_idx] & 2) || !blucket_[pre_idx]) {
+      break;
+    }
+  }
+  // LOG(ERROR)<<"wait for :"<<seq<<" done";
+}
+
+void TransactionExecutor::FinishExecute(int64_t seq) {
+  if (execute_thread_num_ == 1) return;
+  int idx = seq % blucket_num_;
+  std::unique_lock<std::mutex> lk(mutex_);
+  // LOG(ERROR)<<"finish :"<<seq<<" done";
+  blucket_[idx] = 3;
+  cv_.notify_all();
+}
+
 void TransactionExecutor::Stop() {
   stop_ = true;
   if (ordering_thread_.joinable()) {
     ordering_thread_.join();
   }
-  if (execute_thread_.joinable()) {
-    execute_thread_.join();
+  for (auto& th : execute_thread_) {
+    if (th.joinable()) {
+      th.join();
+    }
+  }
+  for (auto& th : prepare_thread_) {
+    if (th.joinable()) {
+      th.join();
+    }
   }
   if (execute_OOO_thread_.joinable()) {
     execute_OOO_thread_.join();
@@ -144,6 +197,12 @@ void TransactionExecutor::OrderMessage() {
   return;
 }
 
+void TransactionExecutor::AddExecuteMessage(std::unique_ptr<Request> message) {
+    global_stats_->IncCommit();
+    message->set_commit_time(GetCurrentTime());
+    execute_queue_.Push(std::move(message));
+}
+
 void TransactionExecutor::ExecuteMessage() {
   while (!IsStop()) {
     auto message = execute_queue_.Pop();
@@ -184,10 +243,8 @@ void 
TransactionExecutor::OnlyExecute(std::unique_ptr<Request> request) {
   // LOG(INFO) << " get request batch size:"
   //          << batch_request.user_requests_size()<<" proxy
   //          id:"<<request->proxy_id();
-  // std::unique_ptr<BatchUserResponse> batch_response =
-  //     std::make_unique<BatchUserResponse>();
   std::unique_ptr<BatchUserResponse> response;
-  global_stats_->GetTransactionDetails(batch_request);
+   global_stats_->GetTransactionDetails(batch_request);
   if (transaction_manager_) {
     response = transaction_manager_->ExecuteBatch(batch_request);
   }
@@ -198,45 +255,93 @@ void 
TransactionExecutor::OnlyExecute(std::unique_ptr<Request> request) {
 
 void TransactionExecutor::Execute(std::unique_ptr<Request> request,
                                   bool need_execute) {
+  RegisterExecute(request->seq());
+  std::unique_ptr<BatchUserRequest> batch_request = nullptr;
+  std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>> 
data;
+  std::vector<std::unique_ptr<google::protobuf::Message>> * data_p = nullptr;
+  BatchUserRequest* batch_request_p = nullptr;
+
   // Execute the request, then send the response back to the user.
-  BatchUserRequest batch_request;
-  if (!batch_request.ParseFromString(request->data())) {
-    LOG(ERROR) << "parse data fail";
-  }
-  batch_request.set_seq(request->seq());
-  batch_request.set_hash(request->hash());
-  batch_request.set_proxy_id(request->proxy_id());
-  if (request->has_committed_certs()) {
-    *batch_request.mutable_committed_certs() = request->committed_certs();
+  if (batch_request_p == nullptr) {
+    batch_request = std::make_unique<BatchUserRequest>();
+    if (!batch_request->ParseFromString(request->data())) {
+      LOG(ERROR) << "parse data fail";
+    }
+    batch_request->set_hash(request->hash());
+    if (request->has_committed_certs()) {
+      *batch_request->mutable_committed_certs() = request->committed_certs();
+    }
+    batch_request->set_seq(request->seq());
+    batch_request->set_proxy_id(request->proxy_id());
+    batch_request_p = batch_request.get();
+    // LOG(ERROR)<<"get data from req:";
+  } else {
+  assert(batch_request_p);
+    batch_request_p->set_seq(request->seq());
+    batch_request_p->set_proxy_id(request->proxy_id());
+    // LOG(ERROR)<<" get from cache:"<<uid;
   }
+  assert(batch_request_p);
 
   // LOG(INFO) << " get request batch size:"
-  //         << batch_request.user_requests_size()<<" proxy
-  //         id:"<<request->proxy_id()<<" need execute:"<<need_execute;
-  // std::unique_ptr<BatchUserResponse> batch_response =
-  //     std::make_unique<BatchUserResponse>();
+  // << batch_request.user_requests_size()<<" proxy id:"
+  //  <<request->proxy_id()<<" need execute:"<<need_execute;
 
   std::unique_ptr<BatchUserResponse> response;
-  global_stats_->GetTransactionDetails(batch_request);
+  global_stats_->GetTransactionDetails(*batch_request_p);
   if (transaction_manager_ && need_execute) {
-    response = transaction_manager_->ExecuteBatch(batch_request);
+    if (execute_thread_num_ == 1) {
+      response = transaction_manager_->ExecuteBatch(*batch_request_p);
+    } else {
+      std::vector<std::unique_ptr<std::string>> response_v;
+
+      if(data_p == nullptr) {
+        int64_t start_time = GetCurrentTime();
+        data = std::move(transaction_manager_->Prepare(*batch_request_p));
+        int64_t end_time = GetCurrentTime();
+        if (end_time - start_time > 10) {
+          // LOG(ERROR)<<"exec data done:"<<uid<<" wait
+          // time:"<<(end_time-start_time);
+        }
+        data_p = data.get();
+      }
+
+      WaitForExecute(request->seq());
+           if(data_p->empty() || (*data_p)[0] == nullptr){
+                   response = 
transaction_manager_->ExecuteBatch(*batch_request_p);
+           }
+           else {
+                   response_v = 
transaction_manager_->ExecuteBatchData(*data_p);
+           }
+      FinishExecute(request->seq());
+
+      if(response == nullptr){
+             response = std::make_unique<BatchUserResponse>();
+             for (auto& s : response_v) {
+                     response->add_response()->swap(*s);
+             }
+      }
+    }
   }
+  // LOG(ERROR)<<" CF = :"<<(cf==1)<<" uid:"<<uid;
 
-  if (duplicate_manager_) {
-    duplicate_manager_->AddExecuted(batch_request.hash(), batch_request.seq());
+  if (duplicate_manager_ && batch_request_p) {       
+    duplicate_manager_->AddExecuted(batch_request_p->hash(), 
batch_request_p->seq());              
   }
 
-  global_stats_->IncTotalRequest(batch_request.user_requests_size());
   if (response == nullptr) {
     response = std::make_unique<BatchUserResponse>();
   }
+  global_stats_->IncTotalRequest(batch_request_p->user_requests_size());
+  response->set_proxy_id(batch_request_p->proxy_id());
+  response->set_createtime(batch_request_p->createtime() + 
request->queuing_time());
+  response->set_local_id(batch_request_p->local_id());
 
-  response->set_proxy_id(batch_request.proxy_id());
-  response->set_createtime(batch_request.createtime());
-  response->set_local_id(batch_request.local_id());
-  response->set_hash(batch_request.hash());
+  response->set_seq(request->seq());
 
-  post_exec_func_(std::move(request), std::move(response));
+  if (post_exec_func_) {
+    post_exec_func_(std::move(request), std::move(response));
+  }
 
   global_stats_->IncExecuteDone();
 }
@@ -245,4 +350,150 @@ void 
TransactionExecutor::SetDuplicateManager(DuplicateManager* manager) {
   duplicate_manager_ = manager;
 }
 
+
+bool TransactionExecutor::SetFlag(uint64_t uid, int f) {
+  std::unique_lock<std::mutex> lk(f_mutex_[uid % mod]);
+  auto it = flag_[uid % mod].find(uid);
+  if (it == flag_[uid % mod].end()) {
+    flag_[uid % mod][uid] |= f;
+    // LOG(ERROR)<<"NO FUTURE uid:"<<uid;
+    return true;
+  }
+  assert(it != flag_[uid % mod].end());
+  if (f == Start_Prepare) {
+    if (flag_[uid % mod][uid] & Start_Execute) {
+      return false;
+    }
+  } else if(f == Start_Execute){
+    if (flag_[uid % mod][uid] & End_Prepare) {
+    //if (flag_[uid % mod][uid] & Start_Prepare) {
+      return false;
+    }
+  }
+  flag_[uid % mod][uid] |= f;
+  return true;
+}
+
+void TransactionExecutor::ClearPromise(uint64_t uid) {
+  std::unique_lock<std::mutex> lk(f_mutex_[uid % mod]);
+  auto it = pre_[uid % mod].find(uid);
+  if (it == pre_[uid % mod].end()) {
+    return;
+  }
+  // LOG(ERROR)<<"CLEAR UID:"<<uid;
+  assert(it != pre_[uid % mod].end());
+  assert(flag_[uid % mod].find(uid) != flag_[uid % mod].end());
+  //assert(data_[uid%mod].find(uid) != data_[uid%mod].end());
+  //assert(req_[uid%mod].find(uid) != req_[uid%mod].end());
+  //data_[uid%mod].erase(data_[uid%mod].find(uid));
+  //req_[uid%mod].erase(req_[uid%mod].find(uid));
+  pre_[uid % mod].erase(it);
+  flag_[uid % mod].erase(flag_[uid % mod].find(uid));
+}
+
+std::promise<int>* TransactionExecutor::GetPromise(uint64_t uid) {
+  std::unique_lock<std::mutex> lk(f_mutex_[uid % mod]);
+  auto it = pre_[uid % mod].find(uid);
+  if (it == pre_[uid % mod].end()) {
+    return nullptr;
+  }
+  return it->second.get();
+}
+
+std::unique_ptr<std::future<int>> TransactionExecutor::GetFuture(uint64_t uid) 
{
+  std::unique_lock<std::mutex> lk(f_mutex_[uid % mod]);
+  auto it = pre_[uid % mod].find(uid);
+  if (it == pre_[uid % mod].end()) {
+    return nullptr;
+  }
+  //return std::move(it->second);
+  // LOG(ERROR)<<"add future:"<<uid;
+  return std::make_unique<std::future<int>>(it->second->get_future());
+}
+
+bool TransactionExecutor::AddFuture(uint64_t uid) {
+  std::unique_lock<std::mutex> lk(f_mutex_[uid % mod]);
+  auto it = pre_[uid % mod].find(uid);
+  if (it == pre_[uid % mod].end()) {
+    // LOG(ERROR)<<"add future:"<<uid;
+    std::unique_ptr<std::promise<int>> p =
+        std::make_unique<std::promise<int>>();
+    //auto f = std::make_unique<std::future<int>>(p->get_future());
+    pre_[uid % mod][uid] = std::move(p);
+    //pre_f_[uid % mod][uid] = std::move(f);
+    flag_[uid % mod][uid] = 0;
+    return true;
+  }
+  return false;
+}
+
+void TransactionExecutor::Prepare(std::unique_ptr<Request> request) {
+  if (AddFuture(request->uid())) {
+    prepare_queue_.Push(std::move(request));
+  }
+}
+
+void TransactionExecutor::PrepareMessage() {
+  while (!IsStop()) {
+    std::unique_ptr<Request> request = prepare_queue_.Pop();
+    if (request == nullptr) {
+      continue;
+    }
+
+    uint64_t uid = request->uid();
+    int current_f = SetFlag(uid, Start_Prepare);
+    if (current_f == 0) {
+      // commit has done
+      // LOG(ERROR)<<" want prepare, commit started:"<<uid;
+//      ClearPromise(uid);
+      continue;
+    }
+
+    std::promise<int>* p = GetPromise(uid) ;
+    assert(p);
+    //LOG(ERROR)<<" prepare started:"<<uid;
+
+    // LOG(ERROR)<<" prepare uid:"<<uid;
+
+    // Execute the request, then send the response back to the user.
+    std::unique_ptr<BatchUserRequest> batch_request =
+        std::make_unique<BatchUserRequest>();
+    if (!batch_request->ParseFromString(request->data())) {
+      LOG(ERROR) << "parse data fail";
+    }
+    // batch_request = std::make_unique<BatchUserRequest>();
+    batch_request->set_seq(request->seq());
+    batch_request->set_hash(request->hash());
+    batch_request->set_proxy_id(request->proxy_id());
+    if (request->has_committed_certs()) {
+      *batch_request->mutable_committed_certs() = request->committed_certs();
+    }
+
+    // LOG(ERROR)<<"prepare seq:"<<batch_request->seq()<<" proxy
+    // id:"<<request->proxy_id()<<" local id:"<<batch_request->local_id();
+
+    std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>
+     request_v = transaction_manager_->Prepare(*batch_request);
+    {
+      std::unique_lock<std::mutex> lk(fd_mutex_[uid % mod]);
+   //   assert(request_v);
+      // assert(data_[uid%mod].find(uid) == data_[uid%mod].end());
+      data_[uid%mod][uid] = std::move(request_v);
+      req_[uid % mod][uid] = std::move(batch_request);
+    }
+    //LOG(ERROR)<<"set promise:"<<uid;
+    p->set_value(1);
+    {
+      int set_ret = SetFlag(uid, End_Prepare);
+      if (set_ret == 0) {
+        // LOG(ERROR)<<"commit interrupt:"<<uid;
+        //ClearPromise(uid);
+      } else {
+        //LOG(ERROR)<<"prepare done:"<<uid;
+      }
+    }
+  }
+}
+
+
 }  // namespace resdb
diff --git a/platform/consensus/execution/transaction_executor.h 
b/platform/consensus/execution/transaction_executor.h
index 2b111164..6fb8ef39 100644
--- a/platform/consensus/execution/transaction_executor.h
+++ b/platform/consensus/execution/transaction_executor.h
@@ -62,8 +62,16 @@ class TransactionExecutor {
 
   void SetDuplicateManager(DuplicateManager* manager);
 
+  void AddExecuteMessage(std::unique_ptr<Request> message);
+
   Storage* GetStorage();
 
+  void RegisterExecute(int64_t seq);
+  void WaitForExecute(int64_t seq);
+  void FinishExecute(int64_t seq);
+
+  void Prepare(std::unique_ptr<Request> request);
+
  private:
   void Execute(std::unique_ptr<Request> request, bool need_execute = true);
   void OnlyExecute(std::unique_ptr<Request> request);
@@ -80,6 +88,14 @@ class TransactionExecutor {
 
   void UpdateMaxExecutedSeq(uint64_t seq);
 
+  bool SetFlag(uint64_t uid, int f);
+  void ClearPromise(uint64_t uid);
+  void PrepareMessage();
+
+  bool AddFuture(uint64_t uid);
+  std::unique_ptr<std::future<int>> GetFuture(uint64_t uid);
+  std::promise<int>* GetPromise(uint64_t uid);
+
  protected:
   ResDBConfig config_;
 
@@ -91,11 +107,42 @@ class TransactionExecutor {
   SystemInfo* system_info_ = nullptr;
   std::unique_ptr<TransactionManager> transaction_manager_ = nullptr;
   std::map<uint64_t, std::unique_ptr<Request>> candidates_;
-  std::thread ordering_thread_, execute_thread_, execute_OOO_thread_;
+  std::thread ordering_thread_, execute_OOO_thread_;
+  std::vector<std::thread> execute_thread_;
   LockFreeQueue<Request> commit_queue_, execute_queue_, execute_OOO_queue_;
   std::atomic<bool> stop_;
   Stats* global_stats_ = nullptr;
   DuplicateManager* duplicate_manager_;
+  int execute_thread_num_ = 10;
+  static const int blucket_num_ = 1024;
+  int blucket_[blucket_num_];
+  std::condition_variable cv_;
+  std::mutex mutex_;
+
+  enum PrepareType {
+    Start_Prepare = 1,
+    Start_Execute = 2,
+    End_Prepare = 4,
+  };
+
+
+  std::vector<std::thread> prepare_thread_;
+  static const int mod = 2048;
+  std::mutex f_mutex_[mod], fd_mutex_[mod];
+  LockFreeQueue<Request> prepare_queue_;
+  LockFreeQueue<int64_t> gc_queue_;
+  typedef std::unique_ptr<std::promise<int>> PromiseType;
+  std::map<uint64_t, PromiseType> pre_[mod];
+
+  std::map<uint64_t, std::unique_ptr<std::future<int>>> pre_f_[mod];
+  std::map<uint64_t, int> flag_[mod];
+
+  std::map<uint64_t, std::unique_ptr<BatchUserRequest>> req_[mod];
+  std::unordered_map<
+      uint64_t,
+      std::unique_ptr<std::vector<std::unique_ptr<google::protobuf::Message>>>>
+      data_[mod];
+
 };
 
 }  // namespace resdb
diff --git a/platform/networkstrate/replica_communicator.cpp 
b/platform/networkstrate/replica_communicator.cpp
index de096125..f1521acb 100644
--- a/platform/networkstrate/replica_communicator.cpp
+++ b/platform/networkstrate/replica_communicator.cpp
@@ -34,7 +34,8 @@ ReplicaCommunicator::ReplicaCommunicator(
       verifier_(verifier),
       is_running_(false),
       batch_queue_("bc_batch", tcp_batch),
-      is_use_long_conn_(is_use_long_conn) {
+      is_use_long_conn_(is_use_long_conn),
+      tcp_batch_(tcp_batch) {
   global_stats_ = Stats::GetGlobalStats();
   if (is_use_long_conn_) {
     worker_ = std::make_unique<boost::asio::io_service::work>(io_service_);
@@ -42,18 +43,10 @@ ReplicaCommunicator::ReplicaCommunicator(
       worker_threads_.push_back(std::thread([&]() { io_service_.run(); }));
     }
   }
-
-  /*
-  for (const ReplicaInfo& info : replicas) {
-    std::string ip = info.ip();
-    int port = info.port();
-    auto client = std::make_unique<AsyncReplicaClient>(
-        &io_service_, ip, port + (is_use_long_conn_ ? 10000 : 0), true);
-    client_pools_[std::make_pair(ip, port)] = std::move(client);
-  }
-  */
+  LOG(ERROR)<<" tcp batch:"<<tcp_batch;
 
   StartBroadcastInBackGround();
+
 }
 
 ReplicaCommunicator::~ReplicaCommunicator() {
@@ -131,6 +124,74 @@ void ReplicaCommunicator::StartBroadcastInBackGround() {
   });
 }
 
+void ReplicaCommunicator::StartSingleInBackGround(const std::string& ip, int 
port) {
+  single_bq_[std::make_pair(ip,port)] = 
std::make_unique<BatchQueue<std::unique_ptr<QueueItem>>>("s_batch", tcp_batch_);
+
+  ReplicaInfo replica_info;
+  for (const auto& replica : replicas_) {
+    if (replica.ip() == ip && replica.port() == port) {
+      replica_info = replica;
+      break;
+    }
+  }
+
+  if (replica_info.ip().empty()) {
+    for (const auto& replica : GetClientReplicas()) {
+      if (replica.ip() == ip && replica.port() == port) {
+        replica_info = replica;
+        break;
+      }
+    }
+  }
+
+
+  
single_thread_.push_back(std::thread([&](BatchQueue<std::unique_ptr<QueueItem>> 
*bq, ReplicaInfo replica_info) {
+    while (IsRunning()) {
+      std::vector<std::unique_ptr<QueueItem>> batch_req =
+          bq->Pop(50000);
+      if (batch_req.empty()) {
+        continue;
+      }
+      BroadcastData broadcast_data;
+      for (auto& queue_item : batch_req) {
+        broadcast_data.add_data()->swap(queue_item->data);
+      }
+
+      global_stats_->SendBroadCastMsg(broadcast_data.data_size());
+      //LOG(ERROR)<<" send to ip:"<<replica_info.ip()<<" 
port:"<<replica_info.port()<<" bq size:"<<batch_req.size();
+      int ret = SendMessageFromPool(broadcast_data, {replica_info});
+      if (ret < 0) {
+        LOG(ERROR) << "broadcast request fail:";
+      }
+      //LOG(ERROR)<<" send to ip:"<<replica_info.ip()<<" 
port:"<<replica_info.port()<<" bq size:"<<batch_req.size()<<" done";
+    }
+  }, single_bq_[std::make_pair(ip,port)].get(), replica_info));
+}
+
+
+int ReplicaCommunicator::SendSingleMessage(const google::protobuf::Message& 
message, 
+const ReplicaInfo& replica_info) {
+
+  std::string ip = replica_info.ip();
+  int port = replica_info.port();
+
+    //LOG(ERROR)<<" send msg ip:"<<ip<<" port:"<<port;
+  global_stats_->BroadCastMsg();
+  if (is_use_long_conn_) {
+    auto item = std::make_unique<QueueItem>();
+    item->data = NetChannel::GetRawMessageString(message, verifier_);
+    std::lock_guard<std::mutex> lk(smutex_);
+    if(single_bq_.find(std::make_pair(ip, port)) == single_bq_.end()){
+      StartSingleInBackGround(ip, port);
+    }
+    assert(single_bq_[std::make_pair(ip, port)] != nullptr);
+    single_bq_[std::make_pair(ip, port)]->Push(std::move(item));
+    return 0;
+  } else {
+    return SendMessageInternal(message, replicas_);
+  }
+}
+
 int ReplicaCommunicator::SendMessage(const google::protobuf::Message& message) 
{
   global_stats_->BroadCastMsg();
   if (is_use_long_conn_) {
@@ -139,13 +200,14 @@ int ReplicaCommunicator::SendMessage(const 
google::protobuf::Message& message) {
     batch_queue_.Push(std::move(item));
     return 0;
   } else {
-    LOG(ERROR) << "send internal";
     return SendMessageInternal(message, replicas_);
   }
 }
 
 int ReplicaCommunicator::SendMessage(const google::protobuf::Message& message,
                                      const ReplicaInfo& replica_info) {
+  return SendSingleMessage(message, replica_info);
+
   if (is_use_long_conn_) {
     std::string data = NetChannel::GetRawMessageString(message, verifier_);
     BroadcastData broadcast_data;
@@ -188,11 +250,13 @@ int ReplicaCommunicator::SendMessageFromPool(
     if (client == nullptr) {
       continue;
     }
+    //LOG(ERROR) << "send to:" << replica.ip();
     if (client->SendMessage(data) == 0) {
       ret++;
     } else {
       LOG(ERROR) << "send to:" << replica.ip() << " fail";
     }
+    //LOG(ERROR) << "send to:" << replica.ip()<<" done";
   }
   return ret;
 }
@@ -222,6 +286,7 @@ AsyncReplicaClient* ReplicaCommunicator::GetClientFromPool(
     auto client = std::make_unique<AsyncReplicaClient>(
         &io_service_, ip, port + (is_use_long_conn_ ? 10000 : 0), true);
     client_pools_[std::make_pair(ip, port)] = std::move(client);
+    //StartSingleInBackGround(ip, port);
   }
   return client_pools_[std::make_pair(ip, port)].get();
 }
@@ -257,7 +322,7 @@ void ReplicaCommunicator::SendMessage(const 
google::protobuf::Message& message,
   }
 
   if (target_replica.ip().empty()) {
-    LOG(ERROR) << "no replica info node:" << node_id;
+    LOG(ERROR) << "no replica info";
     return;
   }
 
diff --git a/platform/networkstrate/replica_communicator.h 
b/platform/networkstrate/replica_communicator.h
index 24ef8101..239e4d21 100644
--- a/platform/networkstrate/replica_communicator.h
+++ b/platform/networkstrate/replica_communicator.h
@@ -37,7 +37,7 @@ class ReplicaCommunicator {
   ReplicaCommunicator(const std::vector<ReplicaInfo>& replicas,
                       SignatureVerifier* verifier = nullptr,
                       bool is_use_long_conn = false, int epoll_num = 1,
-                      int tcp_batch = 100);
+                      int tcp_batch = 1);
   virtual ~ReplicaCommunicator();
 
   // HeartBeat message is used to broadcast public keys.
@@ -73,6 +73,11 @@ class ReplicaCommunicator {
   bool IsRunning() const;
   bool IsInPool(const ReplicaInfo& replica_info);
 
+  void StartSingleInBackGround(const std::string& ip, int port);
+
+  int SendSingleMessage(const google::protobuf::Message& message, 
+      const ReplicaInfo& replica_info);
+
  private:
   std::vector<ReplicaInfo> replicas_;
   SignatureVerifier* verifier_;
@@ -93,6 +98,14 @@ class ReplicaCommunicator {
   std::vector<std::thread> worker_threads_;
   std::vector<ReplicaInfo> clients_;
   std::mutex mutex_;
+  
+
+
+  std::map<std::pair<std::string, int>, 
+    std::unique_ptr<BatchQueue<std::unique_ptr<QueueItem>>>> single_bq_;
+  std::vector<std::thread> single_thread_;
+  int tcp_batch_;
+  std::mutex smutex_;
 };
 
 }  // namespace resdb
diff --git a/platform/proto/resdb.proto b/platform/proto/resdb.proto
index ac60498a..47edac38 100644
--- a/platform/proto/resdb.proto
+++ b/platform/proto/resdb.proto
@@ -88,6 +88,7 @@ message Request {
     int64 uid = 23;
     int64 create_time = 24;
     int64 commit_time = 25;
+    bytes data_hash = 26;
 }
 
 // The response message containing response
diff --git a/proto/contract/rpc.proto b/proto/contract/rpc.proto
index 8df1dd40..91295a5f 100644
--- a/proto/contract/rpc.proto
+++ b/proto/contract/rpc.proto
@@ -31,22 +31,29 @@ message Request {
         CREATE_ACCOUNT = 1; // deploy contract
         DEPLOY = 2; // deploy contract
         EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
+        GETBALANCE = 4; // get balance directly (key-value)
+        SETBALANCE = 5; // set balance directly (key-value)
     };
 
     CMD cmd = 1;
+
+    // for smart-contract
     string caller_address = 2;
     optional DeployInfo deploy_info = 3;
     optional string contract_address = 4;
     optional Params func_params = 5;
-    optional string external_address = 6;
+
+    // for key-value
+    optional string account = 6;
+    // hex string
+    optional string balance = 7;
 }
 
 
 
 message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+  int32 ret = 1;
+  optional Account account = 2;
+  optional Contract contract = 3;
+  optional string res = 4;
 }
diff --git a/proto/kv/kv.proto b/proto/kv/kv.proto
index a76c2f48..750058e7 100644
--- a/proto/kv/kv.proto
+++ b/proto/kv/kv.proto
@@ -47,6 +47,7 @@ message KVRequest {
     int32 max_version = 8;
     // For top history
     int32 top_number = 9;
+    bytes smart_contract_request = 10;
 }
 
 message ValueInfo {
@@ -68,5 +69,6 @@ message KVResponse {
     bytes value = 2;
     ValueInfo value_info = 3;
     Items items = 4;
+    bytes smart_contract_response = 10;
 }
 
diff --git a/service/contract/BUILD b/service/contract/BUILD
index 11545b16..d97c304b 100644
--- a/service/contract/BUILD
+++ b/service/contract/BUILD
@@ -26,5 +26,6 @@ cc_binary(
         "//platform/config:resdb_config_utils",
         "//platform/consensus/ordering/pbft:consensus_manager_pbft",
         "//service/utils:server_factory",
+        "//chain/storage:memory_db",
     ],
 )
diff --git a/service/contract/contract_service.cpp 
b/service/contract/contract_service.cpp
index 73826af9..5bcc8942 100644
--- a/service/contract/contract_service.cpp
+++ b/service/contract/contract_service.cpp
@@ -19,6 +19,7 @@
 
 #include <glog/logging.h>
 
+#include "chain/storage/memory_db.h"
 #include "executor/contract/executor/contract_executor.h"
 #include "platform/config/resdb_config_utils.h"
 #include "platform/consensus/ordering/pbft/consensus_manager_pbft.h"
@@ -62,9 +63,10 @@ int main(int argc, char** argv) {
       GenerateResDBConfig(config_file, private_key_file, cert_file);
   ResConfigData config_data = config->GetConfigData();
 
+  std::unique_ptr<resdb::Storage> memory_db = resdb::storage::NewMemoryDB();
   auto server = CustomGenerateResDBServer<ConsensusManagerPBFT>(
       config_file, private_key_file, cert_file,
-      std::make_unique<ContractTransactionManager>(), logging_dir);
+      std::make_unique<ContractTransactionManager>(memory_db.get()), 
logging_dir);
 
   server->Run();
 }
diff --git a/service/tools/contract/api_tools/contract_tools.cpp 
b/service/tools/contract/api_tools/contract_tools.cpp
index 0271b312..72e7a73e 100644
--- a/service/tools/contract/api_tools/contract_tools.cpp
+++ b/service/tools/contract/api_tools/contract_tools.cpp
@@ -19,9 +19,11 @@
 
 #include <glog/logging.h>
 
+#include <getopt.h>
+#include <nlohmann/json.hpp>
 #include <boost/algorithm/string.hpp>
 #include <vector>
-#include <unistd.h>  // For getopt
+#include <fstream>
 
 #include "interface/contract/contract_client.h"
 #include "platform/config/resdb_config_utils.h"
@@ -30,21 +32,21 @@ using resdb::GenerateResDBConfig;
 using resdb::ResDBConfig;
 using resdb::contract::ContractClient;
 
+
+
 void ShowUsage() {
   printf(
-      "<cmd> -c <config> -m <caller address> -n <contract name> -p <contract "
-      "path> -a <params> -e <external address>\n");
+      "<cmd> -c <config> -m <caller address> -n <contract name> -p <contact "
+      "path> -a <params> \n");
   exit(0);
 }
 
-void AddAddress(ContractClient* client, const std::string& external_address) {
-  absl::Status status = client->AddExternalAddress(external_address);
-  if (!status.ok()) {
-    printf("Add address failed\n");
-  } else {
-    printf("Address added successfully\n");
-  }
-}
+static struct option long_options[] = {
+    { "cmd", required_argument, NULL, 'm'},
+    { "config_file", required_argument, NULL, 'f'},
+    { 0, 0, 0, 0 }
+};
+
 
 void CreateAccount(ContractClient* client) {
   auto account = client->CreateAccount();
@@ -81,70 +83,88 @@ void ExecuteContract(ContractClient* client, const 
std::string& caller_address,
   LOG(ERROR) << "execute result:\n" << *output;
 }
 
+nlohmann::json ReadJSConfig(const std::string& config_path) {
+
+  std::ifstream contract_fstream(config_path);
+  if (!contract_fstream) {
+    throw std::runtime_error( "Unable to open config file "+config_path);
+  }
+
+  return nlohmann::json::parse(contract_fstream);
+}
+
+std::string GetValue(const nlohmann::json& js, std::string key){
+if(!js.contains(key)){
+      printf("need %s\n", key.c_str());
+      exit(0);
+    }
+    return js[key];
+}
+
+
 int main(int argc, char** argv) {
-  if (argc < 3) {
-    ShowUsage();
+  if (argc < 2) {
+    printf("<cmd> -c [config]\n");
     return 0;
   }
 
-  std::string cmd = argv[1];
+
+  std::string config_file;
+  
+  std::string cmd;
   std::string caller_address, contract_name, contract_path, params,
-      contract_address, func_name, external_address;  // Added external_address
+      contract_address, func_name;
   int c;
+  int option_index;
   std::string client_config_file;
-  while ((c = getopt(argc, argv, "m:c:a:n:p:h:f:s:e:")) != -1) {  // Added 'e:'
+  while ((c = getopt_long(argc, argv, "c:h", long_options, &option_index)) != 
-1) {
     switch (c) {
-      case 'm':
-        caller_address = optarg;
-        break;
-      case 'c':
-        client_config_file = optarg;
-        break;
-      case 'n':
-        contract_name = optarg;
+      case -1:
         break;
       case 'f':
-        func_name = optarg;
-        break;
-      case 'p':
-        contract_path = optarg;
-        break;
-      case 'a':
-        params = optarg;
+        config_file = optarg;
         break;
-      case 's':
-        contract_address = optarg;
-        break;
-      case 'e':
-        external_address = optarg;  // Handle the 'e' option
+      case 'c':
+        client_config_file = optarg;
         break;
       case 'h':
         ShowUsage();
         break;
-      default:
-        ShowUsage();
-        break;
     }
   }
 
-  printf("cmd = %s config path = %s\n", cmd.c_str(),
-         client_config_file.c_str());
+  nlohmann::json js = ReadJSConfig(config_file);
+  cmd = GetValue(js, "command");
+
+  printf("client config path = %s config path = %s cmd = %s\n", 
client_config_file.c_str(), config_file.c_str(), cmd.c_str());
   ResDBConfig config = GenerateResDBConfig(client_config_file);
   config.SetClientTimeoutMs(100000);
 
   ContractClient client(config);
 
-  if (cmd == "create") {
+  if (cmd == "create_account") {
     CreateAccount(&client);
-  } else if (cmd == "add_address") {
-    AddAddress(&client, external_address);
   } else if (cmd == "deploy") {
+    
+    contract_path = GetValue(js, "contract_path");
+    contract_name = GetValue(js, "contract_name");
+    contract_address = GetValue(js, "contract_address");
+    params = GetValue(js, "init_params");
+
+    printf("contract path %s cmd %s contract name %s caller_address %s init 
params %s\n", contract_path.c_str(), cmd.c_str(), contract_name.c_str(), 
contract_address.c_str(), params.c_str());
+
     std::vector<std::string> init_params;
     boost::split(init_params, params, boost::is_any_of(","));
 
-    DeployContract(&client, caller_address, contract_name, contract_path,
+    DeployContract(&client, contract_address, contract_name, contract_path,
                    init_params);
   } else if (cmd == "execute") {
+
+    caller_address = GetValue(js, "caller_address");
+    contract_address = GetValue(js, "contract_address");
+    func_name = GetValue(js, "func_name");
+    params = GetValue(js, "params");
+
     printf(
         "execute\n caller address:%s\n contract address: %s\n func: %s\n "
         "params:%s\n",
@@ -155,7 +175,6 @@ int main(int argc, char** argv) {
 
     ExecuteContract(&client, caller_address, contract_address, func_name,
                     func_params);
-  } else {
-    ShowUsage();
   }
-}
\ No newline at end of file
+}
+
diff --git a/proto/contract/rpc.proto 
b/service/tools/contract/api_tools/create.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/contract/api_tools/create.js
index 8df1dd40..26d34f6e 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/contract/api_tools/create.js
@@ -17,36 +17,7 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"create_account",
+  
"contract_path":"/home/junechen/projects/asf-resilientdb/service/tools/contract/api_tools/example_contract/token.json"
 }
diff --git a/proto/contract/rpc.proto 
b/service/tools/contract/api_tools/deploy.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/contract/api_tools/deploy.js
index 8df1dd40..b013fa34 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/contract/api_tools/deploy.js
@@ -17,36 +17,10 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"deploy",
+  "contract_path": 
"service/tools/contract/api_tools/example_contract/token.json",
+  "contract_name": "token.sol:Token",
+  "init_params": "1000",
+  "contract_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8"
 }
diff --git a/service/tools/contract/api_tools/example_contract/token.json 
b/service/tools/contract/api_tools/example_contract/token.json
index 1f91b6d5..eaeaa36f 100644
--- a/service/tools/contract/api_tools/example_contract/token.json
+++ b/service/tools/contract/api_tools/example_contract/token.json
@@ -1,15 +1,13 @@
 {
-  "contracts":
-  {
-    "token.sol:Token":
-    {
-      "bin": 
"608060405234801561001057600080fd5b506040516101fe3803806101fe8339818101604052602081101561003357600080fd5b5051336000908152602081905260409020556101aa806100546000396000f3fe608060405234801561001057600080fd5b5060043610610052577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610057578063a9059cbb1461008f575b600080fd5b61007d6004803603602081101561006d57600080fd5b5035600160a060020a03166100cf565b60408051918252519081900360200190f35b6100bb6004803603604081
 [...]
-      "hashes":
-      {
+  "contracts": {
+    "token.sol:Token": {
+      "bin": 
"6080604052348015600f57600080fd5b506040516103f83803806103f8833981016040819052602c916040565b336000908152602081905260409020556058565b600060208284031215605157600080fd5b5051919050565b610391806100676000396000f3fe608060405234801561001057600080fd5b506004361061005d577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610062578063a5f2a1521461009e578063a9059cbb146100c1575b600080fd5b61008b610070366004610284565b600160a060020a03166000908152602081905260409020
 [...]
+      "hashes": {
         "balanceOf(address)": "70a08231",
-        "transfer(address,uint256)": "a9059cbb"
+        "transfer(address,uint256)": "a9059cbb",
+        "transferTo(address,address,uint256)": "a5f2a152"
       }
     }
   },
-  "version": "0.5.16+commit.9c3226ce.Linux.g++"
+  "version": "0.8.28+commit.7893614a.Linux.g++"
 }
diff --git a/service/tools/contract/api_tools/example_contract/token.sol 
b/service/tools/contract/api_tools/example_contract/token.sol
index f5588212..498cacc1 100644
--- a/service/tools/contract/api_tools/example_contract/token.sol
+++ b/service/tools/contract/api_tools/example_contract/token.sol
@@ -28,4 +28,18 @@ contract Token {
       return false;
     }
   }
+
+  function transferTo(address _from, address _to, uint256 _value) public 
returns (bool) {
+    if (balances[_from] >= _value) {
+      balances[_from] -= _value;
+      balances[_to] += _value;
+      emit Transfer(_from, _to, _value);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
 }  
diff --git a/proto/contract/rpc.proto 
b/service/tools/contract/api_tools/execute.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/contract/api_tools/execute.js
index 8df1dd40..df863de0 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/contract/api_tools/execute.js
@@ -17,36 +17,11 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"execute",
+  "init_params": "1000",
+  "contract_address": "0xfc08e5bfebdcf7bb4cf5aafc29be03c1d53898f1",
+  "caller_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8",
+  "func_name":"transfer(address,uint256)",
+  "params":"0x1be8e78d765a2e63339fc99a66320db73158a35a,100"
 }
diff --git a/service/tools/contract/service_tools/start_contract_service.sh 
b/service/tools/contract/service_tools/start_contract_service.sh
index 28438d75..fa290c6b 100755
--- a/service/tools/contract/service_tools/start_contract_service.sh
+++ b/service/tools/contract/service_tools/start_contract_service.sh
@@ -1,3 +1,5 @@
+<<<<<<< HEAD
+=======
 #
 # Licensed to the Apache Software Foundation (ASF) under one
 # or more contributor license agreements.  See the NOTICE file
@@ -16,6 +18,7 @@
 # specific language governing permissions and limitations
 # under the License.
 #
+>>>>>>> master
 killall -9 contract_service
 
 SERVER_PATH=./bazel-bin/service/contract/contract_service
diff --git a/service/tools/kv/api_tools/BUILD b/service/tools/kv/api_tools/BUILD
index 61a7d366..a25b2f95 100644
--- a/service/tools/kv/api_tools/BUILD
+++ b/service/tools/kv/api_tools/BUILD
@@ -29,6 +29,18 @@ cc_binary(
     ],
 )
 
+cc_binary(
+    name = "contract_service_tools",
+    srcs = ["contract_service_tools.cpp"],
+    deps = [
+        "//common/proto:signature_info_cc_proto",
+        "//interface/kv:contract_client",
+        "//platform/config:resdb_config_utils",
+       "//common:boost_comm",
+    ],
+)
+
+
 cc_binary(
     name = "kv_client_txn_tools",
     srcs = ["kv_client_txn_tools.cpp"],
diff --git a/service/tools/contract/api_tools/contract_tools.cpp 
b/service/tools/kv/api_tools/contract_service_tools.cpp
similarity index 60%
copy from service/tools/contract/api_tools/contract_tools.cpp
copy to service/tools/kv/api_tools/contract_service_tools.cpp
index 0271b312..0fcb05c5 100644
--- a/service/tools/contract/api_tools/contract_tools.cpp
+++ b/service/tools/kv/api_tools/contract_service_tools.cpp
@@ -19,11 +19,13 @@
 
 #include <glog/logging.h>
 
+#include <getopt.h>
+#include <nlohmann/json.hpp>
 #include <boost/algorithm/string.hpp>
 #include <vector>
-#include <unistd.h>  // For getopt
+#include <fstream>
 
-#include "interface/contract/contract_client.h"
+#include "interface/kv/contract_client.h"
 #include "platform/config/resdb_config_utils.h"
 
 using resdb::GenerateResDBConfig;
@@ -32,19 +34,17 @@ using resdb::contract::ContractClient;
 
 void ShowUsage() {
   printf(
-      "<cmd> -c <config> -m <caller address> -n <contract name> -p <contract "
-      "path> -a <params> -e <external address>\n");
+      "<cmd> -c <config> -m <caller address> -n <contract name> -p <contact "
+      "path> -a <params> \n");
   exit(0);
 }
 
-void AddAddress(ContractClient* client, const std::string& external_address) {
-  absl::Status status = client->AddExternalAddress(external_address);
-  if (!status.ok()) {
-    printf("Add address failed\n");
-  } else {
-    printf("Address added successfully\n");
-  }
-}
+static struct option long_options[] = {
+    { "cmd", required_argument, NULL, 'm'},
+    { "config_file", required_argument, NULL, 'f'},
+    { 0, 0, 0, 0 }
+};
+
 
 void CreateAccount(ContractClient* client) {
   auto account = client->CreateAccount();
@@ -81,70 +81,88 @@ void ExecuteContract(ContractClient* client, const 
std::string& caller_address,
   LOG(ERROR) << "execute result:\n" << *output;
 }
 
+nlohmann::json ReadJSConfig(const std::string& config_path) {
+
+  std::ifstream contract_fstream(config_path);
+  if (!contract_fstream) {
+    throw std::runtime_error( "Unable to open config file "+config_path);
+  }
+
+  return nlohmann::json::parse(contract_fstream);
+}
+
+std::string GetValue(const nlohmann::json& js, std::string key){
+if(!js.contains(key)){
+      printf("need %s\n", key.c_str());
+      exit(0);
+    }
+    return js[key];
+}
+
+
 int main(int argc, char** argv) {
-  if (argc < 3) {
-    ShowUsage();
+  if (argc < 2) {
+    printf("<cmd> -c [config]\n");
     return 0;
   }
 
-  std::string cmd = argv[1];
+
+  std::string config_file;
+  
+  std::string cmd;
   std::string caller_address, contract_name, contract_path, params,
-      contract_address, func_name, external_address;  // Added external_address
+      contract_address, func_name;
   int c;
+  int option_index;
   std::string client_config_file;
-  while ((c = getopt(argc, argv, "m:c:a:n:p:h:f:s:e:")) != -1) {  // Added 'e:'
+  while ((c = getopt_long(argc, argv, "c:h", long_options, &option_index)) != 
-1) {
     switch (c) {
-      case 'm':
-        caller_address = optarg;
-        break;
-      case 'c':
-        client_config_file = optarg;
-        break;
-      case 'n':
-        contract_name = optarg;
+      case -1:
         break;
       case 'f':
-        func_name = optarg;
+        config_file = optarg;
         break;
-      case 'p':
-        contract_path = optarg;
-        break;
-      case 'a':
-        params = optarg;
-        break;
-      case 's':
-        contract_address = optarg;
-        break;
-      case 'e':
-        external_address = optarg;  // Handle the 'e' option
+      case 'c':
+        client_config_file = optarg;
         break;
       case 'h':
         ShowUsage();
         break;
-      default:
-        ShowUsage();
-        break;
     }
   }
 
-  printf("cmd = %s config path = %s\n", cmd.c_str(),
-         client_config_file.c_str());
+  nlohmann::json js = ReadJSConfig(config_file);
+  std::cout<<js<<std::endl;
+  cmd = GetValue(js, "command");
+
   ResDBConfig config = GenerateResDBConfig(client_config_file);
   config.SetClientTimeoutMs(100000);
 
   ContractClient client(config);
-
-  if (cmd == "create") {
+  printf("cmd = %s\n", cmd.c_str());
+  if (cmd == "create_account") {
     CreateAccount(&client);
-  } else if (cmd == "add_address") {
-    AddAddress(&client, external_address);
   } else if (cmd == "deploy") {
+    
+    contract_path = GetValue(js, "contract_path");
+    contract_name = GetValue(js, "contract_name");
+    contract_address = GetValue(js, "contract_address");
+    params = GetValue(js, "init_params");
+
+    printf("contract path %s cmd %s contract name %s caller_address %s init 
params %s\n", contract_path.c_str(), cmd.c_str(), contract_name.c_str(), 
contract_address.c_str(), params.c_str());
+
     std::vector<std::string> init_params;
     boost::split(init_params, params, boost::is_any_of(","));
 
-    DeployContract(&client, caller_address, contract_name, contract_path,
+    DeployContract(&client, contract_address, contract_name, contract_path,
                    init_params);
   } else if (cmd == "execute") {
+
+    caller_address = GetValue(js, "caller_address");
+    contract_address = GetValue(js, "contract_address");
+    func_name = GetValue(js, "func_name");
+    params = GetValue(js, "params");
+
     printf(
         "execute\n caller address:%s\n contract address: %s\n func: %s\n "
         "params:%s\n",
@@ -155,7 +173,18 @@ int main(int argc, char** argv) {
 
     ExecuteContract(&client, caller_address, contract_address, func_name,
                     func_params);
-  } else {
-    ShowUsage();
   }
-}
\ No newline at end of file
+  else if (cmd == "get_balance") {
+    std::string address = GetValue(js, "address");
+    auto balance_or = client.GetBalance(address);
+    printf("get address %s balance %s\n", address.c_str(), 
(*balance_or).c_str());
+  } else if (cmd == "set_balance") {
+    std::string address = GetValue(js, "address");
+    std::string balance = GetValue(js, "balance");
+    printf("address %s balance %s\n", address.c_str(), balance.c_str());
+    auto ret = client.SetBalance(address, balance);
+    printf("set address %s balance %s ret %s\n", address.c_str(), 
balance.c_str(), (*ret).c_str());
+  }
+
+}
+
diff --git a/proto/contract/rpc.proto b/service/tools/kv/api_tools/create.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/kv/api_tools/create.js
index 8df1dd40..79c94f9f 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/kv/api_tools/create.js
@@ -17,36 +17,6 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"create_account",
 }
diff --git a/proto/contract/rpc.proto b/service/tools/kv/api_tools/deploy.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/kv/api_tools/deploy.js
index 8df1dd40..5c8cac1b 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/kv/api_tools/deploy.js
@@ -17,36 +17,10 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"deploy",
+  "contract_path": "service/tools/kv/api_tools/example_contract/token.json",
+  "contract_name": "token.sol:Token",
+  "init_params": "1000",
+  "contract_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8"
 }
diff --git a/service/tools/kv/api_tools/example_contract/compile.sh 
b/service/tools/kv/api_tools/example_contract/compile.sh
new file mode 100644
index 00000000..062b5ce7
--- /dev/null
+++ b/service/tools/kv/api_tools/example_contract/compile.sh
@@ -0,0 +1,21 @@
+ #
+ # Licensed to the Apache Software Foundation (ASF) under one
+ # or more contributor license agreements.  See the NOTICE file
+ # distributed with this work for additional information
+ # regarding copyright ownership.  The ASF licenses this file
+ # to you under the Apache License, Version 2.0 (the
+ # "License"); you may not use this file except in compliance
+ # with the License.  You may obtain a copy of the License at
+ #
+ #   http://www.apache.org/licenses/LICENSE-2.0
+ #
+ # Unless required by applicable law or agreed to in writing,
+ # software distributed under the License is distributed on an
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ # KIND, either express or implied.  See the License for the
+ # specific language governing permissions and limitations
+ # under the License.
+ #
+
+solc --evm-version homestead --combined-json bin,hashes --pretty-json 
--optimize token.sol > token.json
+
diff --git a/service/tools/kv/api_tools/example_contract/token.json 
b/service/tools/kv/api_tools/example_contract/token.json
new file mode 100644
index 00000000..eaeaa36f
--- /dev/null
+++ b/service/tools/kv/api_tools/example_contract/token.json
@@ -0,0 +1,13 @@
+{
+  "contracts": {
+    "token.sol:Token": {
+      "bin": 
"6080604052348015600f57600080fd5b506040516103f83803806103f8833981016040819052602c916040565b336000908152602081905260409020556058565b600060208284031215605157600080fd5b5051919050565b610391806100676000396000f3fe608060405234801561001057600080fd5b506004361061005d577c0100000000000000000000000000000000000000000000000000000000600035046370a082318114610062578063a5f2a1521461009e578063a9059cbb146100c1575b600080fd5b61008b610070366004610284565b600160a060020a03166000908152602081905260409020
 [...]
+      "hashes": {
+        "balanceOf(address)": "70a08231",
+        "transfer(address,uint256)": "a9059cbb",
+        "transferTo(address,address,uint256)": "a5f2a152"
+      }
+    }
+  },
+  "version": "0.8.28+commit.7893614a.Linux.g++"
+}
diff --git a/service/tools/contract/api_tools/example_contract/token.sol 
b/service/tools/kv/api_tools/example_contract/token.sol
similarity index 72%
copy from service/tools/contract/api_tools/example_contract/token.sol
copy to service/tools/kv/api_tools/example_contract/token.sol
index f5588212..498cacc1 100644
--- a/service/tools/contract/api_tools/example_contract/token.sol
+++ b/service/tools/kv/api_tools/example_contract/token.sol
@@ -28,4 +28,18 @@ contract Token {
       return false;
     }
   }
+
+  function transferTo(address _from, address _to, uint256 _value) public 
returns (bool) {
+    if (balances[_from] >= _value) {
+      balances[_from] -= _value;
+      balances[_to] += _value;
+      emit Transfer(_from, _to, _value);
+      return true;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
 }  
diff --git a/proto/contract/rpc.proto b/service/tools/kv/api_tools/execute.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/kv/api_tools/execute.js
index 8df1dd40..df863de0 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/kv/api_tools/execute.js
@@ -17,36 +17,11 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"execute",
+  "init_params": "1000",
+  "contract_address": "0xfc08e5bfebdcf7bb4cf5aafc29be03c1d53898f1",
+  "caller_address": "0x67c6697351ff4aec29cdbaabf2fbe3467cc254f8",
+  "func_name":"transfer(address,uint256)",
+  "params":"0x1be8e78d765a2e63339fc99a66320db73158a35a,100"
 }
diff --git a/proto/contract/rpc.proto 
b/service/tools/kv/api_tools/get_balance.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/kv/api_tools/get_balance.js
index 8df1dd40..cb8a5ec4 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/kv/api_tools/get_balance.js
@@ -17,36 +17,7 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"get_balance",
+  "address":"0x1be8e78d765a2e63339fc99a66320db73158a35a"
 }
diff --git a/proto/contract/rpc.proto 
b/service/tools/kv/api_tools/set_balance.js
similarity index 52%
copy from proto/contract/rpc.proto
copy to service/tools/kv/api_tools/set_balance.js
index 8df1dd40..dec5d357 100644
--- a/proto/contract/rpc.proto
+++ b/service/tools/kv/api_tools/set_balance.js
@@ -17,36 +17,8 @@
  * under the License.
  */
 
-syntax = "proto3";
-
-package resdb.contract;
-
-import "proto/contract/func_params.proto";
-import "proto/contract/contract.proto";
-import "proto/contract/account.proto";
-
-message Request {
-    enum CMD {
-        NONE = 0;
-        CREATE_ACCOUNT = 1; // deploy contract
-        DEPLOY = 2; // deploy contract
-        EXECUTE = 3; // execute contract
-        ADD_ADDRESS = 4; // add address
-    };
-
-    CMD cmd = 1;
-    string caller_address = 2;
-    optional DeployInfo deploy_info = 3;
-    optional string contract_address = 4;
-    optional Params func_params = 5;
-    optional string external_address = 6;
-}
-
-
-
-message Response {
-int32 ret = 1;
-optional Account account = 2;
-optional Contract contract = 3;
-optional string res = 4;
+{
+  "command":"set_balance",
+  "address":"0x1be8e78d765a2e63339fc99a66320db73158a35a",
+  "balance":"2000"
 }

Reply via email to