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
use super::Client;
use crate::{Error, Result};
use sn_interface::{
messaging::{
data::{ClientMsg, DataCmd},
ClientAuth, MsgId, WireMsg,
},
types::{PublicKey, Signature},
};
use bytes::Bytes;
use xor_name::XorName;
impl Client {
pub fn sign(&self, data: &[u8]) -> Signature {
self.keypair.sign(data)
}
pub async fn send_signed_cmd(
&self,
dst_address: XorName,
client_pk: PublicKey,
serialised_cmd: Bytes,
signature: Signature,
is_spend_cmd: bool,
) -> Result<()> {
let auth = ClientAuth {
public_key: client_pk,
signature,
};
let msg_id = MsgId::new();
if let Some(cmd_timeout) = self.cmd_timeout {
tokio::time::timeout(cmd_timeout, async {
self.session
.send_cmd(dst_address, auth, serialised_cmd, is_spend_cmd, msg_id)
.await
})
.await
.map_err(|_| Error::CmdAckValidationTimeout {
msg_id,
elapsed: cmd_timeout,
dst_address,
})?
} else {
self.session
.send_cmd(dst_address, auth, serialised_cmd, is_spend_cmd, msg_id)
.await
}
}
#[instrument(skip_all, level = "debug", name = "client-api send cmd")]
pub async fn send_cmd(&self, cmd: DataCmd) -> Result<()> {
let client_pk = self.public_key();
let dst_name = cmd.dst_name();
let debug_cmd = format!("{:?}", cmd);
debug!("Attempting {debug_cmd}");
let is_spend_cmd = matches!(cmd, DataCmd::Spentbook(_));
let serialised_cmd = {
let msg = ClientMsg::Cmd(cmd);
WireMsg::serialize_msg_payload(&msg)?
};
let signature = self.sign(&serialised_cmd);
let res = self
.send_signed_cmd(dst_name, client_pk, serialised_cmd, signature, is_spend_cmd)
.await;
if res.is_ok() {
debug!("{debug_cmd} sent okay: {res:?}");
} else {
trace!("Failed response on {debug_cmd}, response: {:?}", res);
}
res
}
}