Skip to content

Commit

Permalink
[rpc & cli] Add chain_id to SignedMessage, and verify chain id. (#2696)
Browse files Browse the repository at this point in the history
* [rpc & cli] Add chain_id to SignedMessage, and verify chain id.
  • Loading branch information
jolestar authored Jul 12, 2021
1 parent bd607dd commit d11fb85
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 45 deletions.
6 changes: 4 additions & 2 deletions account/service/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use starcoin_logger::prelude::*;
use starcoin_service_registry::mocker::MockHandler;
use starcoin_service_registry::{ActorService, ServiceContext, ServiceFactory, ServiceHandler};
use starcoin_types::account_config::{association_address, STC_TOKEN_CODE};
use starcoin_types::genesis_config::ChainId;
use std::any::Any;
use std::sync::Arc;

Expand All @@ -22,7 +23,7 @@ pub struct AccountService {

impl AccountService {
pub fn mock() -> Result<Self> {
let manager = AccountManager::new(AccountStorage::mock())?;
let manager = AccountManager::new(AccountStorage::mock(), ChainId::test())?;
//auto create default account.
manager.create_account("")?;
Ok(Self { manager })
Expand Down Expand Up @@ -91,7 +92,8 @@ impl ActorService for AccountService {
impl ServiceFactory<AccountService> for AccountService {
fn create(ctx: &mut ServiceContext<AccountService>) -> Result<AccountService> {
let account_storage = ctx.get_shared::<AccountStorage>()?;
let manager = AccountManager::new(account_storage)?;
let config = ctx.get_shared::<Arc<NodeConfig>>()?;
let manager = AccountManager::new(account_storage, config.net().chain_id())?;
Ok(Self { manager })
}
}
Expand Down
14 changes: 12 additions & 2 deletions account/src/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use starcoin_logger::prelude::*;
use starcoin_storage::storage::StorageInstance;
use starcoin_types::account_address;
use starcoin_types::account_address::AccountAddress;
use starcoin_types::genesis_config::ChainId;
use starcoin_types::sign_message::{SignedMessage, SigningMessage};
use starcoin_types::transaction::authenticator::AuthenticationKey;
use starcoin_types::transaction::{RawUserTransaction, SignedUserTransaction};
Expand Down Expand Up @@ -118,13 +119,22 @@ impl Account {
)
}

pub fn sign_message(&self, message: SigningMessage) -> Result<SignedMessage> {
pub fn sign_message(
&self,
message: SigningMessage,
chain_id: ChainId,
) -> Result<SignedMessage> {
let authenticator = self
.private_key
.as_ref()
.map(|private_key| private_key.sign_message(&message))
.ok_or_else(|| format_err!("Readonly account can not sign message."))?;
Ok(SignedMessage::new(self.addr, message, authenticator))
Ok(SignedMessage::new(
self.addr,
message,
authenticator,
chain_id,
))
}

pub fn sign_txn(&self, raw_txn: RawUserTransaction) -> Result<SignedUserTransaction> {
Expand Down
7 changes: 5 additions & 2 deletions account/src/account_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use starcoin_account_api::{AccountInfo, AccountPrivateKey, AccountPublicKey, Acc
use starcoin_crypto::ed25519::Ed25519PrivateKey;
use starcoin_crypto::{Uniform, ValidCryptoMaterial};
use starcoin_logger::prelude::*;
use starcoin_types::genesis_config::ChainId;
use starcoin_types::sign_message::{SignedMessage, SigningMessage};
use starcoin_types::{
account_address::AccountAddress,
Expand All @@ -27,6 +28,7 @@ use std::time::Instant;
pub struct AccountManager {
store: AccountStorage,
key_cache: RwLock<PasswordCache>,
chain_id: ChainId,
}

#[derive(Default, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -62,10 +64,11 @@ impl PasswordCache {
}

impl AccountManager {
pub fn new(storage: AccountStorage) -> AccountResult<Self> {
pub fn new(storage: AccountStorage, chain_id: ChainId) -> AccountResult<Self> {
let manager = Self {
store: storage,
key_cache: RwLock::new(PasswordCache::default()),
chain_id,
};
Ok(manager)
}
Expand Down Expand Up @@ -225,7 +228,7 @@ impl AccountManager {
let account = Account::load(signer_address, Some(p), self.store.clone())?
.ok_or(AccountError::AccountNotExist(signer_address))?;
account
.sign_message(message)
.sign_message(message, self.chain_id)
.map_err(AccountError::MessageSignError)
}
}
Expand Down
31 changes: 27 additions & 4 deletions account/src/account_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ use starcoin_types::account_address::AccountAddress;
use starcoin_types::genesis_config::ChainId;
use starcoin_types::identifier::{IdentStr, Identifier};
use starcoin_types::language_storage::{StructTag, CORE_CODE_ADDRESS};
use starcoin_types::sign_message::{SignedMessage, SigningMessage};
use starcoin_types::transaction::{
RawUserTransaction, Script, SignedUserTransaction, TransactionPayload,
};
use std::str::FromStr;
use std::time::Duration;

#[test]
pub fn test_import_account() -> Result<()> {
let tempdir = tempfile::tempdir()?;
let storage = AccountStorage::create_from_path(tempdir.path(), RocksdbConfig::default())?;
let manager = AccountManager::new(storage)?;
let manager = AccountManager::new(storage, ChainId::test())?;

// should success
let wallet = manager.create_account("hello")?;
Expand All @@ -47,7 +49,7 @@ pub fn test_import_account() -> Result<()> {
pub fn test_wallet() -> Result<()> {
let tempdir = tempfile::tempdir()?;
let storage = AccountStorage::create_from_path(tempdir.path(), RocksdbConfig::default())?;
let manager = AccountManager::new(storage.clone())?;
let manager = AccountManager::new(storage.clone(), ChainId::test())?;

// should success
let wallet = manager.create_account("hello")?;
Expand Down Expand Up @@ -80,7 +82,7 @@ pub fn test_wallet() -> Result<()> {
pub fn test_readonly_account() -> Result<()> {
let tempdir = tempfile::tempdir()?;
let storage = AccountStorage::create_from_path(tempdir.path(), RocksdbConfig::default())?;
let manager = AccountManager::new(storage.clone())?;
let manager = AccountManager::new(storage.clone(), ChainId::test())?;
let mut key_gen = KeyGen::from_os_rng();
let (_private_key, public_key) = key_gen.generate_keypair();
let account_public_key = AccountPublicKey::Single(public_key);
Expand Down Expand Up @@ -109,7 +111,7 @@ pub fn test_readonly_account() -> Result<()> {
pub fn test_wallet_unlock() -> Result<()> {
let tempdir = tempfile::tempdir()?;
let storage = AccountStorage::create_from_path(tempdir.path(), RocksdbConfig::default())?;
let manager = AccountManager::new(storage)?;
let manager = AccountManager::new(storage, ChainId::test())?;

let wallet = manager.create_account("hello")?;

Expand Down Expand Up @@ -142,6 +144,27 @@ pub fn test_wallet_unlock() -> Result<()> {
Ok(())
}

#[test]
pub fn test_sign_message() -> Result<()> {
let tempdir = tempfile::tempdir()?;
let storage = AccountStorage::create_from_path(tempdir.path(), RocksdbConfig::default())?;
let manager = AccountManager::new(storage, ChainId::test())?;

let account = manager.create_account("hello")?;
let _unlock_result =
manager.unlock_account(*account.address(), "hello", Duration::from_secs(100))?;
let signed_message =
account.sign_message(SigningMessage::from_str("hello")?, ChainId::test())?;
signed_message.check_signature()?;
signed_message.check_account(ChainId::test(), None)?;
let signed_message_hex = signed_message.to_hex();
let signed_message = SignedMessage::from_str(signed_message_hex.as_str())?;
println!("{:?}", serde_json::to_string(&signed_message));
signed_message.check_signature()?;
signed_message.check_account(ChainId::test(), None)?;
Ok(())
}

// ignore for now.
#[ignore]
#[test]
Expand Down
2 changes: 1 addition & 1 deletion cmd/generator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn init_or_load_data_dir(
let vault_config = &config.vault;
let account_storage =
AccountStorage::create_from_path(vault_config.dir(), config.storage.rocksdb_config())?;
let manager = AccountManager::new(account_storage)?;
let manager = AccountManager::new(account_storage, config.net().chain_id())?;
let account = match manager.default_account_info()? {
Some(account) => account,
None => manager
Expand Down
19 changes: 14 additions & 5 deletions cmd/starcoin/src/account/sign_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0

use crate::cli_state::CliState;
use crate::view::StringView;
use crate::StarcoinOpt;
use anyhow::Result;
use scmd::{CommandAction, ExecContext};
use starcoin_types::sign_message::SigningMessage;
use serde::{Deserialize, Serialize};
use starcoin_types::sign_message::{SignedMessage, SigningMessage};
use starcoin_vm_types::account_address::AccountAddress;
use structopt::StructOpt;

Expand All @@ -28,7 +28,7 @@ impl CommandAction for SignMessageCmd {
type State = CliState;
type GlobalOpt = StarcoinOpt;
type Opt = SignMessageOpt;
type ReturnItem = StringView;
type ReturnItem = SignResult;

fn run(
&self,
Expand All @@ -38,8 +38,17 @@ impl CommandAction for SignMessageCmd {
let client = ctx.state().client();
let sender = ctx.state().get_account_or_default(opt.sender)?;
let signed_message = client.account_sign_message(sender.address, opt.message.clone())?;
Ok(StringView {
result: signed_message.to_string(),

let hex = signed_message.to_string();
Ok(SignResult {
msg: signed_message.0,
hex,
})
}
}

#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
pub struct SignResult {
pub msg: SignedMessage,
pub hex: String,
}
26 changes: 16 additions & 10 deletions cmd/starcoin/src/account/verify_sign_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// SPDX-License-Identifier: Apache-2.0

use crate::cli_state::CliState;
use crate::view::BoolView;
use crate::StarcoinOpt;
use anyhow::Result;
use scmd::{CommandAction, ExecContext};
use serde::{Deserialize, Serialize};
use starcoin_types::sign_message::SignedMessage;
use structopt::StructOpt;

Expand All @@ -23,7 +23,7 @@ impl CommandAction for VerifySignMessageCmd {
type State = CliState;
type GlobalOpt = StarcoinOpt;
type Opt = VerifySignMessageOpt;
type ReturnItem = BoolView;
type ReturnItem = VerifyResult;

fn run(
&self,
Expand All @@ -34,14 +34,20 @@ impl CommandAction for VerifySignMessageCmd {
let signed_message = opt.signed_message.clone();
let account_resource = state.get_account_resource(signed_message.account)?;

let result = signed_message
.check_signature()
.and_then(|_| signed_message.check_account(account_resource.as_ref()));
if let Err(e) = result.as_ref() {
eprintln!("check signed message error: {}", e)
}
Ok(BoolView {
result: result.is_ok(),
let result = signed_message.check_signature().and_then(|_| {
signed_message.check_account(state.net().chain_id(), account_resource.as_ref())
});
Ok(VerifyResult {
ok: result.is_ok(),
error: result.err().map(|e| e.to_string()),
msg: signed_message,
})
}
}

#[derive(Debug, Clone, Hash, Serialize, Deserialize)]
pub struct VerifyResult {
pub ok: bool,
pub error: Option<String>,
pub msg: SignedMessage,
}
4 changes: 2 additions & 2 deletions rpc/server/src/module/account_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ where
) -> FutureResult<SignedMessageView> {
let account_service = self.account.clone();
let f = async move {
let signature = account_service.sign_message(address, data).await?;
Ok(signature.into())
let signed_message = account_service.sign_message(address, data).await?;
Ok(signed_message.into())
};
Box::pin(f.map_err(map_err).boxed())
}
Expand Down
16 changes: 8 additions & 8 deletions testsuite/features/cmd.feature
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,22 @@ Feature: cmd integration test
# test the account do not exist on chain
Then cmd: "account unlock"
Then cmd: "account sign-message -m helloworld"
Then cmd: "account verify-sign-message -m @$.result@"
Then assert: "$.result true"
Then cmd: "account verify-sign-message -m @$.hex@"
Then assert: "$.ok true"
# create the account on chain
Then cmd: "dev get-coin"
Then cmd: "account sign-message -m helloworld"
Then cmd: "account verify-sign-message -m @$.result@"
Then assert: "$.result true"
Then cmd: "account verify-sign-message -m @$.hex@"
Then assert: "$.ok true"
# init the auth key on chain by send the first transaction, test authkey is not dummy key.
Then cmd: "account transfer -v 1000 -r 0xA550C18 -b"
Then cmd: "account sign-message -m helloworld"
Then cmd: "account verify-sign-message -m @$.result@"
Then assert: "$.result true"
Then cmd: "account verify-sign-message -m @$.hex@"
Then assert: "$.ok true"
# test multi sign account
Then cmd: "account sign-message -s 0xA550C18 -m helloworld"
Then cmd: "account verify-sign-message -m @$.result@"
Then assert: "$.result true"
Then cmd: "account verify-sign-message -m @$.hex@"
Then assert: "$.ok true"

Examples:
| |
Expand Down
Loading

0 comments on commit d11fb85

Please sign in to comment.