This repository has been archived by the owner on Nov 20, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: Refactor transaction validation and message handling (#24)
* fix: Remove cosmos specific error type * feat: Add decorators * feat: Add decorators to runtime * feat: Add validate basic decorator * feat: Add tx timeout decoration * feat: Add validation of memo decoration * refactor: Simplify code * refactor: Refactor modules * refactor: Refactor decorator trait * feat: Add msgs * fix: Fix parameter types bug * style: Reformat * feat: Add handlers * feat: Add get signers * refactor: Refactor ante handlers path * feat: Add chain id to pallet cosmos * refactor: Refactor self contained check * fix: Remove decoding cosmos tx from client * refactor: Refactor amino sign doc * feat: Add signer doc * refactor: Refactor get sign doc hash * test: Add sign doc test * refactor: Refactor features * refactor: Remove unused error types --------- Co-authored-by: Jungyong Um <[email protected]>
- Loading branch information
Showing
34 changed files
with
1,207 additions
and
639 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
[package] | ||
name = "pallet-cosmos-modules" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
repository = "https://github.com/noirhq/horizon/" | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies] | ||
# Substrate | ||
frame-support = { workspace = true } | ||
sp-runtime = { workspace = true } | ||
sp-std = { workspace = true } | ||
|
||
# Horizon | ||
hp-cosmos = { workspace = true, features = ["with-codec"] } | ||
|
||
[features] | ||
default = ["std"] | ||
std = ["frame-support/std", "sp-runtime/std", "sp-std/std", "hp-cosmos/std"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
[package] | ||
name = "pallet-cosmos-auth" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
repository = "https://github.com/noirhq/horizon/" | ||
|
||
[package.metadata.docs.rs] | ||
targets = ["x86_64-unknown-linux-gnu"] | ||
|
||
[dependencies] | ||
frame-system = { workspace = true } | ||
sp-core = { workspace = true } | ||
sp-runtime = { workspace = true } | ||
sp-std = { workspace = true } | ||
|
||
hp-cosmos = { workspace = true } | ||
hp-io = { workspace = true } | ||
pallet-cosmos = { workspace = true } | ||
pallet-cosmos-modules = { workspace = true } | ||
|
||
[features] | ||
default = ["std"] | ||
std = [ | ||
"frame-system/std", | ||
"sp-core/std", | ||
"sp-runtime/std", | ||
"sp-std/std", | ||
"hp-cosmos/std", | ||
"hp-io/std", | ||
"pallet-cosmos/std", | ||
"pallet-cosmos-modules/std" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// This file is part of Horizon. | ||
|
||
// Copyright (C) 2023 Haderech Pte. Ltd. | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
use hp_cosmos::Tx; | ||
use pallet_cosmos_modules::ante::AnteHandler; | ||
use sp_runtime::{ | ||
traits::Get, | ||
transaction_validity::{InvalidTransaction, TransactionValidityError}, | ||
SaturatedConversion, | ||
}; | ||
use sp_std::marker::PhantomData; | ||
|
||
pub struct ValidateBasicHandler<T>(PhantomData<T>); | ||
|
||
impl<T> AnteHandler for ValidateBasicHandler<T> | ||
where | ||
T: frame_system::Config, | ||
{ | ||
fn handle(tx: &Tx) -> Result<(), TransactionValidityError> { | ||
if tx.signatures.is_empty() { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadProof)); | ||
} | ||
if tx.auth_info.signer_infos.len() != tx.signatures.len() { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
pub struct TxTimeoutHeightHandler<T>(PhantomData<T>); | ||
|
||
impl<T> AnteHandler for TxTimeoutHeightHandler<T> | ||
where | ||
T: frame_system::Config, | ||
{ | ||
fn handle(tx: &Tx) -> Result<(), TransactionValidityError> { | ||
if tx.body.timeout_height > 0 && | ||
frame_system::Pallet::<T>::block_number().saturated_into::<u64>() > | ||
tx.body.timeout_height | ||
{ | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} | ||
|
||
pub struct ValidateMemoHandler<T>(PhantomData<T>); | ||
|
||
impl<T> AnteHandler for ValidateMemoHandler<T> | ||
where | ||
T: pallet_cosmos::Config, | ||
{ | ||
fn handle(tx: &Tx) -> Result<(), TransactionValidityError> { | ||
if tx.body.memo.len().saturated_into::<u64>() > T::MaxMemoCharacters::get() { | ||
// TODO: Consider use InvalidTransaction::Custom | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::Call)); | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// This file is part of Horizon. | ||
|
||
// Copyright (C) 2023 Haderech Pte. Ltd. | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
#![cfg_attr(not(feature = "std"), no_std)] | ||
#![allow(clippy::comparison_chain, clippy::large_enum_variant)] | ||
|
||
pub mod basic; | ||
pub mod sigverify; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
// This file is part of Horizon. | ||
|
||
// Copyright (C) 2023 Haderech Pte. Ltd. | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
// | ||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
use hp_cosmos::{AccountId, PublicKey, SignerPublicKey, Tx}; | ||
use hp_io::crypto::secp256k1_ecdsa_verify; | ||
use pallet_cosmos_modules::ante::AnteHandler; | ||
use sp_core::{sha2_256, Get, H160}; | ||
use sp_runtime::transaction_validity::{InvalidTransaction, TransactionValidityError}; | ||
use sp_std::marker::PhantomData; | ||
|
||
pub struct SigVerificationHandler<T>(PhantomData<T>); | ||
|
||
impl<T> AnteHandler for SigVerificationHandler<T> | ||
where | ||
T: frame_system::Config + pallet_cosmos::Config, | ||
{ | ||
fn handle(tx: &Tx) -> Result<(), TransactionValidityError> { | ||
let signatures = &tx.signatures; | ||
|
||
let mut signers = sp_std::vec::Vec::<AccountId>::new(); | ||
for msg in &tx.body.messages { | ||
if let Some(msg_signers) = | ||
hp_io::signers::get_msg_any_signers(&msg.type_url, &msg.value) | ||
{ | ||
for msg_signer in msg_signers { | ||
if !signers.contains(&msg_signer) { | ||
signers.push(msg_signer); | ||
} | ||
} | ||
} | ||
} | ||
if let Some(fee_payer) = &tx.auth_info.fee.payer { | ||
if !signers.contains(fee_payer) { | ||
signers.push(fee_payer.clone()); | ||
} | ||
} | ||
|
||
if signatures.len() != signers.len() { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)); | ||
} | ||
|
||
let signer_infos = &tx.auth_info.signer_infos; | ||
if signatures.len() != signer_infos.len() { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)); | ||
} | ||
|
||
for (i, sig) in signatures.iter().enumerate() { | ||
let signer = signers | ||
.get(i) | ||
.ok_or(TransactionValidityError::Invalid(InvalidTransaction::BadSigner))?; | ||
|
||
// TODO: Support other types of Signers as well | ||
let signer_info = signer_infos | ||
.get(i) | ||
.ok_or(TransactionValidityError::Invalid(InvalidTransaction::BadSigner))?; | ||
|
||
if let Some(SignerPublicKey::Single(PublicKey::Secp256k1(public_key))) = | ||
signer_info.public_key | ||
{ | ||
let address: H160 = hp_io::crypto::ripemd160(&sha2_256(&public_key)).into(); | ||
if signer.address != address { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)); | ||
} | ||
|
||
let (account, _) = pallet_cosmos::Pallet::<T>::account(&signer.address); | ||
if signer_info.sequence > account.sequence { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::Future)); | ||
} else if signer_info.sequence < account.sequence { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::Stale)); | ||
} | ||
|
||
let chain_id = T::ChainId::get(); | ||
let hash = match &signer_info.mode_info { | ||
hp_cosmos::ModeInfo::Single(single) => match single.mode { | ||
hp_cosmos::SignMode::Direct => | ||
hp_io::tx::get_signer_doc_bytes(&tx.raw, &chain_id, 0u64), | ||
|
||
hp_cosmos::SignMode::LegacyAminoJson => | ||
hp_io::tx::get_amino_signer_doc_bytes( | ||
&tx.raw, | ||
&chain_id, | ||
0u64, | ||
signer_info.sequence, | ||
), | ||
_ => None, | ||
}, | ||
} | ||
.ok_or(TransactionValidityError::Invalid(InvalidTransaction::BadSigner))?; | ||
|
||
if !secp256k1_ecdsa_verify(sig, &hash, &public_key) { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadProof)); | ||
} | ||
} else { | ||
return Err(TransactionValidityError::Invalid(InvalidTransaction::BadSigner)); | ||
} | ||
} | ||
|
||
Ok(()) | ||
} | ||
} |
Oops, something went wrong.