Skip to content

Commit

Permalink
[AccountAbstraction] Implement SessionKey (#582)
Browse files Browse the repository at this point in the history
  • Loading branch information
jolestar authored Aug 8, 2023
1 parent badfa31 commit c669256
Show file tree
Hide file tree
Showing 34 changed files with 1,502 additions and 294 deletions.
114 changes: 74 additions & 40 deletions crates/rooch-executor/src/actor/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use rooch_framework::bindings::transaction_validator::TransactionValidator;
use rooch_genesis::RoochGenesis;
use rooch_store::RoochStore;
use rooch_types::address::MultiChainAddress;
use rooch_types::framework::auth_validator::TxValidateResult;
use rooch_types::transaction::AuthenticatorInfo;
use rooch_types::transaction::{AbstractTransaction, TransactionSequenceMapping};

Expand Down Expand Up @@ -82,12 +83,18 @@ impl ExecutorActor {
let result = self.validate_authenticator(&moveos_tx.ctx, authenticator);

match result {
Ok((pre_execute_functions, post_execute_functions)) => {
Ok((tx_validate_result, pre_execute_functions, post_execute_functions)) => {
// Add the original multichain address to the context
moveos_tx
.ctx
.add(multi_chain_address_sender)
.expect("add sender to context failed");
// Add the tx_validate_result to the context
moveos_tx
.ctx
.add(tx_validate_result)
.expect("add tx_validate_result failed");

moveos_tx.append_pre_execute_functions(pre_execute_functions);
moveos_tx.append_post_execute_functions(post_execute_functions);
Ok(self.moveos.verify(moveos_tx)?)
Expand All @@ -107,54 +114,54 @@ impl ExecutorActor {
&self,
ctx: &TxContext,
authenticator: AuthenticatorInfo,
) -> Result<(Vec<FunctionCall>, Vec<FunctionCall>)> {
) -> Result<(TxValidateResult, Vec<FunctionCall>, Vec<FunctionCall>)> {
let tx_validator = self.moveos.as_module_bundle::<TransactionValidator>();
let auth_validator = tx_validator.validate(ctx, authenticator.clone())?;
let auth_validator_caller = AuthValidatorCaller::new(&self.moveos, auth_validator);
auth_validator_caller.validate(ctx, authenticator.authenticator.payload)?;
// pre_execute_function: TransactionValidator first, then AuthValidator
let pre_execute_functions = vec![
TransactionValidator::pre_execute_function_call(),
auth_validator_caller.pre_execute_function_call(),
];
// post_execute_function: AuthValidator first, then TransactionValidator
let post_execute_functions = vec![
auth_validator_caller.post_execute_function_call(),
TransactionValidator::post_execute_function_call(),
];
Ok((pre_execute_functions, post_execute_functions))
let tx_validate_result = tx_validator.validate(ctx, authenticator.clone())?;
let auth_validator_option = tx_validate_result.auth_validator();
match auth_validator_option {
Some(auth_validator) => {
let auth_validator_caller = AuthValidatorCaller::new(&self.moveos, auth_validator);
auth_validator_caller.validate(ctx, authenticator.authenticator.payload)?;
// pre_execute_function: TransactionValidator first, then AuthValidator
let pre_execute_functions = vec![
TransactionValidator::pre_execute_function_call(),
auth_validator_caller.pre_execute_function_call(),
];
// post_execute_function: AuthValidator first, then TransactionValidator
let post_execute_functions = vec![
auth_validator_caller.post_execute_function_call(),
TransactionValidator::post_execute_function_call(),
];
Ok((
tx_validate_result,
pre_execute_functions,
post_execute_functions,
))
}
None => {
let pre_execute_functions = vec![TransactionValidator::pre_execute_function_call()];
let post_execute_functions =
vec![TransactionValidator::post_execute_function_call()];
Ok((
tx_validate_result,
pre_execute_functions,
post_execute_functions,
))
}
}
}

pub fn get_rooch_store(&self) -> RoochStore {
self.rooch_store.clone()
}
}

impl Actor for ExecutorActor {}

#[async_trait]
impl<T> Handler<ValidateTransactionMessage<T>> for ExecutorActor
where
T: 'static + AbstractTransaction + Send + Sync,
{
async fn handle(
&mut self,
msg: ValidateTransactionMessage<T>,
_ctx: &mut ActorContext,
) -> Result<VerifiedMoveOSTransaction> {
self.validate(msg.tx)
pub fn moveos(&self) -> &MoveOS {
&self.moveos
}
}

#[async_trait]
impl Handler<ExecuteTransactionMessage> for ExecutorActor {
async fn handle(
&mut self,
msg: ExecuteTransactionMessage,
_ctx: &mut ActorContext,
) -> Result<ExecuteTransactionResult> {
let tx_hash = msg.tx.ctx.tx_hash();
let (state_root, output) = self.moveos.execute(msg.tx)?;
pub fn execute(&mut self, tx: VerifiedMoveOSTransaction) -> Result<ExecuteTransactionResult> {
let tx_hash = tx.ctx.tx_hash();
let (state_root, output) = self.moveos.execute_and_apply(tx)?;
let event_hashes: Vec<_> = output.events.iter().map(|e| e.hash()).collect();
let event_root = InMemoryAccumulator::from_leaves(event_hashes.as_slice()).root_hash();

Expand Down Expand Up @@ -182,6 +189,33 @@ impl Handler<ExecuteTransactionMessage> for ExecutorActor {
}
}

impl Actor for ExecutorActor {}

#[async_trait]
impl<T> Handler<ValidateTransactionMessage<T>> for ExecutorActor
where
T: 'static + AbstractTransaction + Send + Sync,
{
async fn handle(
&mut self,
msg: ValidateTransactionMessage<T>,
_ctx: &mut ActorContext,
) -> Result<VerifiedMoveOSTransaction> {
self.validate(msg.tx)
}
}

#[async_trait]
impl Handler<ExecuteTransactionMessage> for ExecutorActor {
async fn handle(
&mut self,
msg: ExecuteTransactionMessage,
_ctx: &mut ActorContext,
) -> Result<ExecuteTransactionResult> {
self.execute(msg.tx)
}
}

#[async_trait]
impl Handler<ExecuteViewFunctionMessage> for ExecutorActor {
async fn handle(
Expand Down
2 changes: 2 additions & 0 deletions crates/rooch-framework-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ rooch-framework = { workspace = true }
rooch-genesis = { workspace = true }
rooch-types = { workspace = true }
rooch-key = { workspace = true }
rooch-executor = { workspace = true }
rooch-store = { workspace = true }

[dev-dependencies]
rooch-integration-test-runner = { workspace = true }
Expand Down
36 changes: 23 additions & 13 deletions crates/rooch-framework-tests/src/binding_test.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use moveos::moveos::MoveOS;
use anyhow::{bail, Result};
use move_core_types::vm_status::KeptVMStatus;
use moveos_store::MoveOSStore;
use moveos_types::module_binding::{ModuleBundle, MoveFunctionCaller};
use rooch_genesis::RoochGenesis;
use rooch_executor::actor::executor::ExecutorActor;
use rooch_store::RoochStore;
use rooch_types::transaction::AbstractTransaction;

pub struct RustBindingTest {
moveos: MoveOS,
executor: ExecutorActor,
}

impl RustBindingTest {
pub fn new() -> Result<Self> {
let moveos_store = MoveOSStore::mock_moveos_store().unwrap();
let genesis: &RoochGenesis = &rooch_genesis::ROOCH_GENESIS;

let mut moveos = MoveOS::new(moveos_store, genesis.all_natives(), genesis.config.clone())?;
if moveos.state().is_genesis() {
moveos.init_genesis(genesis.genesis_txs())?;
}
Ok(Self { moveos })
let moveos_store = MoveOSStore::mock_moveos_store()?;
let rooch_store = RoochStore::mock_rooch_store();
let executor = ExecutorActor::new(moveos_store, rooch_store)?;
Ok(Self { executor })
}

pub fn as_module_bundle<'a, M: ModuleBundle<'a>>(&'a self) -> M {
self.moveos.as_module_bundle::<M>()
self.executor.moveos().as_module_bundle::<M>()
}

pub fn execute<T: AbstractTransaction>(&mut self, tx: T) -> Result<()> {
let verified_tx = self.executor.validate(tx)?;
let execute_result = self.executor.execute(verified_tx)?;
if execute_result.transaction_info.status != KeptVMStatus::Executed {
bail!(
"tx should success, error: {:?}",
execute_result.transaction_info.status
);
}
Ok(())
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use moveos_types::transaction::MoveAction;
use rooch_framework::bindings::empty::Empty;
use moveos_types::{module_binding::ModuleBundle, transaction::MoveAction};
use rooch_framework::{bindings::empty::Empty, ROOCH_FRAMEWORK_ADDRESS};
use rooch_key::keystore::{AccountKeystore, InMemKeystore};
use rooch_types::{
crypto::BuiltinScheme,
framework::session_key::SessionScope,
transaction::{rooch::RoochTransactionData, AbstractTransaction},
};

Expand Down Expand Up @@ -94,3 +95,46 @@ fn test_validate_schnorr() {
.validate(&move_tx.ctx, auth_info)
.unwrap();
}

#[test]
fn test_session_key_ed25519() {
let mut binding_test = binding_test::RustBindingTest::new().unwrap();

let keystore = InMemKeystore::new_ed25519_insecure_for_tests(1);
let sender = keystore.addresses()[0];
let sequence_number = 0;

let auth_key = vec![1u8; 32];
let session_scope = SessionScope::new(
ROOCH_FRAMEWORK_ADDRESS,
Empty::MODULE_NAME.as_str(),
Empty::EMPTY_FUNCTION_NAME.as_str(),
);
let expiration_time = 100;
let max_inactive_interval = 100;
let action =
rooch_framework::bindings::session_key::SessionKeyModule::create_session_key_action(
auth_key.clone(),
BuiltinScheme::Ed25519,
session_scope.clone(),
expiration_time,
max_inactive_interval,
);
let tx_data = RoochTransactionData::new(sender, sequence_number, action);
let tx = keystore
.sign_transaction(&sender, tx_data, BuiltinScheme::Ed25519)
.unwrap();
binding_test.execute(tx).unwrap();

let session_key_module =
binding_test.as_module_bundle::<rooch_framework::bindings::session_key::SessionKeyModule>();
let session_key_option = session_key_module
.get_session_key(sender.into(), auth_key)
.unwrap();
assert!(session_key_option.is_some(), "Session key not found");
let session_key = session_key_option.unwrap();
assert_eq!(session_key.scheme, BuiltinScheme::Ed25519.flag() as u64);
assert_eq!(session_key.scopes, vec![session_scope]);
assert_eq!(session_key.expiration_time, expiration_time);
assert_eq!(session_key.max_inactive_interval, max_inactive_interval);
}
1 change: 1 addition & 0 deletions crates/rooch-framework/doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ This is the reference documentation of the Rooch Framework.
- [`0x3::multi_ed25519_validator`](multi_ed25519_validator.md#0x3_multi_ed25519_validator)
- [`0x3::schnorr`](schnorr.md#0x3_schnorr)
- [`0x3::schnorr_validator`](schnorr_validator.md#0x3_schnorr_validator)
- [`0x3::session_key`](session_key.md#0x3_session_key)
- [`0x3::transaction_validator`](transaction_validator.md#0x3_transaction_validator)


Expand Down
3 changes: 2 additions & 1 deletion crates/rooch-framework/doc/account_authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Migrate their from the account module for simplyfying the account module.
<b>use</b> <a href="">0x1::vector</a>;
<b>use</b> <a href="">0x2::account_storage</a>;
<b>use</b> <a href="">0x2::storage_context</a>;
<b>use</b> <a href="auth_validator.md#0x3_auth_validator">0x3::auth_validator</a>;
<b>use</b> <a href="auth_validator_registry.md#0x3_auth_validator_registry">0x3::auth_validator_registry</a>;
</code></pre>

Expand Down Expand Up @@ -259,7 +260,7 @@ Return the authentication validator is installed for the account at <code>accoun

<pre><code><b>public</b> <b>fun</b> <a href="account_authentication.md#0x3_account_authentication_install_auth_validator">install_auth_validator</a>&lt;ValidatorType: store&gt;(ctx: &<b>mut</b> StorageContext, account_signer: &<a href="">signer</a>) {
<b>let</b> validator = <a href="auth_validator_registry.md#0x3_auth_validator_registry_borrow_validator_by_type">auth_validator_registry::borrow_validator_by_type</a>&lt;ValidatorType&gt;(ctx);
<b>let</b> validator_id = <a href="auth_validator_registry.md#0x3_auth_validator_registry_validator_id">auth_validator_registry::validator_id</a>(validator);
<b>let</b> validator_id = <a href="auth_validator.md#0x3_auth_validator_validator_id">auth_validator::validator_id</a>(validator);
<b>let</b> account_addr = <a href="_address_of">signer::address_of</a>(account_signer);

<b>assert</b>!(
Expand Down
Loading

0 comments on commit c669256

Please sign in to comment.