mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 13:31:10 +00:00
0de7d9bb64
* Adds `author_rotateKeys` RPC `author_rotateKeys` will rotate all session keys, store them into the keystore and returns their encoded public keys as result. These encoded public keys can be used directly to send the transaction to the chain. * Review comments
292 lines
9.5 KiB
Rust
292 lines
9.5 KiB
Rust
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
|
|
// This file is part of Substrate.
|
|
|
|
// Substrate 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.
|
|
|
|
// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use super::*;
|
|
use self::error::Error;
|
|
|
|
use assert_matches::assert_matches;
|
|
use primitives::storage::well_known_keys;
|
|
use sr_io::blake2_256;
|
|
use test_client::{
|
|
prelude::*,
|
|
consensus::BlockOrigin,
|
|
runtime,
|
|
};
|
|
use substrate_executor::NativeExecutionDispatch;
|
|
|
|
#[test]
|
|
fn should_return_storage() {
|
|
let core = tokio::runtime::Runtime::new().unwrap();
|
|
let client = Arc::new(test_client::new());
|
|
let genesis_hash = client.genesis_hash();
|
|
let client = State::new(client, Subscriptions::new(Arc::new(core.executor())));
|
|
let key = StorageKey(b":code".to_vec());
|
|
|
|
assert_eq!(
|
|
client.storage(key.clone(), Some(genesis_hash).into())
|
|
.map(|x| x.map(|x| x.0.len())).unwrap().unwrap() as usize,
|
|
LocalExecutor::native_equivalent().len(),
|
|
);
|
|
assert_matches!(
|
|
client.storage_hash(key.clone(), Some(genesis_hash).into()).map(|x| x.is_some()),
|
|
Ok(true)
|
|
);
|
|
assert_eq!(
|
|
client.storage_size(key.clone(), None).unwrap().unwrap() as usize,
|
|
LocalExecutor::native_equivalent().len(),
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn should_return_child_storage() {
|
|
let core = tokio::runtime::Runtime::new().unwrap();
|
|
let client = Arc::new(test_client::TestClientBuilder::new()
|
|
.add_child_storage("test", "key", vec![42_u8])
|
|
.build());
|
|
let genesis_hash = client.genesis_hash();
|
|
let client = State::new(client, Subscriptions::new(Arc::new(core.executor())));
|
|
let child_key = StorageKey(well_known_keys::CHILD_STORAGE_KEY_PREFIX.iter().chain(b"test").cloned().collect());
|
|
let key = StorageKey(b"key".to_vec());
|
|
|
|
|
|
assert_matches!(
|
|
client.child_storage(child_key.clone(), key.clone(), Some(genesis_hash).into()),
|
|
Ok(Some(StorageData(ref d))) if d[0] == 42 && d.len() == 1
|
|
);
|
|
assert_matches!(
|
|
client.child_storage_hash(child_key.clone(), key.clone(), Some(genesis_hash).into())
|
|
.map(|x| x.is_some()),
|
|
Ok(true)
|
|
);
|
|
assert_matches!(
|
|
client.child_storage_size(child_key.clone(), key.clone(), None),
|
|
Ok(Some(1))
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn should_call_contract() {
|
|
let core = tokio::runtime::Runtime::new().unwrap();
|
|
let client = Arc::new(test_client::new());
|
|
let genesis_hash = client.genesis_hash();
|
|
let client = State::new(client, Subscriptions::new(Arc::new(core.executor())));
|
|
|
|
assert_matches!(
|
|
client.call("balanceOf".into(), Bytes(vec![1,2,3]), Some(genesis_hash).into()),
|
|
Err(Error::Client(client::error::Error::Execution(_)))
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn should_notify_about_storage_changes() {
|
|
let mut core = tokio::runtime::Runtime::new().unwrap();
|
|
let remote = core.executor();
|
|
let (subscriber, id, transport) = Subscriber::new_test("test");
|
|
|
|
{
|
|
let api = State::new(Arc::new(test_client::new()), Subscriptions::new(Arc::new(remote)));
|
|
|
|
api.subscribe_storage(Default::default(), subscriber, None.into());
|
|
|
|
// assert id assigned
|
|
assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1))));
|
|
|
|
let mut builder = api.client.new_block(Default::default()).unwrap();
|
|
builder.push_transfer(runtime::Transfer {
|
|
from: AccountKeyring::Alice.into(),
|
|
to: AccountKeyring::Ferdie.into(),
|
|
amount: 42,
|
|
nonce: 0,
|
|
}).unwrap();
|
|
api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
|
|
}
|
|
|
|
// assert notification sent to transport
|
|
let (notification, next) = core.block_on(transport.into_future()).unwrap();
|
|
assert!(notification.is_some());
|
|
// no more notifications on this channel
|
|
assert_eq!(core.block_on(next.into_future()).unwrap().0, None);
|
|
}
|
|
|
|
#[test]
|
|
fn should_send_initial_storage_changes_and_notifications() {
|
|
let mut core = tokio::runtime::Runtime::new().unwrap();
|
|
let remote = core.executor();
|
|
let (subscriber, id, transport) = Subscriber::new_test("test");
|
|
|
|
{
|
|
let api = State::new(Arc::new(test_client::new()), Subscriptions::new(Arc::new(remote)));
|
|
|
|
let alice_balance_key = blake2_256(&runtime::system::balance_of_key(AccountKeyring::Alice.into()));
|
|
|
|
api.subscribe_storage(Default::default(), subscriber, Some(vec![
|
|
StorageKey(alice_balance_key.to_vec()),
|
|
]).into());
|
|
|
|
// assert id assigned
|
|
assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1))));
|
|
|
|
let mut builder = api.client.new_block(Default::default()).unwrap();
|
|
builder.push_transfer(runtime::Transfer {
|
|
from: AccountKeyring::Alice.into(),
|
|
to: AccountKeyring::Ferdie.into(),
|
|
amount: 42,
|
|
nonce: 0,
|
|
}).unwrap();
|
|
api.client.import(BlockOrigin::Own, builder.bake().unwrap()).unwrap();
|
|
}
|
|
|
|
// assert initial values sent to transport
|
|
let (notification, next) = core.block_on(transport.into_future()).unwrap();
|
|
assert!(notification.is_some());
|
|
// assert notification sent to transport
|
|
let (notification, next) = core.block_on(next.into_future()).unwrap();
|
|
assert!(notification.is_some());
|
|
// no more notifications on this channel
|
|
assert_eq!(core.block_on(next.into_future()).unwrap().0, None);
|
|
}
|
|
|
|
#[test]
|
|
fn should_query_storage() {
|
|
fn run_tests(client: Arc<TestClient>) {
|
|
let core = tokio::runtime::Runtime::new().unwrap();
|
|
let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor())));
|
|
|
|
let add_block = |nonce| {
|
|
let mut builder = client.new_block(Default::default()).unwrap();
|
|
// fake change: None -> None -> None
|
|
builder.push_storage_change(vec![1], None).unwrap();
|
|
// fake change: None -> Some(value) -> Some(value)
|
|
builder.push_storage_change(vec![2], Some(vec![2])).unwrap();
|
|
// actual change: None -> Some(value) -> None
|
|
builder.push_storage_change(vec![3], if nonce == 0 { Some(vec![3]) } else { None }).unwrap();
|
|
// actual change: None -> Some(value)
|
|
builder.push_storage_change(vec![4], if nonce == 0 { None } else { Some(vec![4]) }).unwrap();
|
|
// actual change: Some(value1) -> Some(value2)
|
|
builder.push_storage_change(vec![5], Some(vec![nonce as u8])).unwrap();
|
|
let block = builder.bake().unwrap();
|
|
let hash = block.header.hash();
|
|
client.import(BlockOrigin::Own, block).unwrap();
|
|
hash
|
|
};
|
|
let block1_hash = add_block(0);
|
|
let block2_hash = add_block(1);
|
|
let genesis_hash = client.genesis_hash();
|
|
|
|
let mut expected = vec![
|
|
StorageChangeSet {
|
|
block: genesis_hash,
|
|
changes: vec![
|
|
(StorageKey(vec![1]), None),
|
|
(StorageKey(vec![2]), None),
|
|
(StorageKey(vec![3]), None),
|
|
(StorageKey(vec![4]), None),
|
|
(StorageKey(vec![5]), None),
|
|
],
|
|
},
|
|
StorageChangeSet {
|
|
block: block1_hash,
|
|
changes: vec![
|
|
(StorageKey(vec![2]), Some(StorageData(vec![2]))),
|
|
(StorageKey(vec![3]), Some(StorageData(vec![3]))),
|
|
(StorageKey(vec![5]), Some(StorageData(vec![0]))),
|
|
],
|
|
},
|
|
];
|
|
|
|
// Query changes only up to block1
|
|
let keys = (1..6).map(|k| StorageKey(vec![k])).collect::<Vec<_>>();
|
|
let result = api.query_storage(
|
|
keys.clone(),
|
|
genesis_hash,
|
|
Some(block1_hash).into(),
|
|
);
|
|
|
|
assert_eq!(result.unwrap(), expected);
|
|
|
|
// Query all changes
|
|
let result = api.query_storage(
|
|
keys.clone(),
|
|
genesis_hash,
|
|
None.into(),
|
|
);
|
|
|
|
expected.push(StorageChangeSet {
|
|
block: block2_hash,
|
|
changes: vec![
|
|
(StorageKey(vec![3]), None),
|
|
(StorageKey(vec![4]), Some(StorageData(vec![4]))),
|
|
(StorageKey(vec![5]), Some(StorageData(vec![1]))),
|
|
],
|
|
});
|
|
assert_eq!(result.unwrap(), expected);
|
|
}
|
|
|
|
run_tests(Arc::new(test_client::new()));
|
|
run_tests(Arc::new(TestClientBuilder::new().set_support_changes_trie(true).build()));
|
|
}
|
|
|
|
#[test]
|
|
fn should_split_ranges() {
|
|
assert_eq!(split_range(1, None), (0..1, None));
|
|
assert_eq!(split_range(100, None), (0..100, None));
|
|
assert_eq!(split_range(1, Some(0)), (0..1, None));
|
|
assert_eq!(split_range(100, Some(50)), (0..50, Some(50..100)));
|
|
assert_eq!(split_range(100, Some(99)), (0..99, Some(99..100)));
|
|
}
|
|
|
|
|
|
#[test]
|
|
fn should_return_runtime_version() {
|
|
let core = tokio::runtime::Runtime::new().unwrap();
|
|
|
|
let client = Arc::new(test_client::new());
|
|
let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor())));
|
|
|
|
let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\
|
|
\"specVersion\":1,\"implVersion\":1,\"apis\":[[\"0xdf6acb689907609b\",2],\
|
|
[\"0x37e397fc7c91f5e4\",1],[\"0xd2bc9897eed08f15\",1],[\"0x40fe3ad401f8959a\",3],\
|
|
[\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\
|
|
[\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1]]}";
|
|
|
|
assert_eq!(
|
|
serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(),
|
|
result,
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn should_notify_on_runtime_version_initially() {
|
|
let mut core = tokio::runtime::Runtime::new().unwrap();
|
|
let (subscriber, id, transport) = Subscriber::new_test("test");
|
|
|
|
{
|
|
let client = Arc::new(test_client::new());
|
|
let api = State::new(client.clone(), Subscriptions::new(Arc::new(core.executor())));
|
|
|
|
api.subscribe_runtime_version(Default::default(), subscriber);
|
|
|
|
// assert id assigned
|
|
assert_eq!(core.block_on(id), Ok(Ok(SubscriptionId::Number(1))));
|
|
}
|
|
|
|
// assert initial version sent.
|
|
let (notification, next) = core.block_on(transport.into_future()).unwrap();
|
|
assert!(notification.is_some());
|
|
// no more notifications on this channel
|
|
assert_eq!(core.block_on(next.into_future()).unwrap().0, None);
|
|
}
|