Skip to content

Commit 501e245

Browse files
committed
add get_vote_signatures
1 parent 44e251d commit 501e245

File tree

10 files changed

+223
-4
lines changed

10 files changed

+223
-4
lines changed

Cargo.lock

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

keypair.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[217,4,91,191,84,247,101,66,202,150,225,0,142,220,120,194,8,157,138,212,166,243,178,233,172,92,206,166,89,157,235,27,149,165,102,148,110,132,67,250,69,254,91,119,181,12,209,45,152,207,172,206,95,33,203,151,118,248,222,6,32,66,62,217]

rpc-client-api/src/config.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use {
66
commitment_config::{CommitmentConfig, CommitmentLevel},
77
},
88
solana_transaction_status::{TransactionDetails, UiTransactionEncoding},
9+
std::collections::HashSet,
910
};
1011

1112
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
@@ -90,6 +91,14 @@ pub struct RpcGetVoteAccountsConfig {
9091
pub delinquent_slot_distance: Option<u64>,
9192
}
9293

94+
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
95+
#[serde(rename_all = "camelCase")]
96+
pub struct RpcGetVoteSignaturesConfig {
97+
pub vote_pubkey: Option<HashSet<String>>, // validator vote address, as a base-58 encoded string
98+
#[serde(flatten)]
99+
pub commitment: Option<CommitmentConfig>,
100+
}
101+
93102
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
94103
#[serde(untagged)]
95104
pub enum RpcLeaderScheduleConfigWrapper {

rpc-client-api/src/request.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ pub enum RpcRequest {
107107
GetTransactionCount,
108108
GetVersion,
109109
GetVoteAccounts,
110+
GetVoteSignatures,
110111
IsBlockhashValid,
111112
MinimumLedgerSlot,
112113
RegisterNode,
@@ -183,6 +184,7 @@ impl fmt::Display for RpcRequest {
183184
RpcRequest::GetTransactionCount => "getTransactionCount",
184185
RpcRequest::GetVersion => "getVersion",
185186
RpcRequest::GetVoteAccounts => "getVoteAccounts",
187+
RpcRequest::GetVoteSignatures => "getVoteSignatures",
186188
RpcRequest::IsBlockhashValid => "isBlockhashValid",
187189
RpcRequest::MinimumLedgerSlot => "minimumLedgerSlot",
188190
RpcRequest::RegisterNode => "registerNode",

rpc-client/src/nonblocking/rpc_client.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use solana_rpc_client_api::deprecated_config::{
1212
RpcConfirmedBlockConfig, RpcConfirmedTransactionConfig,
1313
RpcGetConfirmedSignaturesForAddress2Config,
1414
};
15+
use solana_transaction_status::VoteSignatures;
1516
#[cfg(feature = "spinner")]
1617
use {crate::spinner, solana_sdk::clock::MAX_HASH_AGE_IN_SECONDS, std::cmp::min};
1718
use {
@@ -2487,6 +2488,20 @@ impl RpcClient {
24872488
.await
24882489
}
24892490

2491+
pub async fn get_vote_signatures(
2492+
&self,
2493+
slot: Slot,
2494+
encoding: UiTransactionEncoding,
2495+
config: RpcGetVoteSignaturesConfig,
2496+
) -> ClientResult<VoteSignatures> {
2497+
self.send(
2498+
self.maybe_map_request(RpcRequest::GetVoteSignatures)
2499+
.await?,
2500+
json!([slot, encoding, config]),
2501+
)
2502+
.await
2503+
}
2504+
24902505
/// Returns identity and transaction information about a confirmed block in the ledger.
24912506
///
24922507
/// # RPC Reference
@@ -2854,6 +2869,7 @@ impl RpcClient {
28542869
)
28552870
.await
28562871
}
2872+
28572873

28582874
#[deprecated(since = "1.7.0", note = "Please use RpcClient::get_blocks() instead")]
28592875
#[allow(deprecated)]

rpc-client/src/rpc_client.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use {
4848
transaction::{self, uses_durable_nonce, Transaction, VersionedTransaction},
4949
},
5050
solana_transaction_status::{
51+
VoteSignatures,
5152
EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus,
5253
UiConfirmedBlock, UiTransactionEncoding,
5354
},
@@ -2120,7 +2121,17 @@ impl RpcClient {
21202121
) -> ClientResult<UiConfirmedBlock> {
21212122
self.invoke((self.rpc_client.as_ref()).get_block_with_config(slot, config))
21222123
}
2123-
2124+
pub fn get_vote_signatures(
2125+
&self,
2126+
slot: Slot,
2127+
config: RpcGetVoteSignaturesConfig,
2128+
) -> ClientResult<VoteSignatures> {
2129+
self.invoke((self.rpc_client.as_ref()).get_vote_signatures(
2130+
slot,
2131+
UiTransactionEncoding::Json,
2132+
config,
2133+
))
2134+
}
21242135
#[deprecated(since = "1.7.0", note = "Please use RpcClient::get_block() instead")]
21252136
#[allow(deprecated)]
21262137
pub fn get_confirmed_block(&self, slot: Slot) -> ClientResult<EncodedConfirmedBlock> {

rpc.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
#! /bin/bash
3+
MG=5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d
4+
TG=4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY
5+
# valgrind --leak-check=full --main-stacksize=10000000 --num-callers=500
6+
7+
exec target/release/solana-validator \
8+
--identity keypair.json \
9+
--entrypoint entrypoint.testnet.solana.com:8001 \
10+
--entrypoint entrypoint2.testnet.solana.com:8001 \
11+
--entrypoint entrypoint3.testnet.solana.com:8001 \
12+
--rpc-port 8899 \
13+
--dynamic-port-range 8002-8099 \
14+
--gossip-port 8001 \
15+
--no-voting \
16+
--private-rpc \
17+
--rpc-bind-address 0.0.0.0 \
18+
--enable-cpi-and-log-storage \
19+
--enable-rpc-transaction-history \
20+
--wal-recovery-mode skip_any_corrupted_record \
21+
--log /mnt/ssd1/validator.log \
22+
--accounts /mnt/ssd1/accounts \
23+
--ledger /mnt/ssd1/ledger \
24+
--snapshots /mnt/ssd1/snapshots \
25+
--limit-ledger-size 400000000 \
26+
--rpc-send-default-max-retries 3 \
27+
--rpc-send-service-max-retries 3 \
28+
--rpc-send-retry-ms 2000 \
29+
--full-rpc-api \
30+
--accounts-index-memory-limit-mb 250 \
31+
--no-poh-speed-test \
32+
--only-known-rpc \
33+
--accountsdb-plugin-config /root/solana-proofs/config.json \
34+
--known-validator 5D1fNXzvv5NjV1ysLjirC4WY92RNsVH18vjmcszZd8on \
35+
--known-validator eoKpUABi59aT4rR9HGS3LcMecfut9x7zJyodWWP43YQ \
36+
--known-validator nqkFSApiR4mTENxvmQwsNy9hXF2MGb6NqCA4Epmp7AH \
37+
--expected-genesis-hash $TG
38+
39+
40+
41+
# --no-genesis-fetch \
42+
# --entrypoint entrypoint.testnet.solana.com:8001 \
43+
# --entrypoint entrypoint2.testnet.solana.com:8001 \
44+
# --entrypoint entrypoint3.testnet.solana.com:8001 \

rpc/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ solana-gossip = { workspace = true }
3838
solana-ledger = { workspace = true }
3939
solana-measure = { workspace = true }
4040
solana-metrics = { workspace = true }
41+
solana-program = { workshpace = true }
4142
solana-perf = { workspace = true }
4243
solana-poh = { workspace = true }
4344
solana-rayon-threadlimit = { workspace = true }

rpc/src/rpc.rs

Lines changed: 130 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use {
1919
inline_spl_token::{SPL_TOKEN_ACCOUNT_MINT_OFFSET, SPL_TOKEN_ACCOUNT_OWNER_OFFSET},
2020
inline_spl_token_2022::{self, ACCOUNTTYPE_ACCOUNT},
2121
},
22+
solana_program::{instruction::CompiledInstruction, message::Message},
2223
solana_client::connection_cache::{ConnectionCache, Protocol},
2324
solana_entry::entry::Entry,
2425
solana_faucet::faucet::request_airdrop_transaction,
@@ -87,7 +88,8 @@ use {
8788
solana_storage_bigtable::Error as StorageError,
8889
solana_streamer::socket::SocketAddrSpace,
8990
solana_transaction_status::{
90-
map_inner_instructions, BlockEncodingOptions, ConfirmedBlock,
91+
EncodedTransaction, TransactionDetails, VoteSignatures,
92+
map_inner_instructions, BlockEncodingOptions, ConfirmedBlock,
9193
ConfirmedTransactionStatusWithSignature, ConfirmedTransactionWithStatusMeta,
9294
EncodedConfirmedTransactionWithStatusMeta, Reward, RewardType, TransactionBinaryEncoding,
9395
TransactionConfirmationStatus, TransactionStatus, UiConfirmedBlock, UiTransactionEncoding,
@@ -1348,7 +1350,106 @@ impl JsonRpcRequestProcessor {
13481350
}
13491351
}
13501352
}
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+
}
13521453
pub fn get_signature_confirmation_status(
13531454
&self,
13541455
signature: Signature,
@@ -3318,6 +3419,14 @@ pub mod rpc_full {
33183419
config: Option<RpcEncodingConfigWrapper<RpcBlockConfig>>,
33193420
) -> BoxFuture<Result<Option<UiConfirmedBlock>>>;
33203421

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+
33213430
#[rpc(meta, name = "getBlockTime")]
33223431
fn get_block_time(
33233432
&self,
@@ -3431,6 +3540,16 @@ pub mod rpc_full {
34313540
.collect())
34323541
}
34333542

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+
34343553
fn get_cluster_nodes(&self, meta: Self::Metadata) -> Result<Vec<RpcContactInfo>> {
34353554
debug!("get_cluster_nodes rpc request received");
34363555
let cluster_info = &meta.cluster_info;
@@ -4258,7 +4377,15 @@ pub mod rpc_deprecated_v1_7 {
42584377
.await
42594378
})
42604379
}
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+
// }
42624389
fn get_confirmed_blocks(
42634390
&self,
42644391
meta: Self::Metadata,

transaction-status/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,13 @@ pub struct ConfirmedBlock {
644644
pub block_height: Option<u64>,
645645
}
646646

647+
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone, Default)]
648+
#[serde(rename_all = "camelCase")]
649+
pub struct VoteSignatures {
650+
pub vote_signature: Vec<Option<String>>,
651+
pub vote_messages: Vec<Option<Vec<u8>>>,
652+
}
653+
647654
// Confirmed block with type guarantees that transaction metadata
648655
// is always present. Used for uploading to BigTable.
649656
#[derive(Clone, Debug, PartialEq)]

0 commit comments

Comments
 (0)