Skip to content

Commit ac34081

Browse files
Reisenswimricky
authored andcommitted
fixup! pyth: introduce pyth accumulator library
1 parent 83a5f1b commit ac34081

File tree

1 file changed

+55
-31
lines changed

1 file changed

+55
-31
lines changed

runtime/src/bank.rs

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,6 +1280,23 @@ pub struct CommitTransactionCounts {
12801280
pub signature_count: u64,
12811281
}
12821282

1283+
/// Accumulator specific error type. It would be nice to use `transaction::Error` but it does
1284+
/// not include any `Custom` style variant we can leverage, so we introduce our own.
1285+
#[derive(Debug, thiserror::Error)]
1286+
enum AccumulatorUpdateError {
1287+
#[error("get_program_accounts failed to return accounts")]
1288+
GetProgramAccounts,
1289+
1290+
#[error("failed to serialize sequence account")]
1291+
FailedSequenceSerialization,
1292+
1293+
#[error("failed to serialize message account")]
1294+
FailedMessageSerialization,
1295+
1296+
#[error("io error")]
1297+
Io(#[from] std::io::Error),
1298+
}
1299+
12831300
impl Bank {
12841301
pub fn default_for_tests() -> Self {
12851302
Self::default_with_accounts(Accounts::default_for_tests())
@@ -2480,12 +2497,15 @@ impl Bank {
24802497
///
24812498
/// Note:
24822499
/// - Library imports are placed within this function to keep the diff against upstream small.
2483-
/// - Functionality is kept in the `solana-pyth` library to contain our new dependencies.
24842500
/// - This update will incur a performance hit on each slot, so must be kept efficient.
2485-
/// - Focused on Merkle temporarily and will be generalized to the Accumulator trait.
2486-
///
2487-
/// TODO: Remove dangerous unwrap() calls.
2501+
/// - Focused on Merkle for initial release but will generalise to more accumulators in future.
24882502
fn update_accumulator(&self) {
2503+
if let Err(e) = self.update_accumulator_impl() {
2504+
error!("Error updating accumulator: {:?}", e);
2505+
}
2506+
}
2507+
2508+
fn update_accumulator_impl(&self) -> std::result::Result<(), AccumulatorUpdateError> {
24892509
use {
24902510
byteorder::ReadBytesExt,
24912511
solana_pyth::{
@@ -2506,9 +2526,8 @@ impl Bank {
25062526
let accumulator_program =
25072527
Pubkey::from_str("Vbmv1jt4vyuqBZcpYPpnVhrqVe5e6ZPb6JxDcffRHUM").unwrap();
25082528

2509-
let accounts = self
2510-
.get_program_accounts(&accumulator_program, &ScanConfig::new(true))
2511-
.unwrap();
2529+
let accounts = self.get_program_accounts(&accumulator_program, &ScanConfig::new(true))
2530+
.map_err(|_| AccumulatorUpdateError::GetProgramAccounts)?;
25122531

25132532
// Filter accounts that don't match the Anchor sighash.
25142533
let accounts = accounts.iter().filter(|(_, account)| {
@@ -2524,13 +2543,13 @@ impl Bank {
25242543
// This code, using the offsets in each Account, extracts the various data versions from
25252544
// the account. We deduplicate this result because the accumulator expects a set.
25262545
let accounts = accounts
2527-
.flat_map(|(_, account)| {
2546+
.map(|(_, account)| {
25282547
let data = account.data();
25292548
let mut cursor = std::io::Cursor::new(&data);
2530-
let _sighash = cursor.read_u64::<LittleEndian>().unwrap();
2531-
let _bump = cursor.read_u8().unwrap();
2532-
let _version = cursor.read_u8().unwrap();
2533-
let header_len = cursor.read_u16::<LittleEndian>().unwrap();
2549+
let _sighash = cursor.read_u64::<LittleEndian>()?;
2550+
let _bump = cursor.read_u8()?;
2551+
let _version = cursor.read_u8()?;
2552+
let header_len = cursor.read_u16::<LittleEndian>()?;
25342553
let mut header_begin = header_len;
25352554
let mut inputs = Vec::new();
25362555
while let Some(end) = cursor.read_u16::<LittleEndian>().ok() {
@@ -2544,8 +2563,11 @@ impl Bank {
25442563
header_begin = end_offset;
25452564
}
25462565

2547-
inputs
2566+
Ok(inputs)
25482567
})
2568+
.collect::<std::result::Result<Vec<_>, std::io::Error>>()?
2569+
.into_iter()
2570+
.flatten()
25492571
.sorted_unstable()
25502572
.dedup();
25512573

@@ -2558,33 +2580,33 @@ impl Bank {
25582580
);
25592581

25602582
let accumulator_data = {
2561-
let data = accounts.clone().collect::<Vec<_>>();
2562-
let data = data.try_to_vec().unwrap();
2583+
let data = accounts.clone().collect::<Vec<_>>().try_to_vec()?;
25632584
let owner = solana_sdk::system_program::id();
25642585
let balance = self.get_minimum_balance_for_rent_exemption(data.len());
25652586
let mut account = AccountSharedData::new(balance, data.len(), &owner);
25662587
account.set_data(data);
25672588
account
25682589
};
25692590

2570-
// Write the Account Set into `accumulator_state` so that the hermes application can
2571-
// request historical data to prove.
2572-
self.store_account_and_update_capitalization(&accumulator_account, &accumulator_data);
2573-
25742591
// Generate a Message owned by Wormhole to be sent cross-chain. This short-circuits the
25752592
// Wormhole message generation code that would normally be called, but the Guardian
25762593
// set filters our messages so this does not pose a security risk.
25772594
if let Some(accumulator) = MerkleAccumulator::from_set(accounts) {
2578-
self.post_accumulator_attestation(accumulator);
2595+
self.post_accumulator_attestation(accumulator)?;
25792596
}
2597+
2598+
// Write the Account Set into `accumulator_state` so that the hermes application can
2599+
// request historical data to prove.
2600+
self.store_account_and_update_capitalization(&accumulator_account, &accumulator_data);
2601+
2602+
Ok(())
25802603
}
25812604

2582-
/// TODO: Remove dangerous unwrap() calls.
25832605
/// TODO: Safe integer conversion checks if any are missed.
25842606
fn post_accumulator_attestation(
25852607
&self,
25862608
acc: solana_pyth::accumulators::merkle::MerkleAccumulator,
2587-
) {
2609+
) -> std::result::Result<(), AccumulatorUpdateError> {
25882610
use {
25892611
solana_pyth::{
25902612
wormhole::{AccumulatorSequenceTracker, MessageData, PostedMessageUnreliableData},
@@ -2625,9 +2647,11 @@ impl Bank {
26252647
},
26262648
};
26272649

2650+
info!("msg_data.message: {:?}", message.message);
2651+
26282652
// Now we can bump and write the Sequence account.
26292653
sequence.sequence += 1;
2630-
let sequence = sequence.try_to_vec().unwrap();
2654+
let sequence = sequence.try_to_vec().map_err(|_| AccumulatorUpdateError::FailedSequenceSerialization)?;
26312655
let sequence_balance = self.get_minimum_balance_for_rent_exemption(sequence.len());
26322656
let sequence_account = {
26332657
let owner = &WORMHOLE_PID;
@@ -2640,15 +2664,8 @@ impl Bank {
26402664
account
26412665
};
26422666

2643-
self.store_account_and_update_capitalization(
2644-
&Pubkey::new_from_array(ACCUMULATOR_SEQUENCE_ADDR),
2645-
&sequence_account,
2646-
);
2647-
2648-
info!("msg_data.message: {:?}", message.message);
2649-
26502667
// Serialize into (and create if necesary) the message account.
2651-
let message = message.try_to_vec().unwrap();
2668+
let message = message.try_to_vec().map_err(|_| AccumulatorUpdateError::FailedMessageSerialization)?;
26522669
let message_balance = self.get_minimum_balance_for_rent_exemption(message.len());
26532670
let message_account = {
26542671
let owner = &WORMHOLE_PID;
@@ -2667,7 +2684,14 @@ impl Bank {
26672684
&Pubkey::new_from_array(WORMHOLE_PID),
26682685
);
26692686

2687+
self.store_account_and_update_capitalization(
2688+
&Pubkey::new_from_array(ACCUMULATOR_SEQUENCE_ADDR),
2689+
&sequence_account,
2690+
);
2691+
26702692
self.store_account_and_update_capitalization(&message_pda, &message_account);
2693+
2694+
Ok(())
26712695
}
26722696

26732697
pub fn epoch_duration_in_years(&self, prev_epoch: Epoch) -> f64 {

0 commit comments

Comments
 (0)