Newer
Older
use anyhow::{anyhow, Result};
use sp_core::{crypto::AccountId32, sr25519::Pair, Pair as _};
use std::ops::Deref;
use subxt::tx::{BaseExtrinsicParamsBuilder, PairSigner, TxStatus};
type SessionKeys = [u8; 128];
pub async fn rotate_keys(client: &Client) -> Result<SessionKeys> {
client
.rpc()
.rotate_keys()
.await?
.deref()
.try_into()
.map_err(|e| anyhow!("Session keys have wrong length: {:?}", e))
}
pub async fn set_session_keys(pair: Pair, client: Client, session_keys: SessionKeys) -> Result<()> {
client
.tx()
.sign_and_submit_then_watch(
&gdev::tx()
.authority_members()
.set_session_keys(session_keys),
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
Ok(())
}
pub async fn update_session_keys(pair: Pair, client: Client) -> Result<()> {
let session_keys = rotate_keys(&client).await?;
set_session_keys(pair, client, session_keys).await
}
pub async fn go_online(pair: Pair, client: Client) -> Result<()> {
if client
.storage()
.fetch(
&gdev::storage()
.session()
.next_keys(AccountId32::from(pair.public())),
None,
)
.await?
.is_none()
{
return Err(anyhow!("This account has not set session keys!"));
}
client
.tx()
.sign_and_submit_then_watch(
&gdev::tx().authority_members().go_online(),
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
Ok(())
}
pub async fn go_offline(pair: Pair, client: Client) -> Result<()> {
client
.tx()
.sign_and_submit_then_watch(
&gdev::tx().authority_members().go_offline(),
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
Ok(())
pub async fn online(client: Client, args: &Args) -> Result<()> {
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
let parent_hash = client
.storage()
.fetch(&gdev::storage().system().parent_hash(), None)
.await?
.unwrap();
let gql_client = reqwest::Client::builder()
.user_agent("gcli/0.1.0")
.build()?;
let mut identity_cache = cache::IdentityCache::new(
&client,
if args.no_indexer {
None
} else {
Some(Indexer {
gql_client,
gql_url: &args.indexer,
})
},
);
let online_authorities = client
.storage()
.fetch(
&gdev::storage().authority_members().online_authorities(),
Some(parent_hash),
)
.await?
.unwrap_or_default();
println!("Online:");
for identity_id in online_authorities {
println!(
" {}",
identity_cache
.fetch_identity(identity_id, parent_hash)
.await
.unwrap_or_else(|_| format!("{identity_id}"))
);
}
let incoming_authorities = client
.storage()
.fetch(
&gdev::storage().authority_members().incoming_authorities(),
Some(parent_hash),
)
.await?
.unwrap_or_default();
println!("Incoming:");
for identity_id in incoming_authorities {
println!(
" {}",
identity_cache
.fetch_identity(identity_id, parent_hash)
.await
.unwrap_or_else(|_| format!("{identity_id}"))
);
}
let outgoing_authorities = client
.storage()
.fetch(
&gdev::storage().authority_members().outgoing_authorities(),
Some(parent_hash),
)
.await?
.unwrap_or_default();
println!("Outgoing:");
for identity_id in outgoing_authorities {
println!(
" {}",
identity_cache
.fetch_identity(identity_id, parent_hash)
.await
.unwrap_or_else(|_| format!("{identity_id}"))
);
}
Ok(())
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/// emit a new smith cert from signer's identity to target identity
pub async fn emit_cert(args: Args, receiver: u32) -> Result<()> {
// issuer key
let pair = get_keys(
args.secret_format,
&args.address,
&args.secret,
NeededKeys::Secret,
)?
.1
.unwrap();
// connect to client
let client = Client::from_url(&args.url).await.unwrap();
// get issuer index
let issuer = commands::identity::get_idty_index_by_account_id(
client.clone(),
&AccountId32::from(pair.public()),
)
.await?
.ok_or(anyhow!("can not certify if not member"))?;
// submit and track certification
cert(client, pair, issuer, receiver).await?;
Ok(())
}
/// submit a certification and track progress
async fn cert(client: Client, pair: Pair, issuer: u32, receiver: u32) -> Result<()> {
let mut progress = client
.tx()
.sign_and_submit_then_watch(
&gdev::tx().smith_cert().add_cert(issuer, receiver),
&PairSigner::new(pair),
BaseExtrinsicParamsBuilder::new(),
)
.await?;
let in_block = loop {
if let Some(status) = progress.next_item().await {
match status? {
TxStatus::Ready => {
println!("transaction submitted to the network, waiting 6 seconds...");
}
TxStatus::InBlock(in_block) => break in_block,
TxStatus::Invalid => {
println!("Invalid");
}
_ => continue,
}
}
};
// get the block events and return if ExtrinsicFailed
let events = in_block.wait_for_success().await?;
// look for the expected event
let new_cert_event = events.find_first::<gdev::smith_cert::events::NewCert>()?;
let renew_cert_event = events.find_first::<gdev::smith_cert::events::RenewedCert>()?;
if let Some(event) = new_cert_event {
println!("{event:?}");
}
if let Some(event) = renew_cert_event {
println!("{event:?}");
}
Ok(())
}