diff --git a/crates/rooch-rpc-api/src/jsonrpc_types/account_sign_view.rs b/crates/rooch-rpc-api/src/jsonrpc_types/account_sign_view.rs index fcb3226cc..fbb9b9515 100644 --- a/crates/rooch-rpc-api/src/jsonrpc_types/account_sign_view.rs +++ b/crates/rooch-rpc-api/src/jsonrpc_types/account_sign_view.rs @@ -1,46 +1,18 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 +use rooch_types::{crypto::Signature, framework::auth_payload::AuthPayload}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use super::BytesView; - #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct AccountSignView { - pub msg: String, - pub payload: AuthPayloadView, -} - -#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] -pub struct AuthPayloadView { - pub signature: BytesView, - pub message_prefix: BytesView, - pub message_info: BytesView, - pub public_key: BytesView, - pub from_address: String, + pub signature: Signature, + pub payload: AuthPayload, } impl AccountSignView { - pub fn new(msg: String, payload: AuthPayloadView) -> Self { - Self { msg, payload } - } -} - -impl AuthPayloadView { - pub fn new( - signature: BytesView, - message_prefix: BytesView, - message_info: BytesView, - public_key: BytesView, - from_address: String, - ) -> Self { - Self { - signature, - message_prefix, - message_info, - public_key, - from_address, - } + pub fn new(signature: Signature, payload: AuthPayload) -> Self { + Self { signature, payload } } } diff --git a/crates/rooch-types/src/framework/auth_payload.rs b/crates/rooch-types/src/framework/auth_payload.rs index 85dd07307..30ffd4c5b 100644 --- a/crates/rooch-types/src/framework/auth_payload.rs +++ b/crates/rooch-types/src/framework/auth_payload.rs @@ -18,6 +18,7 @@ use moveos_types::{ h256::{sha2_256_of, H256}, state::{MoveStructState, MoveStructType}, }; +use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::io; @@ -94,7 +95,7 @@ impl Decodable for SignData { } } -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] pub struct AuthPayload { // Message signature pub signature: Vec, diff --git a/crates/rooch/src/commands/account/commands/sign.rs b/crates/rooch/src/commands/account/commands/sign.rs index 00549a3f0..dcfc5b155 100644 --- a/crates/rooch/src/commands/account/commands/sign.rs +++ b/crates/rooch/src/commands/account/commands/sign.rs @@ -1,21 +1,19 @@ // Copyright (c) RoochNetwork // SPDX-License-Identifier: Apache-2.0 -use crate::cli_types::{CommandAction, WalletContextOptions}; +use crate::cli_types::{CommandAction, TransactionOptions, WalletContextOptions}; +use anyhow::Result; use async_trait::async_trait; use clap::Parser; -use hex::ToHex; -use moveos_types::state::MoveState; +use move_command_line_common::types::ParsedStructType; +use move_core_types::language_storage::TypeTag; +use moveos_types::transaction::MoveAction; use rooch_key::keystore::account_keystore::AccountKeystore; -use rooch_rpc_api::jsonrpc_types::{ - account_sign_view::{AccountSignView, AuthPayloadView}, - BytesView, -}; use rooch_types::{ - address::ParsedAddress, - error::{RoochError, RoochResult}, + error::RoochResult, + framework::auth_payload::{AuthPayload, SignData}, + function_arg::{parse_function_arg, FunctionArg, ParsedFunctionId}, }; -use std::str::FromStr; /// Sign an msg with current account private key (sign_hashed) /// @@ -23,52 +21,80 @@ use std::str::FromStr; /// --address to export only one address with a private key. #[derive(Debug, Parser)] pub struct SignCommand { - #[clap(short = 'a', long = "address", value_parser=ParsedAddress::parse, default_value = "")] - address: ParsedAddress, + /// Function name as `
::::` + /// Example: `0x42::message::set_message`, `rooch_framework::empty::empty` + #[clap(long, required = true)] + pub function: ParsedFunctionId, + + /// TypeTag arguments separated by spaces. + /// + /// Example: `0x1::M::T1 0x1::M::T2 rooch_framework::empty::Empty` + #[clap( + long = "type-args", + value_parser=ParsedStructType::parse, + )] + pub type_args: Vec, + + /// Arguments combined with their type separated by spaces. + /// + /// Supported types [u8, u16, u32, u64, u128, u256, bool, object_id, string, address, vector] + /// + /// Example: `address:0x1 bool:true u8:0 u256:1234 'vector:a,b,c,d'` + /// address and uint can be written in short form like `@0x1 1u8 4123u256`. + #[clap(long = "args", value_parser=parse_function_arg)] + pub args: Vec, + + #[clap(flatten)] + tx_options: TransactionOptions, + #[clap(flatten)] pub context_options: WalletContextOptions, /// Return command outputs in json format #[clap(long, default_value = "false")] json: bool, - - /// Msg command will sign - #[clap(long, default_value = "")] - msg: String, } #[async_trait] -impl CommandAction> for SignCommand { - async fn execute(self) -> RoochResult> { +impl CommandAction> for SignCommand { + async fn execute(self) -> RoochResult> { let context = self.context_options.build_require_password()?; let password = context.get_password(); + let address_mapping = context.address_mapping(); + let sender = context.resolve_address(self.tx_options.sender)?.into(); + let kp = context.keystore.get_key_pair(&sender, password)?; + let bitcoin_address = kp.public().bitcoin_address()?; + let max_gas_amount = self.tx_options.max_gas_amount; - let mapping = context.address_mapping(); - let address = self.address.into_rooch_address(&mapping).map_err(|e| { - RoochError::CommandArgumentError(format!("Invalid Rooch address String: {}", e)) - })?; - - let signature = context.keystore.sign_hashed( - &address, - &self.msg.clone().to_bytes(), - password.clone(), - )?; - - let kp = context.keystore.get_key_pair(&address, password)?; + let function_id = self.function.into_function_id(&address_mapping)?; + let args = self + .args + .into_iter() + .map(|arg| arg.into_bytes(&address_mapping)) + .collect::>>()?; + let type_args = self + .type_args + .into_iter() + .map(|tag| { + Ok(TypeTag::Struct(Box::new( + tag.into_struct_tag(&address_mapping)?, + ))) + }) + .collect::>>()?; + let action = MoveAction::new_function_call(function_id, type_args, args); - let auth_payload = AuthPayloadView::new( - BytesView::from(signature.as_ref().to_vec()), - BytesView::from_str("Bitcoin Signed Message:\n")?, - BytesView::from_str("Rooch Transaction:\n")?, - BytesView::from(kp.public().as_ref().to_vec()), - address.clone().to_bech32(), - ); + let tx_data = context + .build_tx_data(sender, action, max_gas_amount) + .await?; + let sign_data = SignData::new_with_default(&tx_data); + let data_hash = sign_data.data_hash(); + let signature = kp.sign(data_hash.as_bytes()); + let auth_payload = AuthPayload::new(sign_data, signature, bitcoin_address.to_string()); if self.json { - Ok(Some(AccountSignView::new(self.msg.clone(), auth_payload))) + Ok(Some(auth_payload)) } else { - println!("Msg you input : {}", &self.msg); - println!("Signature : {}", signature.encode_hex::()); + println!("Auth Payload: {:?}", auth_payload); Ok(None) } } diff --git a/crates/rooch/src/commands/account/commands/verify.rs b/crates/rooch/src/commands/account/commands/verify.rs index c25a93f48..a20084dd4 100644 --- a/crates/rooch/src/commands/account/commands/verify.rs +++ b/crates/rooch/src/commands/account/commands/verify.rs @@ -9,15 +9,15 @@ use rooch_key::keystore::account_keystore::AccountKeystore; use rooch_rpc_api::jsonrpc_types::account_sign_view::AccountSignView; use rooch_types::error::{RoochError, RoochResult}; -/// Sign an msg with current account private key (sign_hashed) +/// Verify a signed message /// -/// This operation must be specified with -a or -/// --address to export only one address with a private key. +/// This operation must be specified with -m, or +/// --message to verify the signed message #[derive(Debug, Parser)] pub struct VerifyCommand { - /// signature that will be verified - #[clap(long, required = true)] - signature: String, + /// the message to be verified + #[clap(short = 'm', long, required = true)] + message: String, #[clap(flatten)] pub context_options: WalletContextOptions, @@ -34,14 +34,8 @@ impl CommandAction> for VerifyCommand { let password = context.get_password(); let mapping = context.address_mapping(); - let addrss = self.signature.into_rooch_address(&mapping).map_err(|e| { - RoochError::CommandArgumentError(format!("Invalid Rooch address String: {}", e)) - })?; - - let mut msg_body = Vec::::new(); - msg_body.copy_from_slice(&auth_payload.message_prefix); - msg_body.copy_from_slice(&self.msg.clone().into_bytes()); + self.message; let signature = context.keystore.sign_hashed(&addrss, &msg_body, password)?; if self.json {