-
Notifications
You must be signed in to change notification settings - Fork 56
/
Copy pathlogic_call_relaying.rs
143 lines (135 loc) · 5.06 KB
/
logic_call_relaying.rs
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
139
140
141
142
143
use cosmos_gravity::query::{get_latest_logic_calls, get_logic_call_signatures};
use ethereum_gravity::one_eth_f32;
use ethereum_gravity::{
logic_call::send_eth_logic_call, types::EthClient, utils::get_logic_call_nonce,
};
use ethers::types::Address as EthAddress;
use gravity_proto::gravity::query_client::QueryClient as GravityQueryClient;
use gravity_utils::ethereum::{bytes_to_hex_str, downcast_to_f32};
use gravity_utils::types::{LogicCallConfirmResponse, Valset};
use gravity_utils::{message_signatures::encode_logic_call_confirm_hashed, types::LogicCall};
use std::time::Duration;
use tonic::transport::Channel;
#[allow(clippy::too_many_arguments)]
pub async fn relay_logic_calls(
// the validator set currently in the contract on Ethereum
current_valset: Valset,
eth_client: EthClient,
grpc_client: &mut GravityQueryClient<Channel>,
gravity_contract_address: EthAddress,
gravity_id: String,
timeout: Duration,
eth_gas_price_multiplier: f32,
) {
let latest_calls = match get_latest_logic_calls(grpc_client).await {
Ok(calls) => {
debug!("Latest Logic calls {:?}", calls);
calls
}
Err(err) => {
error!("Error while retrieving latest logic calls: {:?}", err);
return;
}
};
let mut oldest_signed_call: Option<LogicCall> = None;
let mut oldest_signatures: Option<Vec<LogicCallConfirmResponse>> = None;
for call in latest_calls {
let sigs = get_logic_call_signatures(
grpc_client,
call.invalidation_id.clone(),
call.invalidation_nonce,
)
.await;
debug!("Got sigs {:?}", sigs);
if let Ok(sigs) = sigs {
let hash = encode_logic_call_confirm_hashed(gravity_id.clone(), call.clone());
// this checks that the signatures for the batch are actually possible to submit to the chain
if current_valset.order_sigs(&hash, &sigs).is_ok() {
oldest_signed_call = Some(call);
oldest_signatures = Some(sigs);
} else {
warn!(
"LogicCall {}/{} can not be submitted yet, waiting for more signatures",
bytes_to_hex_str(&call.invalidation_id),
call.invalidation_nonce
);
}
} else {
error!(
"could not get signatures for {}/{} with {:?}",
bytes_to_hex_str(&call.invalidation_id),
call.invalidation_nonce,
sigs
);
}
}
if oldest_signed_call.is_none() {
debug!("Could not find Call with signatures! exiting");
return;
}
let oldest_signed_call = oldest_signed_call.unwrap();
let oldest_signatures = oldest_signatures.unwrap();
let latest_ethereum_call = get_logic_call_nonce(
gravity_contract_address,
oldest_signed_call.invalidation_id.clone(),
eth_client.clone(),
)
.await;
if latest_ethereum_call.is_err() {
error!(
"Failed to get latest Ethereum LogicCall with {:?}",
latest_ethereum_call
);
return;
}
let latest_ethereum_call = latest_ethereum_call.unwrap();
let latest_cosmos_call_nonce = oldest_signed_call.clone().invalidation_nonce;
if latest_cosmos_call_nonce > latest_ethereum_call {
let cost = ethereum_gravity::logic_call::estimate_logic_call_cost(
current_valset.clone(),
oldest_signed_call.clone(),
&oldest_signatures,
gravity_contract_address,
gravity_id.clone(),
eth_client.clone(),
)
.await;
if cost.is_err() {
error!("LogicCall cost estimate failed with {:?}", cost);
return;
}
let mut cost = cost.unwrap();
let total_cost = downcast_to_f32(cost.get_total());
if total_cost.is_none() {
error!(
"Total gas cost greater than f32 max, skipping logic call submission: {}",
oldest_signed_call.invalidation_nonce
);
return;
}
let total_cost = total_cost.unwrap();
let gas_price_as_f32 = downcast_to_f32(cost.gas_price).unwrap(); // if the total cost isn't greater, this isn't
info!(
"We have detected latest LogicCall {} but latest on Ethereum is {} This LogicCall is estimated to cost {} Gas / {:.4} ETH to submit",
latest_cosmos_call_nonce,
latest_ethereum_call,
cost.gas_price.clone(),
total_cost / one_eth_f32(),
);
cost.gas_price = ((gas_price_as_f32 * eth_gas_price_multiplier) as u128).into();
let res = send_eth_logic_call(
current_valset,
oldest_signed_call,
&oldest_signatures,
timeout,
gravity_contract_address,
gravity_id.clone(),
cost,
eth_client.clone(),
)
.await;
if res.is_err() {
info!("LogicCall submission failed with {:?}", res);
}
}
}