Skip to content

Commit

Permalink
add function execute_tx_locally
Browse files Browse the repository at this point in the history
  • Loading branch information
steelgeek091 committed Sep 22, 2024
1 parent 42b2b19 commit 72b6901
Show file tree
Hide file tree
Showing 18 changed files with 331 additions and 40 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/rooch-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ rooch-types = { workspace = true }
rooch-genesis = { workspace = true }
rooch-event = { workspace = true }
rooch-store = { workspace = true }
hex = "0.4.3"
1 change: 1 addition & 0 deletions crates/rooch-executor/src/actor/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ impl Message for ExecuteViewFunctionMessage {

#[derive(Debug, Serialize, Deserialize)]
pub struct StatesMessage {
pub state_root: Option<String>,
pub access_path: AccessPath,
}

Expand Down
10 changes: 9 additions & 1 deletion crates/rooch-executor/src/actor/reader_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use moveos_store::transaction_store::TransactionStore;
use moveos_store::MoveOSStore;
use moveos_types::function_return_value::AnnotatedFunctionResult;
use moveos_types::function_return_value::AnnotatedFunctionReturnValue;
use moveos_types::h256::H256;
use moveos_types::moveos_std::event::EventHandle;
use moveos_types::moveos_std::event::{AnnotatedEvent, Event};
use moveos_types::moveos_std::object::ObjectMeta;
Expand Down Expand Up @@ -146,7 +147,14 @@ impl Handler<StatesMessage> for ReaderExecutorActor {
msg: StatesMessage,
_ctx: &mut ActorContext,
) -> Result<Vec<Option<ObjectState>>, anyhow::Error> {
let resolver = RootObjectResolver::new(self.root.clone(), &self.moveos_store);
let resolver = if let Some(state_root_str) = msg.state_root {
let hex_bytes = hex::decode(state_root_str).expect("decode root state failed");
let state_root = H256::from_slice(hex_bytes.as_slice());
let root_object_meta = ObjectMeta::root_metadata(state_root, 55);
RootObjectResolver::new(root_object_meta, &self.moveos_store)
} else {
RootObjectResolver::new(self.root.clone(), &self.moveos_store)
};
resolver.get_states(msg.access_path)
}
}
Expand Down
20 changes: 15 additions & 5 deletions crates/rooch-executor/src/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,16 @@ impl ExecutorProxy {
.await?
}

pub async fn get_states(&self, access_path: AccessPath) -> Result<Vec<Option<ObjectState>>> {
pub async fn get_states(
&self,
state_root: Option<String>,
access_path: AccessPath,
) -> Result<Vec<Option<ObjectState>>> {
self.reader_actor
.send(StatesMessage { access_path })
.send(StatesMessage {
state_root,
access_path,
})
.await?
}

Expand Down Expand Up @@ -238,7 +245,7 @@ impl ExecutorProxy {
}

pub async fn chain_id(&self) -> Result<ChainID> {
self.get_states(AccessPath::object(ChainID::chain_id_object_id()))
self.get_states(None, AccessPath::object(ChainID::chain_id_object_id()))
.await?
.into_iter()
.next()
Expand All @@ -248,7 +255,7 @@ impl ExecutorProxy {
}

pub async fn bitcoin_network(&self) -> Result<BitcoinNetwork> {
self.get_states(AccessPath::object(BitcoinNetwork::object_id()))
self.get_states(None, AccessPath::object(BitcoinNetwork::object_id()))
.await?
.into_iter()
.next()
Expand All @@ -260,7 +267,10 @@ impl ExecutorProxy {
//TODO provide a trait to abstract the async state reader, elemiate the duplicated code bwteen RpcService and Client
pub async fn get_sequence_number(&self, address: AccountAddress) -> Result<u64> {
Ok(self
.get_states(AccessPath::object(Account::account_object_id(address)))
.get_states(
None,
AccessPath::object(Account::account_object_id(address)),
)
.await?
.pop()
.flatten()
Expand Down
6 changes: 6 additions & 0 deletions crates/rooch-open-rpc-spec/schemas/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,12 @@
"name": "rooch_getStates",
"description": "Get the states by access_path If the StateOptions.decode is true, the state is decoded and the decoded value is returned in the response.",
"params": [
{
"name": "state_root",
"schema": {
"type": "string"
}
},
{
"name": "access_path",
"required": true,
Expand Down
3 changes: 2 additions & 1 deletion crates/rooch-rpc-api/src/api/rooch_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pub trait RoochAPI {
#[method(name = "getStates")]
async fn get_states(
&self,
state_root: Option<String>,
access_path: AccessPathView,
state_option: Option<StateOptions>,
) -> RpcResult<Vec<Option<ObjectStateView>>>;
Expand Down Expand Up @@ -90,7 +91,7 @@ pub trait RoochAPI {
let key_states = field_key.into_iter().map(FieldKey::from).collect();
let access_path_view =
AccessPathView::from(AccessPath::fields(object_id.into(), key_states));
self.get_states(access_path_view, state_option).await
self.get_states(None, access_path_view, state_option).await
}

/// List Object Fields via ObjectID.
Expand Down
123 changes: 118 additions & 5 deletions crates/rooch-rpc-client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use anyhow::{ensure, Error, Result};
use jsonrpsee::core::client::ClientT;
use jsonrpsee::http_client::{HttpClient, HttpClientBuilder};
use move_core_types::language_storage::ModuleId;
use move_core_types::account_address::AccountAddress;
use move_core_types::language_storage::{ModuleId, StructTag};
use move_core_types::metadata::Metadata;
use move_core_types::resolver::ModuleResolver;
use move_core_types::resolver::{ModuleResolver, ResourceResolver};
use moveos_types::access_path::AccessPath;
use moveos_types::h256::H256;
use moveos_types::move_std::string::MoveString;
use moveos_types::moveos_std::account::Account;
use moveos_types::moveos_std::move_module::MoveModule;
use moveos_types::state::ObjectState;
use moveos_types::moveos_std::object::{ObjectID, ObjectMeta, RawField};
use moveos_types::state::{FieldKey, MoveType, ObjectState};
use moveos_types::state_resolver::{StateKV, StateResolver, StatelessResolver};
use moveos_types::{
function_return_value::FunctionResult, module_binding::MoveFunctionCaller,
moveos_std::tx_context::TxContext, transaction::FunctionCall,
Expand Down Expand Up @@ -109,7 +114,7 @@ impl ModuleResolver for &Client {
fn get_module(&self, id: &ModuleId) -> Result<Option<Vec<u8>>> {
tokio::task::block_in_place(|| {
Handle::current().block_on(async {
let mut states = self.rooch.get_states(AccessPath::module(id)).await?;
let mut states = self.rooch.get_states(None, AccessPath::module(id)).await?;
states
.pop()
.flatten()
Expand All @@ -123,3 +128,111 @@ impl ModuleResolver for &Client {
})
}
}

#[derive(Clone)]
pub struct ClientResolver {
root: ObjectMeta,
client: Client,
}

impl ClientResolver {
pub fn new(client: Client, root: ObjectMeta) -> Self {
Self { root, client }
}
}

impl ResourceResolver for ClientResolver {
fn get_resource_with_metadata(
&self,
address: &AccountAddress,
resource_tag: &StructTag,
_metadata: &[Metadata],
) -> std::result::Result<(Option<Vec<u8>>, usize), Error> {
let account_object_id = Account::account_object_id(*address);

let key = FieldKey::derive_resource_key(resource_tag);
let result = self
.get_field(&account_object_id, &key)?
.map(|s| {
ensure!(
s.match_dynamic_field_type(MoveString::type_tag(), resource_tag.clone().into()),
"Resource type mismatch, expected field value type: {:?}, actual: {:?}",
resource_tag,
s.object_type()
);
let field = RawField::parse_resource_field(&s.value, resource_tag.clone().into())?;
Ok(field.value)
})
.transpose();

match result {
Ok(opt) => {
if let Some(data) = opt {
Ok((Some(data), 0))
} else {
Ok((None, 0))
}
}
Err(err) => Err(err),
}
}
}

impl ModuleResolver for ClientResolver {
fn get_module_metadata(&self, _module_id: &ModuleId) -> Vec<Metadata> {
vec![]
}

fn get_module(&self, id: &ModuleId) -> std::result::Result<Option<Vec<u8>>, Error> {
(&self.client).get_module(id)
}
}

impl StatelessResolver for ClientResolver {
fn get_field_at(&self, state_root: H256, key: &FieldKey) -> Result<Option<ObjectState>, Error> {
tokio::task::block_in_place(|| {
Handle::current().block_on(async {
let access_path = AccessPath::object(ObjectID::new(key.0));
let mut object_state_view_list = self
.client
.rooch
.get_states(Some(hex::encode(state_root.0.as_slice())), access_path)
.await?;
Ok(object_state_view_list.pop().flatten().map(|state_view| {
let v: ObjectState = state_view.into();
v
}))
})
})
}

fn list_fields_at(
&self,
state_root: H256,
cursor: Option<FieldKey>,
limit: usize,
) -> Result<Vec<StateKV>> {
tokio::task::block_in_place(|| {
Handle::current().block_on(async {
let object_id = ObjectID::new(state_root.0);
let field_cursor = cursor.map(|field_key| field_key.to_hex_literal());
let fields_states = self
.client
.rooch
.list_field_states(object_id.into(), field_cursor, Some(limit as u64), None)
.await?;
Ok(fields_states
.data
.iter()
.map(|item| StateKV::from((item.field_key.into(), item.state.clone().into())))
.collect())
})
})
}
}

impl StateResolver for ClientResolver {
fn root(&self) -> &ObjectMeta {
&self.root
}
}
18 changes: 13 additions & 5 deletions crates/rooch-rpc-client/src/rooch_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,24 @@ impl RoochRpcClient {

pub async fn get_states(
&self,
state_root: Option<String>,
access_path: AccessPath,
) -> Result<Vec<Option<ObjectStateView>>> {
Ok(self.http.get_states(access_path.into(), None).await?)
Ok(self
.http
.get_states(state_root, access_path.into(), None)
.await?)
}

pub async fn get_decoded_states(
&self,
state_root: Option<String>,
access_path: AccessPath,
) -> Result<Vec<Option<ObjectStateView>>> {
Ok(self
.http
.get_states(
state_root,
access_path.into(),
Some(StateOptions::default().decode(true)),
)
Expand All @@ -114,6 +120,7 @@ impl RoochRpcClient {
Ok(self
.http
.get_states(
None,
access_path.into(),
Some(StateOptions::default().decode(true).show_display(true)),
)
Expand Down Expand Up @@ -166,9 +173,10 @@ impl RoochRpcClient {

pub async fn get_sequence_number(&self, sender: RoochAddress) -> Result<u64> {
Ok(self
.get_states(AccessPath::object(Account::account_object_id(
sender.into(),
)))
.get_states(
None,
AccessPath::object(Account::account_object_id(sender.into())),
)
.await?
.pop()
.flatten()
Expand Down Expand Up @@ -373,7 +381,7 @@ impl RoochRpcClient {
account: RoochAddress,
) -> Result<Option<T>> {
let access_path = AccessPath::resource(account.into(), T::struct_tag());
let mut states = self.get_states(access_path).await?;
let mut states = self.get_states(None, access_path).await?;
let state = states.pop().flatten();
if let Some(state) = state {
let state = ObjectState::from(state);
Expand Down
4 changes: 2 additions & 2 deletions crates/rooch-rpc-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,8 +429,8 @@ pub async fn run_start_server(opt: RoochOpt, server_opt: ServerOpt) -> Result<Se
// and thus we need a static reference to it
let governor_conf = Arc::new(
GovernorConfigBuilder::default()
.per_second(opt.traffic_per_second.unwrap_or(2))
.burst_size(opt.traffic_burst_size.unwrap_or(10))
.per_second(opt.traffic_per_second.unwrap_or(20000))
.burst_size(opt.traffic_burst_size.unwrap_or(1000))
.use_headers()
.error_handler(move |error1| ErrorHandler::default().0(error1))
.finish()
Expand Down
Loading

0 comments on commit 72b6901

Please sign in to comment.