|
19 | 19 | inline_spl_token::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET}, |
20 | 20 | inline_spl_token_2022::{self, ACCOUNTTYPE_ACCOUNT}, |
21 | 21 | }, |
| 22 | + solana_program::{instruction::CompiledInstruction, message::Message}, |
22 | 23 | solana_client::connection_cache::{ConnectionCache, Protocol}, |
23 | 24 | solana_entry::entry::Entry, |
24 | 25 | solana_faucet::faucet::request_airdrop_transaction, |
|
87 | 88 | solana_storage_bigtable::Error as StorageError, |
88 | 89 | solana_streamer::socket::SocketAddrSpace, |
89 | 90 | solana_transaction_status::{ |
90 | | - map_inner_instructions, BlockEncodingOptions, ConfirmedBlock, |
| 91 | + EncodedTransaction, TransactionDetails, VoteSignatures, |
| 92 | + map_inner_instructions, BlockEncodingOptions, ConfirmedBlock, |
91 | 93 | ConfirmedTransactionStatusWithSignature, ConfirmedTransactionWithStatusMeta, |
92 | 94 | EncodedConfirmedTransactionWithStatusMeta, Reward, RewardType, TransactionBinaryEncoding, |
93 | 95 | TransactionConfirmationStatus, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding, |
@@ -1348,7 +1350,106 @@ impl JsonRpcRequestProcessor { |
1348 | 1350 | } |
1349 | 1351 | } |
1350 | 1352 | } |
1351 | | - |
| 1353 | + pub async fn get_vote_signatures( |
| 1354 | + &self, |
| 1355 | + slot: Slot, |
| 1356 | + config: Option<RpcGetVoteSignaturesConfig>, |
| 1357 | + ) -> Result<VoteSignatures> { |
| 1358 | + const VOTE_PROGRAM_ID: &str = "Vote111111111111111111111111111111111111111"; |
| 1359 | + |
| 1360 | + // manually constructing config for `getBlock` |
| 1361 | + let cfg = Some(RpcEncodingConfigWrapper::Current(Some(RpcBlockConfig { |
| 1362 | + encoding: Some(UiTransactionEncoding::Json), |
| 1363 | + transaction_details: Some(TransactionDetails::Full), |
| 1364 | + rewards: None, |
| 1365 | + commitment: Some(CommitmentConfig { |
| 1366 | + commitment: CommitmentLevel::Confirmed, |
| 1367 | + }), |
| 1368 | + max_supported_transaction_version: Some(0), |
| 1369 | + }))); |
| 1370 | + |
| 1371 | + let block = self.get_block(slot, cfg).await; |
| 1372 | + let mut vote_signatures: VoteSignatures = VoteSignatures::default(); |
| 1373 | + |
| 1374 | + // info!("harsh | txn {:?}", block.clone.unwrap().unwrap().transactions.unwrap().len()); |
| 1375 | + for outer_txn in block.unwrap().unwrap().transactions.unwrap() { |
| 1376 | + if let EncodedTransaction::Json(inner_txn) = outer_txn.transaction { |
| 1377 | + match inner_txn.message { |
| 1378 | + solana_transaction_status::UiMessage::Raw(message) => { |
| 1379 | + let aks: HashSet<String> = message |
| 1380 | + .account_keys |
| 1381 | + .clone() |
| 1382 | + .into_iter() |
| 1383 | + .map(|key| key) |
| 1384 | + .collect(); |
| 1385 | + |
| 1386 | + let mut compiled_instruction: Vec<CompiledInstruction> = vec![]; |
| 1387 | + let mut account_keys: Vec<Pubkey> = vec![]; |
| 1388 | + |
| 1389 | + let messagec = message.clone(); |
| 1390 | + for ui_ix in messagec.instructions{ |
| 1391 | + compiled_instruction.push( |
| 1392 | + CompiledInstruction { program_id_index: ui_ix.program_id_index, accounts: ui_ix.accounts, data: bs58::decode( ui_ix.data).into_vec().unwrap() } |
| 1393 | + ); |
| 1394 | + } |
| 1395 | + for key in messagec.account_keys{ |
| 1396 | + account_keys.push( |
| 1397 | + Pubkey::from_str(&key).unwrap() |
| 1398 | + ); |
| 1399 | + } |
| 1400 | + let vote_message = Message{ |
| 1401 | + header: messagec.header, |
| 1402 | + account_keys, |
| 1403 | + recent_blockhash: Hash::from_str(&messagec.recent_blockhash).unwrap(), |
| 1404 | + instructions: compiled_instruction |
| 1405 | + }; |
| 1406 | + let vote_message = vote_message.serialize(); |
| 1407 | + let validator_identity = |
| 1408 | + message.account_keys.get(0).unwrap(); |
| 1409 | + |
| 1410 | + if let Some(c) = config.clone() { |
| 1411 | + match c.vote_pubkey { |
| 1412 | + Some(p) => { |
| 1413 | + if aks.contains(&VOTE_PROGRAM_ID.to_string()) |
| 1414 | + // p == validator_identity // for a single validator identity check |
| 1415 | + && p.contains(validator_identity.as_str()) |
| 1416 | + { |
| 1417 | + let vote_signature = |
| 1418 | + Some(inner_txn.signatures[0].clone()); |
| 1419 | + vote_signatures.vote_signature.push(vote_signature); |
| 1420 | + let vote_message = Some(vote_message); |
| 1421 | + vote_signatures.vote_messages.push(vote_message); |
| 1422 | + } |
| 1423 | + // } else if aks.contains(&VOTE_PROGRAM_ID.to_string()) { |
| 1424 | + // let vote_signature = |
| 1425 | + // Some(inner_txn.signatures[0].clone()); |
| 1426 | + // vote_signatures.vote_signature.push(vote_signature); |
| 1427 | + // let vote_message = Some(vote_message); |
| 1428 | + // vote_signature.vote_messages.push(vote_message); |
| 1429 | + // } |
| 1430 | + } |
| 1431 | + // if there's no specified vote_pubkey in config, then collect all vote signatures |
| 1432 | + None => { |
| 1433 | + if aks.contains(&VOTE_PROGRAM_ID.to_string()) |
| 1434 | + { |
| 1435 | + let vote_signature = |
| 1436 | + Some(inner_txn.signatures[0].clone()); |
| 1437 | + vote_signatures.vote_signature.push(vote_signature); |
| 1438 | + let vote_message = Some(vote_message); |
| 1439 | + vote_signatures.vote_messages.push(vote_message); |
| 1440 | + } |
| 1441 | + } |
| 1442 | + } |
| 1443 | + }; |
| 1444 | + } |
| 1445 | + _ => { |
| 1446 | + error!("harsh | failing here {:?}", inner_txn.message); |
| 1447 | + } |
| 1448 | + } |
| 1449 | + } |
| 1450 | + } |
| 1451 | + Ok(vote_signatures) |
| 1452 | + } |
1352 | 1453 | pub fn get_signature_confirmation_status( |
1353 | 1454 | &self, |
1354 | 1455 | signature: Signature, |
@@ -3318,6 +3419,14 @@ pub mod rpc_full { |
3318 | 3419 | config: Option<RpcEncodingConfigWrapper<RpcBlockConfig>>, |
3319 | 3420 | ) -> BoxFuture<Result<Option<UiConfirmedBlock>>>; |
3320 | 3421 |
|
| 3422 | + #[rpc(meta, name = "getVoteSignatures")] |
| 3423 | + fn get_vote_signatures( |
| 3424 | + &self, |
| 3425 | + meta: Self::Metadata, |
| 3426 | + slot: Slot, |
| 3427 | + config: Option<RpcGetVoteSignaturesConfig>, |
| 3428 | + ) -> BoxFuture<Result<VoteSignatures>>; |
| 3429 | + |
3321 | 3430 | #[rpc(meta, name = "getBlockTime")] |
3322 | 3431 | fn get_block_time( |
3323 | 3432 | &self, |
@@ -3431,6 +3540,16 @@ pub mod rpc_full { |
3431 | 3540 | .collect()) |
3432 | 3541 | } |
3433 | 3542 |
|
| 3543 | + fn get_vote_signatures( |
| 3544 | + &self, |
| 3545 | + meta: Self::Metadata, |
| 3546 | + slot: Slot, |
| 3547 | + config: Option<RpcGetVoteSignaturesConfig>, |
| 3548 | + ) -> BoxFuture<Result<VoteSignatures>> { |
| 3549 | + debug!("get_block_headers rpc request received: {:?}", slot); |
| 3550 | + Box::pin(async move { meta.get_vote_signatures(slot, config).await }) |
| 3551 | + } |
| 3552 | + |
3434 | 3553 | fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> { |
3435 | 3554 | debug!("get_cluster_nodes rpc request received"); |
3436 | 3555 | let cluster_info = &meta.cluster_info; |
@@ -4258,7 +4377,15 @@ pub mod rpc_deprecated_v1_7 { |
4258 | 4377 | .await |
4259 | 4378 | }) |
4260 | 4379 | } |
4261 | | - |
| 4380 | + // fn get_vote_signatures( |
| 4381 | + // &self, |
| 4382 | + // meta: Self::Metadata, |
| 4383 | + // slot: Slot, |
| 4384 | + // config: Option<RpcGetVoteSignaturesConfig>, |
| 4385 | + // ) -> BoxFuture<Result<VoteSignatures>> { |
| 4386 | + // debug!("get_block_headers rpc request received: {:?}", slot); |
| 4387 | + // Box::pin(async move { meta.get_vote_signatures(slot, config).await }) |
| 4388 | + // } |
4262 | 4389 | fn get_confirmed_blocks( |
4263 | 4390 | &self, |
4264 | 4391 | meta: Self::Metadata, |
|
0 commit comments