Skip to content

Commit 99246c2

Browse files
authored
Drozdziak1/refactor p2w autoattest py (#502)
* p2w_autoattest.py: Stop using non-daemon mode * wormhole_attester: Remove non-daemon mode and its uses, v3.0.0 We used to need non-daemon mode to run a manual healthcheck on the attester process and its configuration. Currently, we're able to handle this much better with the build-in healthcheck HTTP endpoint. For production, we should be able to get rid of p2w_autoattest.py entirely. Co-authored-by: Stan Drozd <stan@pyth.network>
1 parent 9cbdeb3 commit 99246c2

File tree

5 files changed

+4
-209
lines changed

5 files changed

+4
-209
lines changed

third_party/pyth/p2w_autoattest.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -168,34 +168,6 @@
168168
# modules like async HTTP requests and tokio runtime logs
169169
os.environ["RUST_LOG"] = os.environ.get("RUST_LOG", "info")
170170

171-
# Send the first attestation in one-shot mode for testing
172-
first_attest_result = run_or_die(
173-
[
174-
"pwhac",
175-
"--commitment",
176-
"confirmed",
177-
"--p2w-addr",
178-
P2W_SOL_ADDRESS,
179-
"--rpc-url",
180-
SOL_RPC_URL,
181-
"--payer",
182-
SOL_PAYER_KEYPAIR,
183-
"attest",
184-
"-f",
185-
P2W_ATTESTATION_CFG,
186-
"--timeout",
187-
P2W_RPC_TIMEOUT_SECS,
188-
],
189-
capture_output=True,
190-
debug = True,
191-
)
192-
193-
logging.info("p2w_autoattest ready to roll!")
194-
195-
# Let k8s know the service is up
196-
readiness_thread = threading.Thread(target=readiness, daemon=True)
197-
readiness_thread.start()
198-
199171
# Do not exit this script if a continuous attestation stops for
200172
# whatever reason (this avoids k8s restart penalty)
201173
while True:
@@ -214,7 +186,6 @@
214186
"attest",
215187
"-f",
216188
P2W_ATTESTATION_CFG,
217-
"-d",
218189
"--timeout",
219190
P2W_RPC_TIMEOUT_SECS,
220191
]

wormhole-attester/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wormhole-attester/client/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "pyth-wormhole-attester-client"
3-
version = "2.0.0"
3+
version = "3.0.0"
44
edition = "2018"
55

66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

wormhole-attester/client/src/cli.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -59,27 +59,6 @@ pub enum Action {
5959
Attest {
6060
#[clap(short = 'f', long = "--config", help = "Attestation YAML config")]
6161
attestation_cfg: PathBuf,
62-
#[clap(
63-
short = 'n',
64-
long = "--n-retries",
65-
help = "How many times to retry send_transaction() on each batch before flagging a failure. Only active outside daemon mode",
66-
default_value = "5"
67-
)]
68-
n_retries: usize,
69-
#[clap(
70-
short = 'i',
71-
long = "--retry-interval",
72-
help = "How long to wait between send_transaction
73-
retries. Only active outside daemon mode",
74-
default_value = "5"
75-
)]
76-
retry_interval_secs: u64,
77-
#[clap(
78-
short = 'd',
79-
long = "--daemon",
80-
help = "Do not stop attesting. In this mode, this program will behave more like a daemon and continuously attest the specified symbols."
81-
)]
82-
daemon: bool,
8362
#[clap(
8463
short = 't',
8564
long = "--timeout",

wormhole-attester/client/src/main.rs

Lines changed: 2 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -223,11 +223,8 @@ async fn main() -> Result<(), ErrBox> {
223223
}
224224
Action::Attest {
225225
ref attestation_cfg,
226-
n_retries,
227-
retry_interval_secs,
228226
confirmation_timeout_secs,
229227
metrics_bind_addr,
230-
daemon,
231228
} => {
232229
// Load the attestation config yaml
233230
let attestation_cfg: AttestationConfig =
@@ -249,26 +246,7 @@ async fn main() -> Result<(), ErrBox> {
249246
Duration::from_millis(attestation_cfg.min_rpc_interval_ms),
250247
));
251248

252-
if daemon {
253-
handle_attest_daemon_mode(
254-
rpc_cfg,
255-
payer,
256-
p2w_addr,
257-
attestation_cfg,
258-
metrics_bind_addr,
259-
)
260-
.await?;
261-
} else {
262-
handle_attest_non_daemon_mode(
263-
attestation_cfg,
264-
rpc_cfg,
265-
p2w_addr,
266-
payer,
267-
n_retries,
268-
Duration::from_secs(retry_interval_secs),
269-
)
270-
.await?;
271-
}
249+
handle_attest(rpc_cfg, payer, p2w_addr, attestation_cfg, metrics_bind_addr).await?;
272250
}
273251
Action::GetEmitter => unreachable! {}, // It is handled early in this function.
274252
Action::SetIsActive {
@@ -296,7 +274,7 @@ async fn main() -> Result<(), ErrBox> {
296274
}
297275

298276
/// Continuously send batch attestations for symbols of an attestation config.
299-
async fn handle_attest_daemon_mode(
277+
async fn handle_attest(
300278
rpc_cfg: Arc<RLMutex<RpcCfg>>,
301279
payer: Keypair,
302280
p2w_addr: Pubkey,
@@ -463,76 +441,6 @@ async fn lock_and_make_rpc(rlmtx: &RLMutex<RpcCfg>) -> RpcClient {
463441
RpcClient::new_with_timeout_and_commitment(url, timeout, commitment)
464442
}
465443

466-
/// Non-daemon attestation scheduling
467-
async fn handle_attest_non_daemon_mode(
468-
attestation_cfg: AttestationConfig,
469-
rpc_cfg: Arc<RLMutex<RpcCfg>>,
470-
p2w_addr: Pubkey,
471-
payer: Keypair,
472-
n_retries: usize,
473-
retry_interval: Duration,
474-
) -> Result<(), ErrBox> {
475-
let p2w_cfg = get_config_account(&lock_and_make_rpc(&rpc_cfg).await, &p2w_addr).await?;
476-
477-
let batch_config =
478-
attestation_config_to_batches(&rpc_cfg, &attestation_cfg, p2w_cfg.max_batch_size as usize)
479-
.await
480-
.unwrap_or_else(|_| {
481-
attestation_cfg.instantiate_batches(&[], p2w_cfg.max_batch_size as usize)
482-
});
483-
484-
let batches: Vec<_> = batch_config
485-
.into_iter()
486-
.map(|x| BatchState::new(&x))
487-
.collect();
488-
let batch_count = batches.len();
489-
490-
// For enforcing min_msg_reuse_interval_ms, we keep a piece of
491-
// state that creates or reuses accounts if enough time had
492-
// passed
493-
let message_q_mtx = Arc::new(Mutex::new(P2WMessageQueue::new(
494-
Duration::from_millis(attestation_cfg.min_msg_reuse_interval_ms),
495-
attestation_cfg.max_msg_accounts as usize,
496-
)));
497-
498-
let retry_jobs = batches.into_iter().enumerate().map(|(idx, batch_state)| {
499-
attestation_retry_job(AttestationRetryJobArgs {
500-
batch_no: idx + 1,
501-
batch_count,
502-
group_name: batch_state.group_name,
503-
symbols: batch_state.symbols,
504-
n_retries,
505-
retry_interval,
506-
rpc_cfg: rpc_cfg.clone(),
507-
p2w_addr,
508-
p2w_config: p2w_cfg.clone(),
509-
payer: Keypair::from_bytes(&payer.to_bytes()).unwrap(),
510-
message_q_mtx: message_q_mtx.clone(),
511-
})
512-
});
513-
514-
let results = futures::future::join_all(retry_jobs).await;
515-
516-
// After completing, we count any errors coming from the sched
517-
// futs.
518-
let errors: Vec<_> = results
519-
.iter()
520-
.enumerate()
521-
.filter_map(|(idx, r)| {
522-
r.as_ref()
523-
.err()
524-
.map(|e| format!("Error {}: {:?}\n", idx + 1, e))
525-
})
526-
.collect();
527-
528-
if !errors.is_empty() {
529-
let err_lines = errors.join("\n");
530-
let msg = format!("{} batches failed:\n{}", errors.len(), err_lines);
531-
error!("{}", msg);
532-
return Err(msg.into());
533-
}
534-
Ok(())
535-
}
536444

537445
/// Generate batches to attest by retrieving the on-chain product account data and grouping it
538446
/// according to the configuration in `attestation_cfg`.
@@ -692,69 +600,6 @@ async fn attestation_sched_job(args: AttestationSchedJobArgs) -> Result<(), ErrB
692600
}
693601
}
694602

695-
pub struct AttestationRetryJobArgs {
696-
pub batch_no: usize,
697-
pub batch_count: usize,
698-
pub group_name: String,
699-
pub symbols: Vec<P2WSymbol>,
700-
pub n_retries: usize,
701-
pub retry_interval: Duration,
702-
pub rpc_cfg: Arc<RLMutex<RpcCfg>>,
703-
pub p2w_addr: Pubkey,
704-
pub p2w_config: Pyth2WormholeConfig,
705-
pub payer: Keypair,
706-
pub message_q_mtx: Arc<Mutex<P2WMessageQueue>>,
707-
}
708-
709-
/// A future that cranks a batch up to n_retries times, pausing for
710-
/// retry_interval in between; Used exclusively in non-daemon mode
711-
async fn attestation_retry_job(args: AttestationRetryJobArgs) -> Result<(), ErrBoxSend> {
712-
let AttestationRetryJobArgs {
713-
batch_no,
714-
batch_count,
715-
group_name,
716-
symbols,
717-
n_retries,
718-
retry_interval,
719-
rpc_cfg,
720-
p2w_addr,
721-
p2w_config,
722-
payer,
723-
message_q_mtx,
724-
} = args;
725-
726-
let mut res = Err(
727-
"attestation_retry_job INTERNAL: Could not get a single attestation job result"
728-
.to_string()
729-
.into(),
730-
);
731-
732-
for _i in 0..=n_retries {
733-
res = attestation_job(AttestationJobArgs {
734-
rlmtx: rpc_cfg.clone(),
735-
batch_no,
736-
batch_count,
737-
group_name: group_name.clone(),
738-
p2w_addr,
739-
config: p2w_config.clone(),
740-
payer: Keypair::from_bytes(&payer.to_bytes()).unwrap(), // Keypair has no clone
741-
symbols: symbols.clone(),
742-
max_jobs_sema: Arc::new(Semaphore::new(1)), // Not important for non-daemon mode
743-
message_q_mtx: message_q_mtx.clone(),
744-
})
745-
.await;
746-
747-
// Finish early on success
748-
if res.is_ok() {
749-
break;
750-
}
751-
752-
tokio::time::sleep(retry_interval).await;
753-
}
754-
755-
res
756-
}
757-
758603
/// Arguments for attestation_job(). This struct rules out same-type
759604
/// ordering errors due to the large argument count
760605
pub struct AttestationJobArgs {

0 commit comments

Comments
 (0)