mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 21:41:12 +00:00
1e24e45ea1
* Remove Default for AccountId * More removals of default * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/authorship/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * More work * More work * Remove old code * More work * pallet-asset-tx-payment * tips * sc-consensus-babe * sc-finality-grandpa * sc-consensus-babe-rpc * sc-cli * make npos crates accept non-default account (#10420) * minimal changes to make npos pallets all work * make this pesky reduce.rs a bit cleaner * more work * more work * Tests build * Fix imonline tests * Formatting * Fixes * Fixes * Fix bench * Fixes * Fixes * Fixes * Fixes * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Fixes * Formatting * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/finality-grandpa/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update client/keystore/src/local.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/staking/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update frame/staking/src/lib.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Update primitives/runtime/src/traits.rs Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> * Formatting Co-authored-by: Bastian Köcher <bkchr@users.noreply.github.com> Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com> Co-authored-by: kianenigma <kian@parity.io>
315 lines
8.8 KiB
Rust
315 lines
8.8 KiB
Rust
// This file is part of Substrate.
|
|
|
|
// Copyright (C) 2017-2021 Parity Technologies (UK) Ltd.
|
|
// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
|
|
|
|
// 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 <https://www.gnu.org/licenses/>.
|
|
|
|
use super::*;
|
|
|
|
use assert_matches::assert_matches;
|
|
use codec::Encode;
|
|
use futures::executor;
|
|
use sc_transaction_pool::{BasicPool, FullChainApi};
|
|
use sp_core::{
|
|
blake2_256,
|
|
crypto::{ByteArray, CryptoTypePublicPair, Pair},
|
|
ed25519,
|
|
hexdisplay::HexDisplay,
|
|
sr25519,
|
|
testing::{ED25519, SR25519},
|
|
H256,
|
|
};
|
|
use sp_keystore::testing::KeyStore;
|
|
use std::{mem, sync::Arc};
|
|
use substrate_test_runtime_client::{
|
|
self,
|
|
runtime::{Block, Extrinsic, SessionKeys, Transfer},
|
|
AccountKeyring, Backend, Client, DefaultTestClientBuilderExt, TestClientBuilderExt,
|
|
};
|
|
|
|
fn uxt(sender: AccountKeyring, nonce: u64) -> Extrinsic {
|
|
let tx = Transfer {
|
|
amount: Default::default(),
|
|
nonce,
|
|
from: sender.into(),
|
|
to: AccountKeyring::Bob.into(),
|
|
};
|
|
tx.into_signed_tx()
|
|
}
|
|
|
|
type FullTransactionPool = BasicPool<FullChainApi<Client<Backend>, Block>, Block>;
|
|
|
|
struct TestSetup {
|
|
pub client: Arc<Client<Backend>>,
|
|
pub keystore: Arc<KeyStore>,
|
|
pub pool: Arc<FullTransactionPool>,
|
|
}
|
|
|
|
impl Default for TestSetup {
|
|
fn default() -> Self {
|
|
let keystore = Arc::new(KeyStore::new());
|
|
let client_builder = substrate_test_runtime_client::TestClientBuilder::new();
|
|
let client = Arc::new(client_builder.set_keystore(keystore.clone()).build());
|
|
|
|
let spawner = sp_core::testing::TaskExecutor::new();
|
|
let pool =
|
|
BasicPool::new_full(Default::default(), true.into(), None, spawner, client.clone());
|
|
TestSetup { client, keystore, pool }
|
|
}
|
|
}
|
|
|
|
impl TestSetup {
|
|
fn author(&self) -> Author<FullTransactionPool, Client<Backend>> {
|
|
Author {
|
|
client: self.client.clone(),
|
|
pool: self.pool.clone(),
|
|
subscriptions: SubscriptionManager::new(Arc::new(crate::testing::TaskExecutor)),
|
|
keystore: self.keystore.clone(),
|
|
deny_unsafe: DenyUnsafe::No,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn submit_transaction_should_not_cause_error() {
|
|
let p = TestSetup::default().author();
|
|
let xt = uxt(AccountKeyring::Alice, 1).encode();
|
|
let h: H256 = blake2_256(&xt).into();
|
|
|
|
assert_matches!(
|
|
executor::block_on(AuthorApi::submit_extrinsic(&p, xt.clone().into())),
|
|
Ok(h2) if h == h2
|
|
);
|
|
assert!(executor::block_on(AuthorApi::submit_extrinsic(&p, xt.into())).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn submit_rich_transaction_should_not_cause_error() {
|
|
let p = TestSetup::default().author();
|
|
let xt = uxt(AccountKeyring::Alice, 0).encode();
|
|
let h: H256 = blake2_256(&xt).into();
|
|
|
|
assert_matches!(
|
|
executor::block_on(AuthorApi::submit_extrinsic(&p, xt.clone().into())),
|
|
Ok(h2) if h == h2
|
|
);
|
|
assert!(executor::block_on(AuthorApi::submit_extrinsic(&p, xt.into())).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn should_watch_extrinsic() {
|
|
// given
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let (subscriber, id_rx, data) = jsonrpc_pubsub::typed::Subscriber::new_test("test");
|
|
|
|
// when
|
|
p.watch_extrinsic(
|
|
Default::default(),
|
|
subscriber,
|
|
uxt(AccountKeyring::Alice, 0).encode().into(),
|
|
);
|
|
|
|
let id = executor::block_on(id_rx).unwrap().unwrap();
|
|
assert_matches!(id, SubscriptionId::String(_));
|
|
|
|
let id = match id {
|
|
SubscriptionId::String(id) => id,
|
|
_ => unreachable!(),
|
|
};
|
|
|
|
// check notifications
|
|
let replacement = {
|
|
let tx = Transfer {
|
|
amount: 5,
|
|
nonce: 0,
|
|
from: AccountKeyring::Alice.into(),
|
|
to: AccountKeyring::Bob.into(),
|
|
};
|
|
tx.into_signed_tx()
|
|
};
|
|
executor::block_on(AuthorApi::submit_extrinsic(&p, replacement.encode().into())).unwrap();
|
|
let (res, data) = executor::block_on(data.into_future());
|
|
|
|
let expected = Some(format!(
|
|
r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":"ready","subscription":"{}"}}}}"#,
|
|
id,
|
|
));
|
|
assert_eq!(res, expected);
|
|
|
|
let h = blake2_256(&replacement.encode());
|
|
let expected = Some(format!(
|
|
r#"{{"jsonrpc":"2.0","method":"test","params":{{"result":{{"usurped":"0x{}"}},"subscription":"{}"}}}}"#,
|
|
HexDisplay::from(&h),
|
|
id,
|
|
));
|
|
|
|
let res = executor::block_on(data.into_future()).0;
|
|
assert_eq!(res, expected);
|
|
}
|
|
|
|
#[test]
|
|
fn should_return_watch_validation_error() {
|
|
// given
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let (subscriber, id_rx, _data) = jsonrpc_pubsub::typed::Subscriber::new_test("test");
|
|
|
|
// when
|
|
p.watch_extrinsic(
|
|
Default::default(),
|
|
subscriber,
|
|
uxt(AccountKeyring::Alice, 179).encode().into(),
|
|
);
|
|
|
|
// then
|
|
let res = executor::block_on(id_rx).unwrap();
|
|
assert!(res.is_err(), "Expected the transaction to be rejected as invalid.");
|
|
}
|
|
|
|
#[test]
|
|
fn should_return_pending_extrinsics() {
|
|
let p = TestSetup::default().author();
|
|
|
|
let ex = uxt(AccountKeyring::Alice, 0);
|
|
executor::block_on(AuthorApi::submit_extrinsic(&p, ex.encode().into())).unwrap();
|
|
assert_matches!(
|
|
p.pending_extrinsics(),
|
|
Ok(ref expected) if *expected == vec![Bytes(ex.encode())]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn should_remove_extrinsics() {
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let ex1 = uxt(AccountKeyring::Alice, 0);
|
|
executor::block_on(p.submit_extrinsic(ex1.encode().into())).unwrap();
|
|
let ex2 = uxt(AccountKeyring::Alice, 1);
|
|
executor::block_on(p.submit_extrinsic(ex2.encode().into())).unwrap();
|
|
let ex3 = uxt(AccountKeyring::Bob, 0);
|
|
let hash3 = executor::block_on(p.submit_extrinsic(ex3.encode().into())).unwrap();
|
|
assert_eq!(setup.pool.status().ready, 3);
|
|
|
|
// now remove all 3
|
|
let removed = p
|
|
.remove_extrinsic(vec![
|
|
hash::ExtrinsicOrHash::Hash(hash3),
|
|
// Removing this one will also remove ex2
|
|
hash::ExtrinsicOrHash::Extrinsic(ex1.encode().into()),
|
|
])
|
|
.unwrap();
|
|
|
|
assert_eq!(removed.len(), 3);
|
|
}
|
|
|
|
#[test]
|
|
fn should_insert_key() {
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let suri = "//Alice";
|
|
let key_pair = ed25519::Pair::from_string(suri, None).expect("Generates keypair");
|
|
p.insert_key(
|
|
String::from_utf8(ED25519.0.to_vec()).expect("Keytype is a valid string"),
|
|
suri.to_string(),
|
|
key_pair.public().0.to_vec().into(),
|
|
)
|
|
.expect("Insert key");
|
|
|
|
let public_keys = SyncCryptoStore::keys(&*setup.keystore, ED25519).unwrap();
|
|
|
|
assert!(public_keys
|
|
.contains(&CryptoTypePublicPair(ed25519::CRYPTO_ID, key_pair.public().to_raw_vec())));
|
|
}
|
|
|
|
#[test]
|
|
fn should_rotate_keys() {
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let new_public_keys = p.rotate_keys().expect("Rotates the keys");
|
|
|
|
let session_keys =
|
|
SessionKeys::decode(&mut &new_public_keys[..]).expect("SessionKeys decode successfully");
|
|
|
|
let ed25519_public_keys = SyncCryptoStore::keys(&*setup.keystore, ED25519).unwrap();
|
|
let sr25519_public_keys = SyncCryptoStore::keys(&*setup.keystore, SR25519).unwrap();
|
|
|
|
assert!(ed25519_public_keys
|
|
.contains(&CryptoTypePublicPair(ed25519::CRYPTO_ID, session_keys.ed25519.to_raw_vec())));
|
|
assert!(sr25519_public_keys
|
|
.contains(&CryptoTypePublicPair(sr25519::CRYPTO_ID, session_keys.sr25519.to_raw_vec())));
|
|
}
|
|
|
|
#[test]
|
|
fn test_has_session_keys() {
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let non_existent_public_keys =
|
|
TestSetup::default().author().rotate_keys().expect("Rotates the keys");
|
|
|
|
let public_keys = p.rotate_keys().expect("Rotates the keys");
|
|
let test_vectors = vec![
|
|
(public_keys, Ok(true)),
|
|
(vec![1, 2, 3].into(), Err(Error::InvalidSessionKeys)),
|
|
(non_existent_public_keys, Ok(false)),
|
|
];
|
|
|
|
for (keys, result) in test_vectors {
|
|
assert_eq!(
|
|
result.map_err(|e| mem::discriminant(&e)),
|
|
p.has_session_keys(keys).map_err(|e| mem::discriminant(&e)),
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_has_key() {
|
|
let setup = TestSetup::default();
|
|
let p = setup.author();
|
|
|
|
let suri = "//Alice";
|
|
let alice_key_pair = ed25519::Pair::from_string(suri, None).expect("Generates keypair");
|
|
p.insert_key(
|
|
String::from_utf8(ED25519.0.to_vec()).expect("Keytype is a valid string"),
|
|
suri.to_string(),
|
|
alice_key_pair.public().0.to_vec().into(),
|
|
)
|
|
.expect("Insert key");
|
|
let bob_key_pair = ed25519::Pair::from_string("//Bob", None).expect("Generates keypair");
|
|
|
|
let test_vectors = vec![
|
|
(alice_key_pair.public().to_raw_vec().into(), ED25519, Ok(true)),
|
|
(alice_key_pair.public().to_raw_vec().into(), SR25519, Ok(false)),
|
|
(bob_key_pair.public().to_raw_vec().into(), ED25519, Ok(false)),
|
|
];
|
|
|
|
for (key, key_type, result) in test_vectors {
|
|
assert_eq!(
|
|
result.map_err(|e| mem::discriminant(&e)),
|
|
p.has_key(
|
|
key,
|
|
String::from_utf8(key_type.0.to_vec()).expect("Keytype is a valid string"),
|
|
)
|
|
.map_err(|e| mem::discriminant(&e)),
|
|
);
|
|
}
|
|
}
|