1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
use crate::{auto_validate::AutoValidate, json_rpc::JsonRpcClientWrapper, TransactionContext};
use diem_crypto::ed25519::Ed25519PublicKey;
use diem_global_constants::{OPERATOR_ACCOUNT, OPERATOR_KEY};
use diem_management::{error::Error, transaction::build_raw_transaction};
use diem_transaction_builder::stdlib as transaction_builder;
use diem_types::{
account_address::AccountAddress,
transaction::{authenticator::AuthenticationKey, Transaction},
};
use serde::Serialize;
use std::convert::TryFrom;
use structopt::StructOpt;
#[derive(Debug, StructOpt)]
pub struct AccountResource {
#[structopt(long, help = "Account address to display the account resource")]
account_address: AccountAddress,
#[structopt(flatten)]
config: diem_management::config::ConfigPath,
#[structopt(long, required_unless = "config")]
json_server: Option<String>,
}
impl AccountResource {
pub fn execute(self) -> Result<SimplifiedAccountResource, Error> {
let config = self.config.load()?.override_json_server(&self.json_server);
let client = JsonRpcClientWrapper::new(config.json_server);
let account_resource = client.account_resource(self.account_address)?;
Ok(SimplifiedAccountResource {
account: self.account_address,
authentication_key: hex::encode(account_resource.authentication_key()),
sequence_number: account_resource.sequence_number(),
})
}
}
#[derive(Serialize)]
pub struct SimplifiedAccountResource {
pub account: AccountAddress,
pub authentication_key: String,
pub sequence_number: u64,
}
#[derive(Debug, StructOpt)]
pub struct RotateOperatorKey {
#[structopt(long, required_unless = "config")]
json_server: Option<String>,
#[structopt(flatten)]
validator_config: diem_management::validator_config::ValidatorConfig,
#[structopt(flatten)]
auto_validate: AutoValidate,
}
impl RotateOperatorKey {
pub fn execute(self) -> Result<(TransactionContext, Ed25519PublicKey), Error> {
let config = self
.validator_config
.config()?
.override_json_server(&self.json_server);
let mut storage = config.validator_backend();
let client = JsonRpcClientWrapper::new(config.json_server.clone());
let operator_account = storage.account_address(OPERATOR_ACCOUNT)?;
let account_resource = client.account_resource(operator_account)?;
let on_chain_key = match AuthenticationKey::try_from(account_resource.authentication_key())
{
Ok(auth_key) => auth_key,
Err(e) => {
return Err(Error::UnexpectedError(format!(
"Invalid authentication key found in account resource. Error: {}",
e
)));
}
};
let mut current_storage_key = storage.ed25519_public_from_private(OPERATOR_KEY)?;
let new_storage_key = if on_chain_key == AuthenticationKey::ed25519(¤t_storage_key) {
storage.rotate_key(OPERATOR_KEY)?
} else {
let new_storage_key = current_storage_key;
current_storage_key =
storage.ed25519_public_from_private_previous_version(OPERATOR_KEY)?;
new_storage_key
};
let sequence_number = client.sequence_number(operator_account)?;
let rotate_key_script =
transaction_builder::encode_rotate_authentication_key_script_function(
AuthenticationKey::ed25519(&new_storage_key).to_vec(),
);
let rotate_key_txn = build_raw_transaction(
config.chain_id,
operator_account,
sequence_number,
rotate_key_script.into_script_function(),
);
let rotate_key_txn = storage.sign_using_version(
OPERATOR_KEY,
current_storage_key,
"rotate-operator-key",
rotate_key_txn,
)?;
let rotate_key_txn = Transaction::UserTransaction(rotate_key_txn);
let mut transaction_context =
client.submit_transaction(rotate_key_txn.as_signed_user_txn().unwrap().clone())?;
transaction_context = self
.auto_validate
.execute(config.json_server, transaction_context)?;
Ok((transaction_context, new_storage_key))
}
}