Skip to content

Commit ba31a73

Browse files
authored
feat(msa): add support for unwrapped bytes (#2169)
Add support to verify signatures against unwrapped bytes. This allows for verification of signatures not using PolkadotUi. #2134
1 parent 857896b commit ba31a73

File tree

15 files changed

+152
-51
lines changed

15 files changed

+152
-51
lines changed

pallets/handles/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ sp-std = { workspace = true }
2828
# Frequency related dependencies
2929
common-primitives = { default-features = false, path = "../../common/primitives" }
3030
handles-utils = { default-features = false, path = "src/handles-utils" }
31-
[dev-dependencies]
3231
common-runtime = { path = "../../runtime/common", default-features = false }
32+
33+
[dev-dependencies]
3334
env_logger = { workspace = true }
3435
pretty_assertions = { workspace = true }
3536
serde = { workspace = true, features = ["derive"] }

pallets/handles/src/benchmarking.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
use super::*;
55
use crate::Pallet as Handles;
6+
use common_primitives::utils::wrap_binary_data;
67
use frame_benchmarking::{benchmarks, whitelisted_caller};
78
use frame_support::assert_ok;
89
use frame_system::RawOrigin;

pallets/handles/src/lib.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,21 +50,19 @@ use common_primitives::benchmarks::MsaBenchmarkHelper;
5050
use common_primitives::{
5151
handles::*,
5252
msa::{MessageSourceId, MsaLookup, MsaValidator},
53-
utils::wrap_binary_data,
5453
};
5554
use frame_support::{dispatch::DispatchResult, ensure, pallet_prelude::*, traits::Get};
5655
use frame_system::pallet_prelude::*;
5756
use numtoa::*;
5857
pub use pallet::*;
5958
use sp_core::crypto::AccountId32;
60-
use sp_runtime::{
61-
traits::{Convert, Verify},
62-
DispatchError, MultiSignature,
63-
};
59+
use sp_runtime::{traits::Convert, DispatchError, MultiSignature};
6460
use sp_std::{prelude::*, vec::Vec};
6561

6662
pub mod handles_signed_extension;
6763

64+
use common_runtime::signature::check_signature;
65+
6866
pub mod weights;
6967
pub use weights::*;
7068

@@ -285,10 +283,9 @@ pub mod pallet {
285283
signer: &T::AccountId,
286284
payload: Vec<u8>,
287285
) -> DispatchResult {
288-
let key = T::ConvertIntoAccountId32::convert((*signer).clone());
289-
let wrapped_payload = wrap_binary_data(payload);
286+
let key = T::ConvertIntoAccountId32::convert(signer.clone());
290287

291-
ensure!(signature.verify(&wrapped_payload[..], &key), Error::<T>::InvalidSignature);
288+
ensure!(check_signature(signature, key, payload), Error::<T>::InvalidSignature);
292289

293290
Ok(())
294291
}

pallets/msa/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ common-primitives = { default-features = false, path = "../../common/primitives"
3030
serde = { workspace = true, features = ["derive"] }
3131
serde_json = { workspace = true, features = ["alloc"] }
3232
hex = { workspace = true, default-features = false, features = ["alloc"] }
33+
common-runtime = { path = "../../runtime/common", default-features = false }
3334

3435
[dev-dependencies]
35-
common-runtime = { path = "../../runtime/common", default-features = false }
3636
pallet-schemas = { path = "../schemas", default-features = false }
3737
pallet-handles = { path = "../handles", default-features = false }
3838
pallet-collective = { workspace = true }

pallets/msa/src/lib.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ use frame_support::{
3939
};
4040
use parity_scale_codec::{Decode, Encode};
4141

42+
use common_runtime::signature::check_signature;
43+
4244
#[cfg(feature = "runtime-benchmarks")]
4345
use common_primitives::benchmarks::{MsaBenchmarkHelper, RegisterProviderBenchmarkHelper};
4446

@@ -57,9 +59,7 @@ use log;
5759
use scale_info::TypeInfo;
5860
use sp_core::crypto::AccountId32;
5961
use sp_runtime::{
60-
traits::{
61-
BlockNumberProvider, Convert, DispatchInfoOf, Dispatchable, SignedExtension, Verify, Zero,
62-
},
62+
traits::{BlockNumberProvider, Convert, DispatchInfoOf, Dispatchable, SignedExtension, Zero},
6363
ArithmeticError, DispatchError, MultiSignature,
6464
};
6565
use sp_std::{prelude::*, vec};
@@ -461,7 +461,10 @@ pub mod pallet {
461461
) -> DispatchResult {
462462
let provider_key = ensure_signed(origin)?;
463463

464-
Self::verify_signature(&proof, &delegator_key, add_provider_payload.encode())?;
464+
ensure!(
465+
Self::verify_signature(&proof, &delegator_key, add_provider_payload.encode()),
466+
Error::<T>::InvalidSignature
467+
);
465468

466469
Self::register_signature(&proof, add_provider_payload.expiration.into())?;
467470

@@ -551,9 +554,10 @@ pub mod pallet {
551554
) -> DispatchResult {
552555
let provider_key = ensure_signed(origin)?;
553556

554-
// delegator must have signed the payload.
555-
Self::verify_signature(&proof, &delegator_key, add_provider_payload.encode())
556-
.map_err(|_| Error::<T>::AddProviderSignatureVerificationFailed)?;
557+
ensure!(
558+
Self::verify_signature(&proof, &delegator_key, add_provider_payload.encode()),
559+
Error::<T>::AddProviderSignatureVerificationFailed
560+
);
557561

558562
Self::register_signature(&proof, add_provider_payload.expiration.into())?;
559563
let (provider_id, delegator_id) =
@@ -647,19 +651,23 @@ pub mod pallet {
647651
) -> DispatchResult {
648652
let _ = ensure_signed(origin)?;
649653

650-
Self::verify_signature(
651-
&msa_owner_proof,
652-
&msa_owner_public_key,
653-
add_key_payload.encode(),
654-
)
655-
.map_err(|_| Error::<T>::MsaOwnershipInvalidSignature)?;
654+
ensure!(
655+
Self::verify_signature(
656+
&msa_owner_proof,
657+
&msa_owner_public_key,
658+
add_key_payload.encode()
659+
),
660+
Error::<T>::MsaOwnershipInvalidSignature
661+
);
656662

657-
Self::verify_signature(
658-
&new_key_owner_proof,
659-
&add_key_payload.new_public_key.clone(),
660-
add_key_payload.encode(),
661-
)
662-
.map_err(|_| Error::<T>::NewKeyOwnershipInvalidSignature)?;
663+
ensure!(
664+
Self::verify_signature(
665+
&new_key_owner_proof,
666+
&add_key_payload.new_public_key,
667+
add_key_payload.encode()
668+
),
669+
Error::<T>::NewKeyOwnershipInvalidSignature
670+
);
663671

664672
Self::register_signature(&msa_owner_proof, add_key_payload.expiration)?;
665673
Self::register_signature(&new_key_owner_proof, add_key_payload.expiration)?;
@@ -1095,13 +1103,10 @@ impl<T: Config> Pallet<T> {
10951103
signature: &MultiSignature,
10961104
signer: &T::AccountId,
10971105
payload: Vec<u8>,
1098-
) -> DispatchResult {
1106+
) -> bool {
10991107
let key = T::ConvertIntoAccountId32::convert((*signer).clone());
1100-
let wrapped_payload = wrap_binary_data(payload);
11011108

1102-
ensure!(signature.verify(&wrapped_payload[..], &key), Error::<T>::InvalidSignature);
1103-
1104-
Ok(())
1109+
check_signature(signature, key, payload)
11051110
}
11061111

11071112
/// Add a provider to a delegator with the default permissions

pallets/msa/src/tests/creation_tests.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,45 @@ fn it_does_not_allow_duplicate_keys() {
276276
assert_eq!(CurrentMsaIdentifierMaximum::<Test>::get(), 1);
277277
});
278278
}
279+
280+
#[test]
281+
fn verify_signature_with_wrapped_bytes() {
282+
new_test_ext().execute_with(|| {
283+
let provider_msa = 1;
284+
let (key_pair_delegator, _) = sr25519::Pair::generate();
285+
286+
let expiration: BlockNumber = 10;
287+
288+
let add_provider_payload = AddProvider::new(provider_msa, None, expiration);
289+
let encode_add_provider_data = wrap_binary_data(add_provider_payload.encode());
290+
291+
let signature: MultiSignature = key_pair_delegator.sign(&encode_add_provider_data).into();
292+
293+
assert!(Msa::verify_signature(
294+
&signature,
295+
&key_pair_delegator.public().into(),
296+
add_provider_payload.encode()
297+
));
298+
});
299+
}
300+
301+
#[test]
302+
fn verify_signature_without_wrapped_bytes() {
303+
new_test_ext().execute_with(|| {
304+
let provider_msa = 1;
305+
let (key_pair_delegator, _) = sr25519::Pair::generate();
306+
307+
let expiration: BlockNumber = 10;
308+
309+
let add_provider_payload = AddProvider::new(provider_msa, None, expiration);
310+
311+
let signature: MultiSignature =
312+
key_pair_delegator.sign(&add_provider_payload.encode()).into();
313+
314+
assert!(Msa::verify_signature(
315+
&signature,
316+
&key_pair_delegator.public().into(),
317+
add_provider_payload.encode()
318+
));
319+
});
320+
}

pallets/passkey/src/benchmarking.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use crate::{
1010
},
1111
types::*,
1212
};
13+
use common_primitives::utils::wrap_binary_data;
1314
use frame_benchmarking::benchmarks;
1415
use frame_support::assert_ok;
1516
use sp_core::{crypto::KeyTypeId, Encode};

pallets/passkey/src/lib.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
rustdoc::invalid_codeblock_attributes,
1717
missing_docs
1818
)]
19-
use common_primitives::utils::wrap_binary_data;
20-
use common_runtime::extensions::check_nonce::CheckNonce;
19+
use common_runtime::{extensions::check_nonce::CheckNonce, signature::check_signature};
2120
use frame_support::{
2221
dispatch::{DispatchInfo, GetDispatchInfo, PostDispatchInfo},
2322
pallet_prelude::*,
@@ -27,7 +26,7 @@ use frame_system::pallet_prelude::*;
2726
use pallet_transaction_payment::OnChargeTransaction;
2827
use sp_runtime::{
2928
generic::Era,
30-
traits::{Convert, Dispatchable, SignedExtension, Verify, Zero},
29+
traits::{Convert, Dispatchable, SignedExtension, Zero},
3130
transaction_validity::{TransactionValidity, TransactionValidityError},
3231
AccountId32, MultiSignature,
3332
};
@@ -315,14 +314,12 @@ impl<T: Config> PasskeySignatureCheck<T> {
315314
signature: &MultiSignature,
316315
) -> DispatchResult {
317316
let key = T::ConvertIntoAccountId32::convert((*signer).clone());
318-
let signed_payload: Vec<u8> = wrap_binary_data(signed_data.clone().into());
319317

320-
let verified = signature.verify(&signed_payload[..], &key);
321-
if verified {
322-
Ok(())
323-
} else {
324-
Err(Error::<T>::InvalidAccountSignature.into())
318+
if !check_signature(signature, key, signed_data.clone()) {
319+
return Err(Error::<T>::InvalidAccountSignature.into());
325320
}
321+
322+
Ok(())
326323
}
327324
}
328325

pallets/passkey/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Unit tests for the passkey module.
22
use super::*;
33
use crate::mock::Passkey;
4+
use common_primitives::utils::wrap_binary_data;
45
use frame_support::{assert_err, assert_noop, assert_ok, dispatch::RawOrigin};
56
use frame_system::{limits::BlockLength, Call as SystemCall};
67
use mock::*;

pallets/stateful-storage/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ sp-runtime = { workspace = true }
2727
sp-std = { workspace = true }
2828
# Frequency related dependencies
2929
common-primitives = { default-features = false, path = "../../common/primitives" }
30+
common-runtime = { path = "../../runtime/common", default-features = false }
3031

3132
[dev-dependencies]
32-
common-runtime = { path = "../../runtime/common", default-features = false }
3333
env_logger = { workspace = true }
3434
pretty_assertions = { workspace = true }
3535
sp-keystore = { workspace = true }

pallets/stateful-storage/src/benchmarking.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{types::ItemAction, Pallet as StatefulStoragePallet};
44
use common_primitives::{
55
schema::{ModelType, PayloadLocation},
66
stateful_storage::{PageHash, PageId},
7+
utils::wrap_binary_data,
78
};
89
use frame_benchmarking::{benchmarks, whitelisted_caller};
910
use frame_support::assert_ok;

pallets/stateful-storage/src/lib.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,13 @@ use common_primitives::{
4646
msa::{
4747
DelegatorId, MessageSourceId, MsaLookup, MsaValidator, ProviderId, SchemaGrantValidator,
4848
},
49-
node::Verify,
5049
schema::{PayloadLocation, SchemaId, SchemaInfoResponse, SchemaProvider, SchemaSetting},
5150
stateful_storage::{
5251
ItemizedStoragePageResponse, ItemizedStorageResponse, PageHash, PageId,
5352
PaginatedStorageResponse,
5453
},
55-
utils::wrap_binary_data,
5654
};
55+
5756
use frame_support::{dispatch::DispatchResult, ensure, pallet_prelude::*, traits::Get};
5857
use frame_system::pallet_prelude::*;
5958
pub use pallet::*;
@@ -687,10 +686,12 @@ impl<T: Config> Pallet<T> {
687686
signer: &T::AccountId,
688687
payload: Vec<u8>,
689688
) -> DispatchResult {
690-
let key = T::ConvertIntoAccountId32::convert((*signer).clone());
691-
let wrapped_payload = wrap_binary_data(payload);
689+
let key = T::ConvertIntoAccountId32::convert(signer.clone());
692690

693-
ensure!(signature.verify(&wrapped_payload[..], &key), Error::<T>::InvalidSignature);
691+
ensure!(
692+
common_runtime::signature::check_signature(signature, key, payload),
693+
Error::<T>::InvalidSignature
694+
);
694695

695696
Ok(())
696697
}

runtime/common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pub mod constants;
44
pub mod extensions;
55
pub mod fee;
66
pub mod proxy;
7+
pub mod signature;
78
pub mod weights;
89

910
/// Macro to set a value (e.g. when using the `parameter_types` macro) to either a production value

runtime/common/src/signature.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
use common_primitives::utils::wrap_binary_data;
2+
use sp_runtime::{traits::Verify, AccountId32, MultiSignature};
3+
use sp_std::vec::Vec;
4+
5+
pub fn check_signature(signature: &MultiSignature, signer: AccountId32, payload: Vec<u8>) -> bool {
6+
let verify_signature = |payload: &[u8]| signature.verify(payload, &signer.clone().into());
7+
8+
if verify_signature(&payload) {
9+
return true;
10+
}
11+
12+
let wrapped_payload = wrap_binary_data(payload);
13+
verify_signature(&wrapped_payload)
14+
}
15+
16+
#[cfg(test)]
17+
use sp_core::{sr25519, Pair};
18+
19+
#[test]
20+
fn test_verify_signature_with_wrapped_bytes() {
21+
let (key_pair_delegator, _) = sr25519::Pair::generate();
22+
23+
let payload = b"test_payload".to_vec();
24+
let encode_add_provider_data = wrap_binary_data(payload.clone());
25+
26+
let signature: MultiSignature = key_pair_delegator.sign(&encode_add_provider_data).into();
27+
28+
assert!(check_signature(&signature, key_pair_delegator.public().into(), payload.clone()));
29+
}
30+
31+
#[test]
32+
fn test_verify_signature_without_wrapped_bytes() {
33+
let (signer, _) = sr25519::Pair::generate();
34+
35+
let payload = b"test_payload".to_vec();
36+
37+
let signature: MultiSignature = signer.sign(&payload).into();
38+
39+
assert!(check_signature(&signature, signer.public().into(), payload));
40+
}
41+
42+
#[test]
43+
fn test_check_signature_with_invalid_signature() {
44+
let (signer, _) = sr25519::Pair::generate();
45+
46+
let payload = b"test_payload".to_vec();
47+
48+
let signature: MultiSignature = signer.sign(&payload).into();
49+
50+
let invalid_payload = b"invalid_payload".to_vec();
51+
52+
assert!(!check_signature(&signature, signer.public().into(), invalid_payload));
53+
}

runtime/frequency/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
377377
spec_name: create_runtime_str!("frequency"),
378378
impl_name: create_runtime_str!("frequency"),
379379
authoring_version: 1,
380-
spec_version: 117,
380+
spec_version: 118,
381381
impl_version: 0,
382382
apis: apis::RUNTIME_API_VERSIONS,
383383
transaction_version: 1,
@@ -391,7 +391,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
391391
spec_name: create_runtime_str!("frequency-testnet"),
392392
impl_name: create_runtime_str!("frequency"),
393393
authoring_version: 1,
394-
spec_version: 117,
394+
spec_version: 118,
395395
impl_version: 0,
396396
apis: apis::RUNTIME_API_VERSIONS,
397397
transaction_version: 1,

0 commit comments

Comments
 (0)