Skip to content

Commit

Permalink
[rooch-networkgh-2381] revise the sign and verify process.
Browse files Browse the repository at this point in the history
  • Loading branch information
Feliciss committed Sep 5, 2024
1 parent bb8fe72 commit 4802983
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 81 deletions.
7 changes: 7 additions & 0 deletions crates/rooch-types/src/transaction/rooch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ impl RoochTransactionData {
bcs::to_bytes(self).expect("encode transaction should success")
}

pub fn decode(bytes: &[u8]) -> Result<Self>
where
Self: std::marker::Sized,
{
bcs::from_bytes::<Self>(bytes).map_err(Into::into)
}

pub fn tx_hash(&self) -> H256 {
moveos_types::h256::sha3_256_of(self.encode().as_slice())
}
Expand Down
38 changes: 29 additions & 9 deletions crates/rooch/src/commands/account/commands/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,16 @@ use async_trait::async_trait;
use clap::Parser;
use move_command_line_common::types::ParsedStructType;
use move_core_types::language_storage::TypeTag;
use moveos_types::transaction::MoveAction;
use moveos_types::{state::MoveState, transaction::MoveAction};
use rooch_key::keystore::account_keystore::AccountKeystore;
use rooch_types::{
error::RoochResult,
framework::auth_payload::{AuthPayload, SignData},
function_arg::{parse_function_arg, FunctionArg, ParsedFunctionId},
};
use serde::{Deserialize, Serialize};

/// 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.
/// Sign a tx with an account
#[derive(Debug, Parser)]
pub struct SignCommand {
/// Function name as `<ADDRESS>::<MODULE_ID>::<FUNCTION_NAME>`
Expand Down Expand Up @@ -55,9 +53,24 @@ pub struct SignCommand {
json: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SignOutput {
pub tx_data: String,
pub auth_payload: String,
}

impl SignOutput {
pub fn new(tx_data: String, auth_payload: String) -> Self {
Self {
tx_data,
auth_payload,
}
}
}

#[async_trait]
impl CommandAction<Option<AuthPayload>> for SignCommand {
async fn execute(self) -> RoochResult<Option<AuthPayload>> {
impl CommandAction<Option<SignOutput>> for SignCommand {
async fn execute(self) -> RoochResult<Option<SignOutput>> {
let context = self.context_options.build_require_password()?;
let password = context.get_password();
let address_mapping = context.address_mapping();
Expand Down Expand Up @@ -91,10 +104,17 @@ impl CommandAction<Option<AuthPayload>> for SignCommand {
let signature = kp.sign(data_hash.as_bytes());
let auth_payload = AuthPayload::new(sign_data, signature, bitcoin_address.to_string());

let result = SignOutput::new(
hex::encode(tx_data.encode()),
hex::encode(auth_payload.to_bytes()),
);
if self.json {
Ok(Some(auth_payload))
Ok(Some(result))
} else {
println!("Sign succeeded with the auth payload: {:?}", auth_payload);
println!(
"Sign tx data {} succeeded with the auth payload: {}",
result.tx_data, result.auth_payload
);
Ok(None)
}
}
Expand Down
100 changes: 28 additions & 72 deletions crates/rooch/src/commands/account/commands/verify.rs
Original file line number Diff line number Diff line change
@@ -1,50 +1,24 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use crate::cli_types::{CommandAction, TransactionOptions, WalletContextOptions};
use crate::cli_types::{CommandAction, WalletContextOptions};
use async_trait::async_trait;
use bitcoin::hex::DisplayHex;
use clap::Parser;
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_types::{
error::{RoochResult},
framework::auth_payload::{AuthPayload},
function_arg::{parse_function_arg, FunctionArg, ParsedFunctionId},
transaction::Authenticator,
error::{RoochError, RoochResult},
framework::auth_payload::AuthPayload, transaction::RoochTransactionData,
};
use anyhow::Result;

/// Verify a signed message
/// Verify a tx with a auth payload
#[derive(Debug, Parser)]
pub struct VerifyCommand {
/// Function name as `<ADDRESS>::<MODULE_ID>::<FUNCTION_NAME>`
/// Example: `0x42::message::set_message`, `rooch_framework::empty::empty`
#[clap(long)]
pub function: ParsedFunctionId,
/// tx data hex
#[clap(long, required = true)]
tx_data: String,

/// 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<ParsedStructType>,

/// Arguments combined with their type separated by spaces.
///
/// Supported types [u8, u16, u32, u64, u128, u256, bool, object_id, string, address, vector<inner_type>]
///
/// Example: `address:0x1 bool:true u8:0 u256:1234 'vector<u32>: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<FunctionArg>,

#[clap(flatten)]
pub tx_options: TransactionOptions,
/// auth payload hex
#[clap(long, required = true)]
auth_payload: String,

#[clap(flatten)]
pub context_options: WalletContextOptions,
Expand All @@ -57,45 +31,27 @@ pub struct VerifyCommand {
#[async_trait]
impl CommandAction<Option<String>> for VerifyCommand {
async fn execute(self) -> RoochResult<Option<String>> {
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 max_gas_amount = self.tx_options.max_gas_amount;

let function_id = self.function.into_function_id(&address_mapping)?;
let args = self
.args
.into_iter()
.map(|arg| arg.into_bytes(&address_mapping))
.collect::<Result<Vec<_>>>()?;
let type_args = self
.type_args
.into_iter()
.map(|tag| {
Ok(TypeTag::Struct(Box::new(
tag.into_struct_tag(&address_mapping)?,
)))
})
.collect::<Result<Vec<_>>>()?;
let action = MoveAction::new_function_call(function_id, type_args, args);

let tx_data = context
.build_tx_data(sender, action, max_gas_amount)
.await?;

let auth = Authenticator::bitcoin(&kp, &tx_data);
let auth_payload = bcs::from_bytes::<AuthPayload>(&auth.payload)?;
auth_payload.verify(&tx_data)?;
let tx_data_bytes = hex::decode(&self.tx_data).map_err(|e| {
RoochError::CommandArgumentError(format!(
"Failed to decode tx hex: {}, err:{:?}",
self.tx_data, e
))
})?;
let auth_payload_bytes = hex::decode(&self.auth_payload).map_err(|e| {
RoochError::CommandArgumentError(format!(
"Failed to decode auth payload hex: {}, err:{:?}",
self.auth_payload, e
))
})?;

let tx_data = RoochTransactionData::decode(&tx_data_bytes)?;
let auth_payload = bcs::from_bytes::<AuthPayload>(&auth_payload_bytes)?;
let _ = auth_payload.verify(&tx_data);

if self.json {
Ok(Some(auth_payload.signature.as_hex().to_string()))
Ok(None)
} else {
println!(
"Verify auth payload succeeded with the signature: {}",
auth_payload.signature.as_hex()
);
println!("Verify the auth payload succeeded",);
Ok(None)
}
}
Expand Down

0 comments on commit 4802983

Please sign in to comment.