Skip to content

Commit 72b6901

Browse files
committed
add function execute_tx_locally
1 parent 42b2b19 commit 72b6901

File tree

18 files changed

+331
-40
lines changed

18 files changed

+331
-40
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rooch-executor/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,4 @@ rooch-types = { workspace = true }
3535
rooch-genesis = { workspace = true }
3636
rooch-event = { workspace = true }
3737
rooch-store = { workspace = true }
38+
hex = "0.4.3"

crates/rooch-executor/src/actor/messages.rs

+1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ impl Message for ExecuteViewFunctionMessage {
9999

100100
#[derive(Debug, Serialize, Deserialize)]
101101
pub struct StatesMessage {
102+
pub state_root: Option<String>,
102103
pub access_path: AccessPath,
103104
}
104105

crates/rooch-executor/src/actor/reader_executor.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use moveos_store::transaction_store::TransactionStore;
2121
use moveos_store::MoveOSStore;
2222
use moveos_types::function_return_value::AnnotatedFunctionResult;
2323
use moveos_types::function_return_value::AnnotatedFunctionReturnValue;
24+
use moveos_types::h256::H256;
2425
use moveos_types::moveos_std::event::EventHandle;
2526
use moveos_types::moveos_std::event::{AnnotatedEvent, Event};
2627
use moveos_types::moveos_std::object::ObjectMeta;
@@ -146,7 +147,14 @@ impl Handler<StatesMessage> for ReaderExecutorActor {
146147
msg: StatesMessage,
147148
_ctx: &mut ActorContext,
148149
) -> Result<Vec<Option<ObjectState>>, anyhow::Error> {
149-
let resolver = RootObjectResolver::new(self.root.clone(), &self.moveos_store);
150+
let resolver = if let Some(state_root_str) = msg.state_root {
151+
let hex_bytes = hex::decode(state_root_str).expect("decode root state failed");
152+
let state_root = H256::from_slice(hex_bytes.as_slice());
153+
let root_object_meta = ObjectMeta::root_metadata(state_root, 55);
154+
RootObjectResolver::new(root_object_meta, &self.moveos_store)
155+
} else {
156+
RootObjectResolver::new(self.root.clone(), &self.moveos_store)
157+
};
150158
resolver.get_states(msg.access_path)
151159
}
152160
}

crates/rooch-executor/src/proxy/mod.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,16 @@ impl ExecutorProxy {
116116
.await?
117117
}
118118

119-
pub async fn get_states(&self, access_path: AccessPath) -> Result<Vec<Option<ObjectState>>> {
119+
pub async fn get_states(
120+
&self,
121+
state_root: Option<String>,
122+
access_path: AccessPath,
123+
) -> Result<Vec<Option<ObjectState>>> {
120124
self.reader_actor
121-
.send(StatesMessage { access_path })
125+
.send(StatesMessage {
126+
state_root,
127+
access_path,
128+
})
122129
.await?
123130
}
124131

@@ -238,7 +245,7 @@ impl ExecutorProxy {
238245
}
239246

240247
pub async fn chain_id(&self) -> Result<ChainID> {
241-
self.get_states(AccessPath::object(ChainID::chain_id_object_id()))
248+
self.get_states(None, AccessPath::object(ChainID::chain_id_object_id()))
242249
.await?
243250
.into_iter()
244251
.next()
@@ -248,7 +255,7 @@ impl ExecutorProxy {
248255
}
249256

250257
pub async fn bitcoin_network(&self) -> Result<BitcoinNetwork> {
251-
self.get_states(AccessPath::object(BitcoinNetwork::object_id()))
258+
self.get_states(None, AccessPath::object(BitcoinNetwork::object_id()))
252259
.await?
253260
.into_iter()
254261
.next()
@@ -260,7 +267,10 @@ impl ExecutorProxy {
260267
//TODO provide a trait to abstract the async state reader, elemiate the duplicated code bwteen RpcService and Client
261268
pub async fn get_sequence_number(&self, address: AccountAddress) -> Result<u64> {
262269
Ok(self
263-
.get_states(AccessPath::object(Account::account_object_id(address)))
270+
.get_states(
271+
None,
272+
AccessPath::object(Account::account_object_id(address)),
273+
)
264274
.await?
265275
.pop()
266276
.flatten()

crates/rooch-open-rpc-spec/schemas/openrpc.json

+6
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,12 @@
416416
"name": "rooch_getStates",
417417
"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.",
418418
"params": [
419+
{
420+
"name": "state_root",
421+
"schema": {
422+
"type": "string"
423+
}
424+
},
419425
{
420426
"name": "access_path",
421427
"required": true,

crates/rooch-rpc-api/src/api/rooch_api.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub trait RoochAPI {
5656
#[method(name = "getStates")]
5757
async fn get_states(
5858
&self,
59+
state_root: Option<String>,
5960
access_path: AccessPathView,
6061
state_option: Option<StateOptions>,
6162
) -> RpcResult<Vec<Option<ObjectStateView>>>;
@@ -90,7 +91,7 @@ pub trait RoochAPI {
9091
let key_states = field_key.into_iter().map(FieldKey::from).collect();
9192
let access_path_view =
9293
AccessPathView::from(AccessPath::fields(object_id.into(), key_states));
93-
self.get_states(access_path_view, state_option).await
94+
self.get_states(None, access_path_view, state_option).await
9495
}
9596

9697
/// List Object Fields via ObjectID.

crates/rooch-rpc-client/src/lib.rs

+118-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
// Copyright (c) RoochNetwork
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use anyhow::Result;
4+
use anyhow::{ensure, Error, Result};
55
use jsonrpsee::core::client::ClientT;
66
use jsonrpsee::http_client::{HttpClient, HttpClientBuilder};
7-
use move_core_types::language_storage::ModuleId;
7+
use move_core_types::account_address::AccountAddress;
8+
use move_core_types::language_storage::{ModuleId, StructTag};
89
use move_core_types::metadata::Metadata;
9-
use move_core_types::resolver::ModuleResolver;
10+
use move_core_types::resolver::{ModuleResolver, ResourceResolver};
1011
use moveos_types::access_path::AccessPath;
12+
use moveos_types::h256::H256;
1113
use moveos_types::move_std::string::MoveString;
14+
use moveos_types::moveos_std::account::Account;
1215
use moveos_types::moveos_std::move_module::MoveModule;
13-
use moveos_types::state::ObjectState;
16+
use moveos_types::moveos_std::object::{ObjectID, ObjectMeta, RawField};
17+
use moveos_types::state::{FieldKey, MoveType, ObjectState};
18+
use moveos_types::state_resolver::{StateKV, StateResolver, StatelessResolver};
1419
use moveos_types::{
1520
function_return_value::FunctionResult, module_binding::MoveFunctionCaller,
1621
moveos_std::tx_context::TxContext, transaction::FunctionCall,
@@ -109,7 +114,7 @@ impl ModuleResolver for &Client {
109114
fn get_module(&self, id: &ModuleId) -> Result<Option<Vec<u8>>> {
110115
tokio::task::block_in_place(|| {
111116
Handle::current().block_on(async {
112-
let mut states = self.rooch.get_states(AccessPath::module(id)).await?;
117+
let mut states = self.rooch.get_states(None, AccessPath::module(id)).await?;
113118
states
114119
.pop()
115120
.flatten()
@@ -123,3 +128,111 @@ impl ModuleResolver for &Client {
123128
})
124129
}
125130
}
131+
132+
#[derive(Clone)]
133+
pub struct ClientResolver {
134+
root: ObjectMeta,
135+
client: Client,
136+
}
137+
138+
impl ClientResolver {
139+
pub fn new(client: Client, root: ObjectMeta) -> Self {
140+
Self { root, client }
141+
}
142+
}
143+
144+
impl ResourceResolver for ClientResolver {
145+
fn get_resource_with_metadata(
146+
&self,
147+
address: &AccountAddress,
148+
resource_tag: &StructTag,
149+
_metadata: &[Metadata],
150+
) -> std::result::Result<(Option<Vec<u8>>, usize), Error> {
151+
let account_object_id = Account::account_object_id(*address);
152+
153+
let key = FieldKey::derive_resource_key(resource_tag);
154+
let result = self
155+
.get_field(&account_object_id, &key)?
156+
.map(|s| {
157+
ensure!(
158+
s.match_dynamic_field_type(MoveString::type_tag(), resource_tag.clone().into()),
159+
"Resource type mismatch, expected field value type: {:?}, actual: {:?}",
160+
resource_tag,
161+
s.object_type()
162+
);
163+
let field = RawField::parse_resource_field(&s.value, resource_tag.clone().into())?;
164+
Ok(field.value)
165+
})
166+
.transpose();
167+
168+
match result {
169+
Ok(opt) => {
170+
if let Some(data) = opt {
171+
Ok((Some(data), 0))
172+
} else {
173+
Ok((None, 0))
174+
}
175+
}
176+
Err(err) => Err(err),
177+
}
178+
}
179+
}
180+
181+
impl ModuleResolver for ClientResolver {
182+
fn get_module_metadata(&self, _module_id: &ModuleId) -> Vec<Metadata> {
183+
vec![]
184+
}
185+
186+
fn get_module(&self, id: &ModuleId) -> std::result::Result<Option<Vec<u8>>, Error> {
187+
(&self.client).get_module(id)
188+
}
189+
}
190+
191+
impl StatelessResolver for ClientResolver {
192+
fn get_field_at(&self, state_root: H256, key: &FieldKey) -> Result<Option<ObjectState>, Error> {
193+
tokio::task::block_in_place(|| {
194+
Handle::current().block_on(async {
195+
let access_path = AccessPath::object(ObjectID::new(key.0));
196+
let mut object_state_view_list = self
197+
.client
198+
.rooch
199+
.get_states(Some(hex::encode(state_root.0.as_slice())), access_path)
200+
.await?;
201+
Ok(object_state_view_list.pop().flatten().map(|state_view| {
202+
let v: ObjectState = state_view.into();
203+
v
204+
}))
205+
})
206+
})
207+
}
208+
209+
fn list_fields_at(
210+
&self,
211+
state_root: H256,
212+
cursor: Option<FieldKey>,
213+
limit: usize,
214+
) -> Result<Vec<StateKV>> {
215+
tokio::task::block_in_place(|| {
216+
Handle::current().block_on(async {
217+
let object_id = ObjectID::new(state_root.0);
218+
let field_cursor = cursor.map(|field_key| field_key.to_hex_literal());
219+
let fields_states = self
220+
.client
221+
.rooch
222+
.list_field_states(object_id.into(), field_cursor, Some(limit as u64), None)
223+
.await?;
224+
Ok(fields_states
225+
.data
226+
.iter()
227+
.map(|item| StateKV::from((item.field_key.into(), item.state.clone().into())))
228+
.collect())
229+
})
230+
})
231+
}
232+
}
233+
234+
impl StateResolver for ClientResolver {
235+
fn root(&self) -> &ObjectMeta {
236+
&self.root
237+
}
238+
}

crates/rooch-rpc-client/src/rooch_client.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -89,18 +89,24 @@ impl RoochRpcClient {
8989

9090
pub async fn get_states(
9191
&self,
92+
state_root: Option<String>,
9293
access_path: AccessPath,
9394
) -> Result<Vec<Option<ObjectStateView>>> {
94-
Ok(self.http.get_states(access_path.into(), None).await?)
95+
Ok(self
96+
.http
97+
.get_states(state_root, access_path.into(), None)
98+
.await?)
9599
}
96100

97101
pub async fn get_decoded_states(
98102
&self,
103+
state_root: Option<String>,
99104
access_path: AccessPath,
100105
) -> Result<Vec<Option<ObjectStateView>>> {
101106
Ok(self
102107
.http
103108
.get_states(
109+
state_root,
104110
access_path.into(),
105111
Some(StateOptions::default().decode(true)),
106112
)
@@ -114,6 +120,7 @@ impl RoochRpcClient {
114120
Ok(self
115121
.http
116122
.get_states(
123+
None,
117124
access_path.into(),
118125
Some(StateOptions::default().decode(true).show_display(true)),
119126
)
@@ -166,9 +173,10 @@ impl RoochRpcClient {
166173

167174
pub async fn get_sequence_number(&self, sender: RoochAddress) -> Result<u64> {
168175
Ok(self
169-
.get_states(AccessPath::object(Account::account_object_id(
170-
sender.into(),
171-
)))
176+
.get_states(
177+
None,
178+
AccessPath::object(Account::account_object_id(sender.into())),
179+
)
172180
.await?
173181
.pop()
174182
.flatten()
@@ -373,7 +381,7 @@ impl RoochRpcClient {
373381
account: RoochAddress,
374382
) -> Result<Option<T>> {
375383
let access_path = AccessPath::resource(account.into(), T::struct_tag());
376-
let mut states = self.get_states(access_path).await?;
384+
let mut states = self.get_states(None, access_path).await?;
377385
let state = states.pop().flatten();
378386
if let Some(state) = state {
379387
let state = ObjectState::from(state);

crates/rooch-rpc-server/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,8 @@ pub async fn run_start_server(opt: RoochOpt, server_opt: ServerOpt) -> Result<Se
429429
// and thus we need a static reference to it
430430
let governor_conf = Arc::new(
431431
GovernorConfigBuilder::default()
432-
.per_second(opt.traffic_per_second.unwrap_or(2))
433-
.burst_size(opt.traffic_burst_size.unwrap_or(10))
432+
.per_second(opt.traffic_per_second.unwrap_or(20000))
433+
.burst_size(opt.traffic_burst_size.unwrap_or(1000))
434434
.use_headers()
435435
.error_handler(move |error1| ErrorHandler::default().0(error1))
436436
.finish()

0 commit comments

Comments
 (0)