From 1e63c44e8a3be0c41d70db1c2071e74050429cf4 Mon Sep 17 00:00:00 2001 From: Feliciss <10203-feliciss@users.noreply.0xacab.org> Date: Tue, 3 Sep 2024 21:38:32 +0900 Subject: [PATCH] [gh-2381] modify the sign command output as msg and auth payload. --- .../src/jsonrpc_types/account_sign_view.rs | 35 ++++++++++- .../src/commands/account/commands/mod.rs | 1 + .../src/commands/account/commands/sign.rs | 41 ++++++------- .../src/commands/account/commands/verify.rs | 58 +++++++++++++++++++ crates/rooch/src/commands/account/mod.rs | 4 +- 5 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 crates/rooch/src/commands/account/commands/verify.rs 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 2fd5c0bbaf..fcb3226ccd 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 @@ -4,14 +4,43 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use super::BytesView; + #[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)] pub struct AccountSignView { pub msg: String, - pub signature: 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, } impl AccountSignView { - pub fn new(msg: String, signature: String) -> Self { - Self { msg, signature } + 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, + } } } diff --git a/crates/rooch/src/commands/account/commands/mod.rs b/crates/rooch/src/commands/account/commands/mod.rs index 4fa2ac3f24..87d31ac5fd 100644 --- a/crates/rooch/src/commands/account/commands/mod.rs +++ b/crates/rooch/src/commands/account/commands/mod.rs @@ -11,3 +11,4 @@ pub mod nullify; pub mod sign; pub mod switch; pub mod transfer; +pub mod verify; diff --git a/crates/rooch/src/commands/account/commands/sign.rs b/crates/rooch/src/commands/account/commands/sign.rs index ce31aca0e9..00549a3f03 100644 --- a/crates/rooch/src/commands/account/commands/sign.rs +++ b/crates/rooch/src/commands/account/commands/sign.rs @@ -5,16 +5,17 @@ use crate::cli_types::{CommandAction, WalletContextOptions}; use async_trait::async_trait; use clap::Parser; use hex::ToHex; +use moveos_types::state::MoveState; use rooch_key::keystore::account_keystore::AccountKeystore; -use rooch_rpc_api::jsonrpc_types::account_sign_view::AccountSignView; +use rooch_rpc_api::jsonrpc_types::{ + account_sign_view::{AccountSignView, AuthPayloadView}, + BytesView, +}; use rooch_types::{ address::ParsedAddress, error::{RoochError, RoochResult}, }; - -struct AuthPayload { - message_prefix: Vec, -} +use std::str::FromStr; /// Sign an msg with current account private key (sign_hashed) /// @@ -43,28 +44,28 @@ impl CommandAction> for SignCommand { let password = context.get_password(); let mapping = context.address_mapping(); - let addrss = self.address.into_rooch_address(&mapping).map_err(|e| { + let address = self.address.into_rooch_address(&mapping).map_err(|e| { RoochError::CommandArgumentError(format!("Invalid Rooch address String: {}", e)) })?; - let auth_payload = AuthPayload { - message_prefix: "Bitcoin Signed Message:\n".into() - }; + let signature = context.keystore.sign_hashed( + &address, + &self.msg.clone().to_bytes(), + password.clone(), + )?; - 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()); + let kp = context.keystore.get_key_pair(&address, password)?; - let signature = - context - .keystore - .sign_hashed(&addrss, &msg_body, password)?; + 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(), + ); if self.json { - Ok(Some(AccountSignView::new( - self.msg.clone(), - signature.encode_hex(), - ))) + Ok(Some(AccountSignView::new(self.msg.clone(), auth_payload))) } else { println!("Msg you input : {}", &self.msg); println!("Signature : {}", signature.encode_hex::()); diff --git a/crates/rooch/src/commands/account/commands/verify.rs b/crates/rooch/src/commands/account/commands/verify.rs new file mode 100644 index 0000000000..c25a93f484 --- /dev/null +++ b/crates/rooch/src/commands/account/commands/verify.rs @@ -0,0 +1,58 @@ +// Copyright (c) RoochNetwork +// SPDX-License-Identifier: Apache-2.0 + +use crate::cli_types::{CommandAction, WalletContextOptions}; +use async_trait::async_trait; +use clap::Parser; +use hex::ToHex; +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) +/// +/// This operation must be specified with -a or +/// --address to export only one address with a private key. +#[derive(Debug, Parser)] +pub struct VerifyCommand { + /// signature that will be verified + #[clap(long, required = true)] + signature: String, + + #[clap(flatten)] + pub context_options: WalletContextOptions, + + /// Return command outputs in json format + #[clap(long, default_value = "false")] + json: bool, +} + +#[async_trait] +impl CommandAction> for VerifyCommand { + async fn execute(self) -> RoochResult> { + let context = self.context_options.build_require_password()?; + 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()); + + let signature = context.keystore.sign_hashed(&addrss, &msg_body, password)?; + + if self.json { + Ok(Some(AccountSignView::new( + self.msg.clone(), + signature.encode_hex(), + ))) + } else { + println!("Msg you input : {}", &self.msg); + println!("Signature : {}", signature.encode_hex::()); + Ok(None) + } + } +} diff --git a/crates/rooch/src/commands/account/mod.rs b/crates/rooch/src/commands/account/mod.rs index a4be829de8..eb9338e63c 100644 --- a/crates/rooch/src/commands/account/mod.rs +++ b/crates/rooch/src/commands/account/mod.rs @@ -6,7 +6,7 @@ use async_trait::async_trait; use commands::{ balance::BalanceCommand, create::CreateCommand, create_multisign::CreateMultisignCommand, export::ExportCommand, import::ImportCommand, list::ListCommand, nullify::NullifyCommand, - sign::SignCommand, switch::SwitchCommand, transfer::TransferCommand, + sign::SignCommand, switch::SwitchCommand, transfer::TransferCommand, verify::VerifyCommand, }; use rooch_types::error::RoochResult; use std::path::PathBuf; @@ -38,6 +38,7 @@ impl CommandAction for Account { AccountCommand::Export(export) => export.execute_serialized().await, AccountCommand::Import(import) => import.execute_serialized().await, AccountCommand::Sign(sign) => sign.execute_serialized().await, + AccountCommand::Verify(verify) => verify.execute_serialized().await, } } } @@ -55,4 +56,5 @@ pub enum AccountCommand { Export(ExportCommand), Import(ImportCommand), Sign(SignCommand), + Verify(VerifyCommand), }