Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3124a88284 | ||
|
e76a2065e3 | ||
|
45f8e453a9 | ||
|
20f9c12855 | ||
|
4218414c87 | ||
|
60c91d386f | ||
|
e477501687 | ||
|
20463e141e | ||
|
e699462ed3 | ||
|
8b345f3258 | ||
|
56436a6271 | ||
|
805ea6f469 | ||
|
1db1d173fc | ||
|
11476038cd | ||
|
a669ef3abb | ||
|
dbbdfa1dbb |
299
Cargo.lock
generated
299
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-account-decoder"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana account decoder"
|
||||
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,10 +15,10 @@ bs58 = "0.3.1"
|
||||
bv = "0.11.1"
|
||||
Inflector = "0.11.4"
|
||||
lazy_static = "1.4.0"
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
spl-token-v1-0 = { package = "spl-token", version = "1.0.6", features = ["skip-no-mangle"] }
|
||||
serde = "1.0.112"
|
||||
serde_derive = "1.0.103"
|
||||
|
@@ -40,7 +40,7 @@ pub enum UiAccountData {
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum UiAccountEncoding {
|
||||
Binary,
|
||||
Binary, // SLOW! Avoid this encoding
|
||||
JsonParsed,
|
||||
Binary64,
|
||||
}
|
||||
@@ -51,19 +51,23 @@ impl UiAccount {
|
||||
account: Account,
|
||||
encoding: UiAccountEncoding,
|
||||
additional_data: Option<AccountAdditionalData>,
|
||||
data_slice_config: Option<UiDataSliceConfig>,
|
||||
) -> Self {
|
||||
let data = match encoding {
|
||||
UiAccountEncoding::Binary => {
|
||||
UiAccountData::Binary(bs58::encode(account.data).into_string())
|
||||
}
|
||||
UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(account.data)),
|
||||
UiAccountEncoding::Binary => UiAccountData::Binary(
|
||||
bs58::encode(slice_data(&account.data, data_slice_config)).into_string(),
|
||||
),
|
||||
UiAccountEncoding::Binary64 => UiAccountData::Binary64(base64::encode(slice_data(
|
||||
&account.data,
|
||||
data_slice_config,
|
||||
))),
|
||||
UiAccountEncoding::JsonParsed => {
|
||||
if let Ok(parsed_data) =
|
||||
parse_account_data(pubkey, &account.owner, &account.data, additional_data)
|
||||
{
|
||||
UiAccountData::Json(parsed_data)
|
||||
} else {
|
||||
UiAccountData::Binary64(base64::encode(account.data))
|
||||
UiAccountData::Binary64(base64::encode(&account.data))
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -113,3 +117,57 @@ impl Default for UiFeeCalculator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UiDataSliceConfig {
|
||||
pub offset: usize,
|
||||
pub length: usize,
|
||||
}
|
||||
|
||||
fn slice_data(data: &[u8], data_slice_config: Option<UiDataSliceConfig>) -> &[u8] {
|
||||
if let Some(UiDataSliceConfig { offset, length }) = data_slice_config {
|
||||
if offset >= data.len() {
|
||||
&[]
|
||||
} else if length > data.len() - offset {
|
||||
&data[offset..]
|
||||
} else {
|
||||
&data[offset..offset + length]
|
||||
}
|
||||
} else {
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_slice_data() {
|
||||
let data = vec![1, 2, 3, 4, 5];
|
||||
let slice_config = Some(UiDataSliceConfig {
|
||||
offset: 0,
|
||||
length: 5,
|
||||
});
|
||||
assert_eq!(slice_data(&data, slice_config), &data[..]);
|
||||
|
||||
let slice_config = Some(UiDataSliceConfig {
|
||||
offset: 0,
|
||||
length: 10,
|
||||
});
|
||||
assert_eq!(slice_data(&data, slice_config), &data[..]);
|
||||
|
||||
let slice_config = Some(UiDataSliceConfig {
|
||||
offset: 1,
|
||||
length: 2,
|
||||
});
|
||||
assert_eq!(slice_data(&data, slice_config), &data[1..3]);
|
||||
|
||||
let slice_config = Some(UiDataSliceConfig {
|
||||
offset: 10,
|
||||
length: 2,
|
||||
});
|
||||
assert_eq!(slice_data(&data, slice_config), &[] as &[u8]);
|
||||
}
|
||||
}
|
||||
|
@@ -54,6 +54,7 @@ pub enum ParseAccountError {
|
||||
pub struct ParsedAccount {
|
||||
pub program: String,
|
||||
pub parsed: Value,
|
||||
pub space: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -95,6 +96,7 @@ pub fn parse_account_data(
|
||||
Ok(ParsedAccount {
|
||||
program: format!("{:?}", program_name).to_kebab_case(),
|
||||
parsed: parsed_json,
|
||||
space: data.len() as u64,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -126,6 +128,7 @@ mod test {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parsed.program, "vote".to_string());
|
||||
assert_eq!(parsed.space, VoteState::size_of() as u64);
|
||||
|
||||
let nonce_data = Versions::new_current(State::Initialized(Data::default()));
|
||||
let nonce_account_data = bincode::serialize(&nonce_data).unwrap();
|
||||
@@ -137,5 +140,6 @@ mod test {
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(parsed.program, "nonce".to_string());
|
||||
assert_eq!(parsed.space, State::size() as u64);
|
||||
}
|
||||
}
|
||||
|
@@ -45,7 +45,14 @@ pub fn parse_token(
|
||||
},
|
||||
is_initialized: account.is_initialized,
|
||||
is_native: account.is_native,
|
||||
delegated_amount: token_amount_to_ui_amount(account.delegated_amount, decimals),
|
||||
delegated_amount: if account.delegate.is_none() {
|
||||
None
|
||||
} else {
|
||||
Some(token_amount_to_ui_amount(
|
||||
account.delegated_amount,
|
||||
decimals,
|
||||
))
|
||||
},
|
||||
}))
|
||||
} else if data.len() == size_of::<Mint>() {
|
||||
let mint: Mint = *unpack(&mut data)
|
||||
@@ -102,8 +109,8 @@ pub struct UiTokenAccount {
|
||||
pub delegate: Option<String>,
|
||||
pub is_initialized: bool,
|
||||
pub is_native: bool,
|
||||
#[serde(skip_serializing_if = "UiTokenAmount::is_zero")]
|
||||
pub delegated_amount: UiTokenAmount,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub delegated_amount: Option<UiTokenAmount>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||
@@ -114,16 +121,6 @@ pub struct UiTokenAmount {
|
||||
pub amount: StringAmount,
|
||||
}
|
||||
|
||||
impl UiTokenAmount {
|
||||
fn is_zero(&self) -> bool {
|
||||
if let Ok(amount) = self.amount.parse::<u64>() {
|
||||
amount == 0
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn token_amount_to_ui_amount(amount: u64, decimals: u8) -> UiTokenAmount {
|
||||
// Use `amount_to_ui_amount()` once spl_token is bumped to a version that supports it: https://github.com/solana-labs/solana-program-library/pull/211
|
||||
let amount_decimals = amount as f64 / 10_usize.pow(decimals as u32) as f64;
|
||||
@@ -188,11 +185,7 @@ mod test {
|
||||
delegate: None,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: UiTokenAmount {
|
||||
ui_amount: 0.0,
|
||||
decimals: 2,
|
||||
amount: "0".to_string()
|
||||
},
|
||||
delegated_amount: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-accounts-bench"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -10,10 +10,10 @@ homepage = "https://solana.com/"
|
||||
[dependencies]
|
||||
log = "0.4.6"
|
||||
rayon = "1.3.0"
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
rand = "0.7.0"
|
||||
clap = "2.33.1"
|
||||
crossbeam-channel = "0.4"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-banking-bench"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,16 +13,16 @@ crossbeam-channel = "0.4"
|
||||
log = "0.4.6"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.21" }
|
||||
solana-perf = { path = "../perf", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.22" }
|
||||
solana-perf = { path = "../perf", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-exchange"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -18,21 +18,21 @@ rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
serde_json = "1.0.53"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-genesis = { path = "../genesis", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.21" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-genesis = { path = "../genesis", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.2.21" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,18 +2,18 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-streamer"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-bench-tps"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,23 +14,23 @@ log = "0.4.8"
|
||||
rayon = "1.3.0"
|
||||
serde_json = "1.0.53"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-genesis = { path = "../genesis", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-genesis = { path = "../genesis", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.4.0"
|
||||
serial_test_derive = "0.4.0"
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.2.21" }
|
||||
solana-local-cluster = { path = "../local-cluster", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -27,5 +27,5 @@ Alternatively, you can source it from within a script:
|
||||
local PATCH=0
|
||||
local SPECIAL=""
|
||||
|
||||
semverParseInto "1.2.21" MAJOR MINOR PATCH SPECIAL
|
||||
semverParseInto "1.2.22" MAJOR MINOR PATCH SPECIAL
|
||||
semverParseInto "3.2.1" MAJOR MINOR PATCH SPECIAL
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-clap-utils"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana utilities for the clap"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -11,8 +11,8 @@ edition = "2018"
|
||||
[dependencies]
|
||||
clap = "2.33.0"
|
||||
rpassword = "4.0"
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
thiserror = "1.0.11"
|
||||
tiny-bip39 = "0.7.0"
|
||||
url = "2.1.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli-config"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-cli"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -27,29 +27,29 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.53"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.21" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.2.21" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.22" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.2.22" }
|
||||
thiserror = "1.0.19"
|
||||
url = "2.1.1"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -29,7 +29,7 @@ use solana_client::{
|
||||
client_error::{ClientError, ClientErrorKind, Result as ClientResult},
|
||||
rpc_client::RpcClient,
|
||||
rpc_config::{RpcLargestAccountsFilter, RpcSendTransactionConfig},
|
||||
rpc_response::RpcKeyedAccount,
|
||||
rpc_response::{Response, RpcKeyedAccount},
|
||||
};
|
||||
#[cfg(not(test))]
|
||||
use solana_faucet::faucet::request_airdrop_transaction;
|
||||
@@ -1230,7 +1230,13 @@ fn process_show_account(
|
||||
let cli_account = CliAccount {
|
||||
keyed_account: RpcKeyedAccount {
|
||||
pubkey: account_pubkey.to_string(),
|
||||
account: UiAccount::encode(account_pubkey, account, UiAccountEncoding::Binary, None),
|
||||
account: UiAccount::encode(
|
||||
account_pubkey,
|
||||
account,
|
||||
UiAccountEncoding::Binary64,
|
||||
None,
|
||||
None,
|
||||
),
|
||||
},
|
||||
use_lamports_unit,
|
||||
};
|
||||
@@ -1308,23 +1314,16 @@ fn send_and_confirm_transactions_with_spinner<T: Signers>(
|
||||
transactions_signatures = transactions_signatures
|
||||
.into_iter()
|
||||
.filter(|(_transaction, signature)| {
|
||||
if let Some(signature) = signature {
|
||||
if let Ok(status) = rpc_client.get_signature_status(&signature) {
|
||||
if rpc_client
|
||||
.get_num_blocks_since_signature_confirmation(&signature)
|
||||
.unwrap_or(0)
|
||||
> 1
|
||||
{
|
||||
return false;
|
||||
} else {
|
||||
return match status {
|
||||
None => true,
|
||||
Some(result) => result.is_err(),
|
||||
};
|
||||
signature
|
||||
.and_then(|signature| rpc_client.get_signature_statuses(&[signature]).ok())
|
||||
.map(|Response { context: _, value }| match &value[0] {
|
||||
None => true,
|
||||
Some(transaction_status) => {
|
||||
!(transaction_status.confirmations.is_none()
|
||||
|| transaction_status.confirmations.unwrap() > 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
})
|
||||
.unwrap_or(true)
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1379,7 +1378,7 @@ fn process_deploy(
|
||||
create_account_tx.try_sign(&[config.signers[0], &program_id], blockhash)?;
|
||||
messages.push(&create_account_tx.message);
|
||||
let signers = [config.signers[0], &program_id];
|
||||
let mut write_transactions = vec![];
|
||||
let mut write_messages = vec![];
|
||||
for (chunk, i) in program_data.chunks(DATA_CHUNK_SIZE).zip(0..) {
|
||||
let instruction = loader_instruction::write(
|
||||
&program_id.pubkey(),
|
||||
@@ -1388,19 +1387,17 @@ fn process_deploy(
|
||||
chunk.to_vec(),
|
||||
);
|
||||
let message = Message::new(&[instruction], Some(&signers[0].pubkey()));
|
||||
let mut tx = Transaction::new_unsigned(message);
|
||||
tx.try_sign(&signers, blockhash)?;
|
||||
write_transactions.push(tx);
|
||||
write_messages.push(message);
|
||||
}
|
||||
for transaction in write_transactions.iter() {
|
||||
messages.push(&transaction.message);
|
||||
let mut write_message_refs = vec![];
|
||||
for message in write_messages.iter() {
|
||||
write_message_refs.push(message);
|
||||
}
|
||||
messages.append(&mut write_message_refs);
|
||||
|
||||
let instruction = loader_instruction::finalize(&program_id.pubkey(), &bpf_loader::id());
|
||||
let message = Message::new(&[instruction], Some(&signers[0].pubkey()));
|
||||
let mut finalize_tx = Transaction::new_unsigned(message);
|
||||
finalize_tx.try_sign(&signers, blockhash)?;
|
||||
messages.push(&finalize_tx.message);
|
||||
let finalize_message = Message::new(&[instruction], Some(&signers[0].pubkey()));
|
||||
messages.push(&finalize_message);
|
||||
|
||||
check_account_for_multiple_fees(
|
||||
rpc_client,
|
||||
@@ -1415,11 +1412,24 @@ fn process_deploy(
|
||||
CliError::DynamicProgramError("Program account allocation failed".to_string())
|
||||
})?;
|
||||
|
||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||
|
||||
let mut write_transactions = vec![];
|
||||
for message in write_messages.into_iter() {
|
||||
let mut tx = Transaction::new_unsigned(message);
|
||||
tx.try_sign(&signers, blockhash)?;
|
||||
write_transactions.push(tx);
|
||||
}
|
||||
|
||||
trace!("Writing program data");
|
||||
send_and_confirm_transactions_with_spinner(&rpc_client, write_transactions, &signers).map_err(
|
||||
|_| CliError::DynamicProgramError("Data writes to program account failed".to_string()),
|
||||
)?;
|
||||
|
||||
let (blockhash, _) = rpc_client.get_recent_blockhash()?;
|
||||
let mut finalize_tx = Transaction::new_unsigned(finalize_message);
|
||||
finalize_tx.try_sign(&signers, blockhash)?;
|
||||
|
||||
trace!("Finalizing program account");
|
||||
rpc_client
|
||||
.send_and_confirm_transaction_with_spinner_and_config(
|
||||
|
@@ -350,6 +350,7 @@ mod tests {
|
||||
nonce_account,
|
||||
UiAccountEncoding::Binary64,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let get_account_response = json!(Response {
|
||||
context: RpcResponseContext { slot: 1 },
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-client"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Client"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -19,11 +19,11 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.53"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
tungstenite = "0.10.1"
|
||||
url = "2.1.1"
|
||||
@@ -32,7 +32,7 @@ url = "2.1.1"
|
||||
assert_matches = "1.3.0"
|
||||
jsonrpc-core = "14.1.0"
|
||||
jsonrpc-http-server = "14.1.0"
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -16,10 +16,7 @@ use indicatif::{ProgressBar, ProgressStyle};
|
||||
use log::*;
|
||||
use serde_json::{json, Value};
|
||||
use solana_account_decoder::{
|
||||
parse_token::{
|
||||
get_token_account_mint, parse_token, TokenAccountType, UiMint, UiMultisig, UiTokenAccount,
|
||||
UiTokenAmount,
|
||||
},
|
||||
parse_token::UiTokenAmount,
|
||||
UiAccount,
|
||||
UiAccountData::{Binary, Binary64},
|
||||
UiAccountEncoding,
|
||||
@@ -45,7 +42,6 @@ use solana_transaction_status::{
|
||||
};
|
||||
use solana_vote_program::vote_state::MAX_LOCKOUT_HISTORY;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
net::SocketAddr,
|
||||
thread::sleep,
|
||||
time::{Duration, Instant},
|
||||
@@ -480,6 +476,7 @@ impl RpcClient {
|
||||
let config = RpcAccountInfoConfig {
|
||||
encoding: Some(UiAccountEncoding::Binary64),
|
||||
commitment: Some(commitment_config),
|
||||
data_slice: None,
|
||||
};
|
||||
let response = self.sender.send(
|
||||
RpcRequest::GetAccountInfo,
|
||||
@@ -710,103 +707,6 @@ impl RpcClient {
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
pub fn get_token_account(&self, pubkey: &Pubkey) -> ClientResult<Option<UiTokenAccount>> {
|
||||
Ok(self
|
||||
.get_token_account_with_commitment(pubkey, CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn get_token_account_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResult<Option<UiTokenAccount>> {
|
||||
let Response {
|
||||
context,
|
||||
value: account,
|
||||
} = self.get_account_with_commitment(pubkey, commitment_config)?;
|
||||
|
||||
if account.is_none() {
|
||||
return Err(RpcError::ForUser(format!("AccountNotFound: pubkey={}", pubkey)).into());
|
||||
}
|
||||
let account = account.unwrap();
|
||||
let mint = get_token_account_mint(&account.data)
|
||||
.and_then(|mint_pubkey| {
|
||||
self.get_token_mint_with_commitment(&mint_pubkey, commitment_config)
|
||||
.ok()
|
||||
.map(|response| response.value)
|
||||
.flatten()
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
Into::<ClientError>::into(RpcError::ForUser(format!(
|
||||
"AccountNotFound: mint for token acccount pubkey={}",
|
||||
pubkey
|
||||
)))
|
||||
})?;
|
||||
|
||||
Ok(Response {
|
||||
context,
|
||||
value: match parse_token(&account.data, Some(mint.decimals)) {
|
||||
Ok(TokenAccountType::Account(ui_token_account)) => Some(ui_token_account),
|
||||
_ => None,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_token_mint(&self, pubkey: &Pubkey) -> ClientResult<Option<UiMint>> {
|
||||
Ok(self
|
||||
.get_token_mint_with_commitment(pubkey, CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn get_token_mint_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResult<Option<UiMint>> {
|
||||
let Response {
|
||||
context,
|
||||
value: account,
|
||||
} = self.get_account_with_commitment(pubkey, commitment_config)?;
|
||||
|
||||
Ok(Response {
|
||||
context,
|
||||
value: account
|
||||
.map(|account| match parse_token(&account.data, None) {
|
||||
Ok(TokenAccountType::Mint(ui_token_mint)) => Some(ui_token_mint),
|
||||
_ => None,
|
||||
})
|
||||
.flatten(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_token_multisig(&self, pubkey: &Pubkey) -> ClientResult<Option<UiMultisig>> {
|
||||
Ok(self
|
||||
.get_token_multisig_with_commitment(pubkey, CommitmentConfig::default())?
|
||||
.value)
|
||||
}
|
||||
|
||||
pub fn get_token_multisig_with_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResult<Option<UiMultisig>> {
|
||||
let Response {
|
||||
context,
|
||||
value: account,
|
||||
} = self.get_account_with_commitment(pubkey, commitment_config)?;
|
||||
|
||||
Ok(Response {
|
||||
context,
|
||||
value: account
|
||||
.map(|account| match parse_token(&account.data, None) {
|
||||
Ok(TokenAccountType::Multisig(ui_token_multisig)) => Some(ui_token_multisig),
|
||||
_ => None,
|
||||
})
|
||||
.flatten(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_token_account_balance(&self, pubkey: &Pubkey) -> ClientResult<UiTokenAmount> {
|
||||
Ok(self
|
||||
.get_token_account_balance_with_commitment(pubkey, CommitmentConfig::default())?
|
||||
@@ -828,7 +728,7 @@ impl RpcClient {
|
||||
&self,
|
||||
delegate: &Pubkey,
|
||||
token_account_filter: TokenAccountsFilter,
|
||||
) -> ClientResult<Vec<(Pubkey, UiTokenAccount)>> {
|
||||
) -> ClientResult<Vec<RpcKeyedAccount>> {
|
||||
Ok(self
|
||||
.get_token_accounts_by_delegate_with_commitment(
|
||||
delegate,
|
||||
@@ -843,39 +743,31 @@ impl RpcClient {
|
||||
delegate: &Pubkey,
|
||||
token_account_filter: TokenAccountsFilter,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResult<Vec<(Pubkey, UiTokenAccount)>> {
|
||||
) -> RpcResult<Vec<RpcKeyedAccount>> {
|
||||
let token_account_filter = match token_account_filter {
|
||||
TokenAccountsFilter::Mint(mint) => RpcTokenAccountsFilter::Mint(mint.to_string()),
|
||||
TokenAccountsFilter::ProgramId(program_id) => {
|
||||
RpcTokenAccountsFilter::ProgramId(program_id.to_string())
|
||||
}
|
||||
};
|
||||
let Response {
|
||||
context,
|
||||
value: accounts,
|
||||
} = self.send(
|
||||
RpcRequest::GetTokenAccountsByDelegate,
|
||||
json!([
|
||||
delegate.to_string(),
|
||||
token_account_filter,
|
||||
commitment_config
|
||||
]),
|
||||
)?;
|
||||
let pubkey_accounts = self.accounts_to_token_accounts(
|
||||
commitment_config,
|
||||
parse_keyed_accounts(accounts, RpcRequest::GetTokenAccountsByDelegate)?,
|
||||
);
|
||||
Ok(Response {
|
||||
context,
|
||||
value: pubkey_accounts,
|
||||
})
|
||||
|
||||
let config = RpcAccountInfoConfig {
|
||||
encoding: Some(UiAccountEncoding::JsonParsed),
|
||||
commitment: Some(commitment_config),
|
||||
data_slice: None,
|
||||
};
|
||||
|
||||
self.send(
|
||||
RpcRequest::GetTokenAccountsByOwner,
|
||||
json!([delegate.to_string(), token_account_filter, config]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_token_accounts_by_owner(
|
||||
&self,
|
||||
owner: &Pubkey,
|
||||
token_account_filter: TokenAccountsFilter,
|
||||
) -> ClientResult<Vec<(Pubkey, UiTokenAccount)>> {
|
||||
) -> ClientResult<Vec<RpcKeyedAccount>> {
|
||||
Ok(self
|
||||
.get_token_accounts_by_owner_with_commitment(
|
||||
owner,
|
||||
@@ -890,28 +782,24 @@ impl RpcClient {
|
||||
owner: &Pubkey,
|
||||
token_account_filter: TokenAccountsFilter,
|
||||
commitment_config: CommitmentConfig,
|
||||
) -> RpcResult<Vec<(Pubkey, UiTokenAccount)>> {
|
||||
) -> RpcResult<Vec<RpcKeyedAccount>> {
|
||||
let token_account_filter = match token_account_filter {
|
||||
TokenAccountsFilter::Mint(mint) => RpcTokenAccountsFilter::Mint(mint.to_string()),
|
||||
TokenAccountsFilter::ProgramId(program_id) => {
|
||||
RpcTokenAccountsFilter::ProgramId(program_id.to_string())
|
||||
}
|
||||
};
|
||||
let Response {
|
||||
context,
|
||||
value: accounts,
|
||||
} = self.send(
|
||||
|
||||
let config = RpcAccountInfoConfig {
|
||||
encoding: Some(UiAccountEncoding::JsonParsed),
|
||||
commitment: Some(commitment_config),
|
||||
data_slice: None,
|
||||
};
|
||||
|
||||
self.send(
|
||||
RpcRequest::GetTokenAccountsByOwner,
|
||||
json!([owner.to_string(), token_account_filter, commitment_config]),
|
||||
)?;
|
||||
let pubkey_accounts = self.accounts_to_token_accounts(
|
||||
commitment_config,
|
||||
parse_keyed_accounts(accounts, RpcRequest::GetTokenAccountsByDelegate)?,
|
||||
);
|
||||
Ok(Response {
|
||||
context,
|
||||
value: pubkey_accounts,
|
||||
})
|
||||
json!([owner.to_string(), token_account_filter, config]),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_token_supply(&self, mint: &Pubkey) -> ClientResult<UiTokenAmount> {
|
||||
@@ -931,35 +819,6 @@ impl RpcClient {
|
||||
)
|
||||
}
|
||||
|
||||
fn accounts_to_token_accounts(
|
||||
&self,
|
||||
commitment_config: CommitmentConfig,
|
||||
pubkey_accounts: Vec<(Pubkey, Account)>,
|
||||
) -> Vec<(Pubkey, UiTokenAccount)> {
|
||||
let mut mint_decimals: HashMap<Pubkey, u8> = HashMap::new();
|
||||
pubkey_accounts
|
||||
.into_iter()
|
||||
.filter_map(|(pubkey, account)| {
|
||||
let mint_pubkey = get_token_account_mint(&account.data)?;
|
||||
let decimals = mint_decimals.get(&mint_pubkey).cloned().or_else(|| {
|
||||
let mint = self
|
||||
.get_token_mint_with_commitment(&mint_pubkey, commitment_config)
|
||||
.ok()
|
||||
.map(|response| response.value)
|
||||
.flatten()?;
|
||||
mint_decimals.insert(mint_pubkey, mint.decimals);
|
||||
Some(mint.decimals)
|
||||
})?;
|
||||
match parse_token(&account.data, Some(decimals)) {
|
||||
Ok(TokenAccountType::Account(ui_token_account)) => {
|
||||
Some((pubkey, ui_token_account))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn poll_balance_with_timeout_and_commitment(
|
||||
&self,
|
||||
pubkey: &Pubkey,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
use crate::rpc_filter::RpcFilterType;
|
||||
use solana_account_decoder::UiAccountEncoding;
|
||||
use solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig};
|
||||
use solana_sdk::{clock::Epoch, commitment_config::CommitmentConfig};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
@@ -47,6 +47,7 @@ pub struct RpcStakeConfig {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RpcAccountInfoConfig {
|
||||
pub encoding: Option<UiAccountEncoding>,
|
||||
pub data_slice: Option<UiDataSliceConfig>,
|
||||
#[serde(flatten)]
|
||||
pub commitment: Option<CommitmentConfig>,
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-core"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@@ -42,31 +42,31 @@ regex = "1.3.7"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
serde_json = "1.0.53"
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.21" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.21" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-perf = { path = "../perf", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.2.21" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.21" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.2.21" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.2.21" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.21" }
|
||||
solana-account-decoder = { path = "../account-decoder", version = "1.2.22" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.2.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.22" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-perf = { path = "../perf", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.2.22" }
|
||||
solana-streamer = { path = "../streamer", version = "1.2.22" }
|
||||
solana-sys-tuner = { path = "../sys-tuner", version = "1.2.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
solana-vote-signer = { path = "../vote-signer", version = "1.2.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.22" }
|
||||
spl-token-v1-0 = { package = "spl-token", version = "1.0.6", features = ["skip-no-mangle"] }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
@@ -77,6 +77,7 @@ tokio_io_01 = { version = "0.1", package = "tokio-io" }
|
||||
trees = "0.2.1"
|
||||
|
||||
[dev-dependencies]
|
||||
base64 = "0.12.3"
|
||||
matches = "0.1.6"
|
||||
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
serial_test = "0.4.0"
|
||||
|
@@ -1490,12 +1490,6 @@ impl ClusterInfo {
|
||||
.time_gossip_write_lock("purge", &self.stats.purge)
|
||||
.purge(timestamp(), &timeouts);
|
||||
inc_new_counter_info!("cluster_info-purge-count", num_purged);
|
||||
let table_size = self.gossip.read().unwrap().crds.table.len();
|
||||
datapoint_debug!(
|
||||
"cluster_info-purge",
|
||||
("table_size", table_size as i64, i64),
|
||||
("purge_stake_timeout", timeout as i64, i64)
|
||||
);
|
||||
}
|
||||
|
||||
/// randomly pick a node and ask them for updates asynchronously
|
||||
@@ -1743,7 +1737,7 @@ impl ClusterInfo {
|
||||
"generate_pull_responses",
|
||||
&self.stats.generate_pull_responses,
|
||||
)
|
||||
.generate_pull_responses(&caller_and_filters);
|
||||
.generate_pull_responses(&caller_and_filters, now);
|
||||
|
||||
self.time_gossip_write_lock("process_pull_reqs", &self.stats.process_pull_requests)
|
||||
.process_pull_requests(caller_and_filters, now);
|
||||
@@ -2085,6 +2079,10 @@ impl ClusterInfo {
|
||||
|
||||
fn print_reset_stats(&self, last_print: &mut Instant) {
|
||||
if last_print.elapsed().as_millis() > 2000 {
|
||||
let (table_size, purged_values_size) = {
|
||||
let r_gossip = self.gossip.read().unwrap();
|
||||
(r_gossip.crds.table.len(), r_gossip.pull.purged_values.len())
|
||||
};
|
||||
datapoint_info!(
|
||||
"cluster_info_stats",
|
||||
("entrypoint", self.stats.entrypoint.clear(), i64),
|
||||
@@ -2108,6 +2106,8 @@ impl ClusterInfo {
|
||||
self.stats.new_push_requests_num.clear(),
|
||||
i64
|
||||
),
|
||||
("table_size", table_size as i64, i64),
|
||||
("purged_values_size", purged_values_size as i64, i64),
|
||||
);
|
||||
datapoint_info!(
|
||||
"cluster_info_stats2",
|
||||
|
193
core/src/cluster_slots_service.rs
Normal file
193
core/src/cluster_slots_service.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use crate::{cluster_info::ClusterInfo, cluster_slots::ClusterSlots};
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks,
|
||||
blockstore::{Blockstore, CompletedSlotsReceiver},
|
||||
};
|
||||
use solana_measure::measure::Measure;
|
||||
use solana_sdk::{clock::Slot, pubkey::Pubkey};
|
||||
use std::{
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
{Arc, RwLock},
|
||||
},
|
||||
thread::sleep,
|
||||
thread::{self, Builder, JoinHandle},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct ClusterSlotsServiceTiming {
|
||||
pub lowest_slot_elapsed: u64,
|
||||
pub update_completed_slots_elapsed: u64,
|
||||
}
|
||||
|
||||
impl ClusterSlotsServiceTiming {
|
||||
fn update(&mut self, lowest_slot_elapsed: u64, update_completed_slots_elapsed: u64) {
|
||||
self.lowest_slot_elapsed += lowest_slot_elapsed;
|
||||
self.update_completed_slots_elapsed += update_completed_slots_elapsed;
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClusterSlotsService {
|
||||
t_cluster_slots_service: JoinHandle<()>,
|
||||
}
|
||||
|
||||
impl ClusterSlotsService {
|
||||
pub fn new(
|
||||
blockstore: Arc<Blockstore>,
|
||||
cluster_slots: Arc<ClusterSlots>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
cluster_info: Arc<ClusterInfo>,
|
||||
completed_slots_receiver: CompletedSlotsReceiver,
|
||||
exit: Arc<AtomicBool>,
|
||||
) -> Self {
|
||||
let id = cluster_info.id();
|
||||
Self::initialize_lowest_slot(id, &blockstore, &cluster_info);
|
||||
Self::initialize_epoch_slots(&blockstore, &cluster_info, &completed_slots_receiver);
|
||||
let t_cluster_slots_service = Builder::new()
|
||||
.name("solana-cluster-slots-service".to_string())
|
||||
.spawn(move || {
|
||||
Self::run(
|
||||
blockstore,
|
||||
cluster_slots,
|
||||
bank_forks,
|
||||
cluster_info,
|
||||
completed_slots_receiver,
|
||||
exit,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
ClusterSlotsService {
|
||||
t_cluster_slots_service,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(self) -> thread::Result<()> {
|
||||
self.t_cluster_slots_service.join()
|
||||
}
|
||||
|
||||
fn run(
|
||||
blockstore: Arc<Blockstore>,
|
||||
cluster_slots: Arc<ClusterSlots>,
|
||||
bank_forks: Arc<RwLock<BankForks>>,
|
||||
cluster_info: Arc<ClusterInfo>,
|
||||
completed_slots_receiver: CompletedSlotsReceiver,
|
||||
exit: Arc<AtomicBool>,
|
||||
) {
|
||||
let mut cluster_slots_service_timing = ClusterSlotsServiceTiming::default();
|
||||
let mut last_stats = Instant::now();
|
||||
loop {
|
||||
if exit.load(Ordering::Relaxed) {
|
||||
break;
|
||||
}
|
||||
let new_root = bank_forks.read().unwrap().root();
|
||||
let id = cluster_info.id();
|
||||
let mut lowest_slot_elapsed = Measure::start("lowest_slot_elapsed");
|
||||
let lowest_slot = blockstore.lowest_slot();
|
||||
Self::update_lowest_slot(&id, lowest_slot, &cluster_info);
|
||||
lowest_slot_elapsed.stop();
|
||||
let mut update_completed_slots_elapsed =
|
||||
Measure::start("update_completed_slots_elapsed");
|
||||
Self::update_completed_slots(&completed_slots_receiver, &cluster_info);
|
||||
cluster_slots.update(new_root, &cluster_info, &bank_forks);
|
||||
update_completed_slots_elapsed.stop();
|
||||
|
||||
cluster_slots_service_timing.update(
|
||||
lowest_slot_elapsed.as_us(),
|
||||
update_completed_slots_elapsed.as_us(),
|
||||
);
|
||||
|
||||
if last_stats.elapsed().as_secs() > 2 {
|
||||
datapoint_info!(
|
||||
"cluster_slots_service-timing",
|
||||
(
|
||||
"lowest_slot_elapsed",
|
||||
cluster_slots_service_timing.lowest_slot_elapsed,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"update_completed_slots_elapsed",
|
||||
cluster_slots_service_timing.update_completed_slots_elapsed,
|
||||
i64
|
||||
),
|
||||
);
|
||||
cluster_slots_service_timing = ClusterSlotsServiceTiming::default();
|
||||
last_stats = Instant::now();
|
||||
}
|
||||
sleep(Duration::from_millis(200));
|
||||
}
|
||||
}
|
||||
|
||||
fn update_completed_slots(
|
||||
completed_slots_receiver: &CompletedSlotsReceiver,
|
||||
cluster_info: &ClusterInfo,
|
||||
) {
|
||||
let mut slots: Vec<Slot> = vec![];
|
||||
while let Ok(mut more) = completed_slots_receiver.try_recv() {
|
||||
slots.append(&mut more);
|
||||
}
|
||||
slots.sort();
|
||||
if !slots.is_empty() {
|
||||
cluster_info.push_epoch_slots(&slots);
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_lowest_slot(id: Pubkey, blockstore: &Blockstore, cluster_info: &ClusterInfo) {
|
||||
// Safe to set into gossip because by this time, the leader schedule cache should
|
||||
// also be updated with the latest root (done in blockstore_processor) and thus
|
||||
// will provide a schedule to window_service for any incoming shreds up to the
|
||||
// last_confirmed_epoch.
|
||||
cluster_info.push_lowest_slot(id, blockstore.lowest_slot());
|
||||
}
|
||||
|
||||
fn update_lowest_slot(id: &Pubkey, lowest_slot: Slot, cluster_info: &ClusterInfo) {
|
||||
cluster_info.push_lowest_slot(*id, lowest_slot);
|
||||
}
|
||||
|
||||
fn initialize_epoch_slots(
|
||||
blockstore: &Blockstore,
|
||||
cluster_info: &ClusterInfo,
|
||||
completed_slots_receiver: &CompletedSlotsReceiver,
|
||||
) {
|
||||
let root = blockstore.last_root();
|
||||
let mut slots: Vec<_> = blockstore
|
||||
.live_slots_iterator(root)
|
||||
.filter_map(|(slot, slot_meta)| {
|
||||
if slot_meta.is_full() {
|
||||
Some(slot)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
while let Ok(mut more) = completed_slots_receiver.try_recv() {
|
||||
slots.append(&mut more);
|
||||
}
|
||||
slots.sort();
|
||||
slots.dedup();
|
||||
if !slots.is_empty() {
|
||||
cluster_info.push_epoch_slots(&slots);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::cluster_info::Node;
|
||||
|
||||
#[test]
|
||||
pub fn test_update_lowest_slot() {
|
||||
let node_info = Node::new_localhost_with_pubkey(&Pubkey::default());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(node_info.info);
|
||||
ClusterSlotsService::update_lowest_slot(&Pubkey::default(), 5, &cluster_info);
|
||||
let lowest = cluster_info
|
||||
.get_lowest_slot_for_node(&Pubkey::default(), None, |lowest_slot, _| {
|
||||
lowest_slot.clone()
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(lowest.lowest, 5);
|
||||
}
|
||||
}
|
@@ -159,8 +159,9 @@ impl CrdsGossip {
|
||||
pub fn generate_pull_responses(
|
||||
&self,
|
||||
filters: &[(CrdsValue, CrdsFilter)],
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
self.pull.generate_pull_responses(&self.crds, filters)
|
||||
self.pull.generate_pull_responses(&self.crds, filters, now)
|
||||
}
|
||||
|
||||
pub fn filter_pull_responses(
|
||||
|
@@ -131,7 +131,7 @@ pub struct CrdsGossipPull {
|
||||
/// timestamp of last request
|
||||
pub pull_request_time: HashMap<Pubkey, u64>,
|
||||
/// hash and insert time
|
||||
purged_values: VecDeque<(Hash, u64)>,
|
||||
pub purged_values: VecDeque<(Hash, u64)>,
|
||||
pub crds_timeout: u64,
|
||||
pub msg_timeout: u64,
|
||||
pub num_pulls: usize,
|
||||
@@ -237,8 +237,9 @@ impl CrdsGossipPull {
|
||||
&self,
|
||||
crds: &Crds,
|
||||
requests: &[(CrdsValue, CrdsFilter)],
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
self.filter_crds_values(crds, requests)
|
||||
self.filter_crds_values(crds, requests, now)
|
||||
}
|
||||
|
||||
// Checks if responses should be inserted and
|
||||
@@ -364,22 +365,50 @@ impl CrdsGossipPull {
|
||||
for (value_hash, _insert_timestamp) in &self.purged_values {
|
||||
filters.iter_mut().for_each(|filter| filter.add(value_hash));
|
||||
}
|
||||
|
||||
filters
|
||||
}
|
||||
|
||||
/// filter values that fail the bloom filter up to max_bytes
|
||||
fn filter_crds_values(
|
||||
&self,
|
||||
crds: &Crds,
|
||||
filters: &[(CrdsValue, CrdsFilter)],
|
||||
now: u64,
|
||||
) -> Vec<Vec<CrdsValue>> {
|
||||
let mut ret = vec![vec![]; filters.len()];
|
||||
let msg_timeout = CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS;
|
||||
let jitter = rand::thread_rng().gen_range(0, msg_timeout / 4);
|
||||
let start = filters.len();
|
||||
//skip filters from callers that are too old
|
||||
let future = now.saturating_add(msg_timeout);
|
||||
let past = now.saturating_sub(msg_timeout);
|
||||
let recent: Vec<_> = filters
|
||||
.iter()
|
||||
.filter(|(caller, _)| caller.wallclock() < future && caller.wallclock() >= past)
|
||||
.collect();
|
||||
inc_new_counter_info!(
|
||||
"gossip_filter_crds_values-dropped_requests",
|
||||
start - recent.len()
|
||||
);
|
||||
if recent.is_empty() {
|
||||
return ret;
|
||||
}
|
||||
let mut total_skipped = 0;
|
||||
for v in crds.table.values() {
|
||||
filters.iter().enumerate().for_each(|(i, (_, filter))| {
|
||||
recent.iter().enumerate().for_each(|(i, (caller, filter))| {
|
||||
//skip values that are too new
|
||||
if v.value.wallclock() > caller.wallclock().checked_add(jitter).unwrap_or_else(|| 0)
|
||||
{
|
||||
total_skipped += 1;
|
||||
return;
|
||||
}
|
||||
if !filter.contains(&v.value_hash) {
|
||||
ret[i].push(v.value.clone());
|
||||
}
|
||||
});
|
||||
}
|
||||
inc_new_counter_info!("gossip_filter_crds_values-dropped_values", total_skipped);
|
||||
ret
|
||||
}
|
||||
pub fn make_timeouts_def(
|
||||
@@ -636,6 +665,62 @@ mod test {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_generate_pull_responses() {
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
let node = CrdsGossipPull::default();
|
||||
node_crds.insert(entry, 0).unwrap();
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
0,
|
||||
)));
|
||||
node_crds.insert(new, 0).unwrap();
|
||||
let req = node.new_pull_request(
|
||||
&node_crds,
|
||||
&node_pubkey,
|
||||
0,
|
||||
0,
|
||||
&HashMap::new(),
|
||||
PACKET_DATA_SIZE,
|
||||
);
|
||||
|
||||
let mut dest_crds = Crds::default();
|
||||
let dest = CrdsGossipPull::default();
|
||||
let (_, filters, caller) = req.unwrap();
|
||||
let mut filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let rsp = dest.generate_pull_responses(&dest_crds, &filters, 0);
|
||||
|
||||
assert_eq!(rsp[0].len(), 0);
|
||||
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS,
|
||||
)));
|
||||
dest_crds
|
||||
.insert(new, CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS)
|
||||
.unwrap();
|
||||
|
||||
//should skip new value since caller is to old
|
||||
let rsp =
|
||||
dest.generate_pull_responses(&dest_crds, &filters, CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS);
|
||||
assert_eq!(rsp[0].len(), 0);
|
||||
|
||||
//should return new value since caller is new
|
||||
filters[0].0 = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS + 1,
|
||||
)));
|
||||
|
||||
let rsp =
|
||||
dest.generate_pull_responses(&dest_crds, &filters, CRDS_GOSSIP_PULL_MSG_TIMEOUT_MS);
|
||||
assert_eq!(rsp[0].len(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_process_pull_request() {
|
||||
let mut node_crds = Crds::default();
|
||||
@@ -664,7 +749,7 @@ mod test {
|
||||
let mut dest = CrdsGossipPull::default();
|
||||
let (_, filters, caller) = req.unwrap();
|
||||
let filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let rsp = dest.generate_pull_responses(&dest_crds, &filters);
|
||||
let rsp = dest.generate_pull_responses(&dest_crds, &filters, 0);
|
||||
dest.process_pull_requests(&mut dest_crds, filters, 1);
|
||||
assert!(rsp.iter().all(|rsp| rsp.is_empty()));
|
||||
assert!(dest_crds.lookup(&caller.label()).is_some());
|
||||
@@ -688,7 +773,7 @@ mod test {
|
||||
let mut node_crds = Crds::default();
|
||||
let entry = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
0,
|
||||
1,
|
||||
)));
|
||||
let node_pubkey = entry.label().pubkey();
|
||||
let mut node = CrdsGossipPull::default();
|
||||
@@ -696,7 +781,7 @@ mod test {
|
||||
|
||||
let new = CrdsValue::new_unsigned(CrdsData::ContactInfo(ContactInfo::new_localhost(
|
||||
&Pubkey::new_rand(),
|
||||
0,
|
||||
1,
|
||||
)));
|
||||
node_crds.insert(new, 0).unwrap();
|
||||
|
||||
@@ -735,7 +820,7 @@ mod test {
|
||||
);
|
||||
let (_, filters, caller) = req.unwrap();
|
||||
let filters: Vec<_> = filters.into_iter().map(|f| (caller.clone(), f)).collect();
|
||||
let mut rsp = dest.generate_pull_responses(&dest_crds, &filters);
|
||||
let mut rsp = dest.generate_pull_responses(&dest_crds, &filters, 0);
|
||||
dest.process_pull_requests(&mut dest_crds, filters, 0);
|
||||
// if there is a false positive this is empty
|
||||
// prob should be around 0.1 per iteration
|
||||
|
@@ -19,6 +19,7 @@ pub mod contact_info;
|
||||
pub mod bank_weight_fork_choice;
|
||||
pub mod cluster_info;
|
||||
pub mod cluster_slots;
|
||||
pub mod cluster_slots_service;
|
||||
pub mod consensus;
|
||||
pub mod crds;
|
||||
pub mod crds_gossip;
|
||||
|
@@ -13,7 +13,7 @@ use crate::{
|
||||
use crossbeam_channel::{Receiver as CrossbeamReceiver, Sender as CrossbeamSender};
|
||||
use solana_ledger::{
|
||||
bank_forks::BankForks,
|
||||
blockstore::{Blockstore, CompletedSlotsReceiver, SlotMeta},
|
||||
blockstore::{Blockstore, SlotMeta},
|
||||
shred::Nonce,
|
||||
};
|
||||
use solana_measure::measure::Measure;
|
||||
@@ -80,8 +80,6 @@ pub struct RepairTiming {
|
||||
pub set_root_elapsed: u64,
|
||||
pub get_votes_elapsed: u64,
|
||||
pub add_votes_elapsed: u64,
|
||||
pub lowest_slot_elapsed: u64,
|
||||
pub update_completed_slots_elapsed: u64,
|
||||
pub get_best_orphans_elapsed: u64,
|
||||
pub get_best_shreds_elapsed: u64,
|
||||
pub send_repairs_elapsed: u64,
|
||||
@@ -93,15 +91,11 @@ impl RepairTiming {
|
||||
set_root_elapsed: u64,
|
||||
get_votes_elapsed: u64,
|
||||
add_votes_elapsed: u64,
|
||||
lowest_slot_elapsed: u64,
|
||||
update_completed_slots_elapsed: u64,
|
||||
send_repairs_elapsed: u64,
|
||||
) {
|
||||
self.set_root_elapsed += set_root_elapsed;
|
||||
self.get_votes_elapsed += get_votes_elapsed;
|
||||
self.add_votes_elapsed += add_votes_elapsed;
|
||||
self.lowest_slot_elapsed += lowest_slot_elapsed;
|
||||
self.update_completed_slots_elapsed += update_completed_slots_elapsed;
|
||||
self.send_repairs_elapsed += send_repairs_elapsed;
|
||||
}
|
||||
}
|
||||
@@ -114,7 +108,6 @@ pub const MAX_ORPHANS: usize = 5;
|
||||
|
||||
pub struct RepairInfo {
|
||||
pub bank_forks: Arc<RwLock<BankForks>>,
|
||||
pub completed_slots_receiver: CompletedSlotsReceiver,
|
||||
pub epoch_schedule: EpochSchedule,
|
||||
pub duplicate_slots_reset_sender: DuplicateSlotsResetSender,
|
||||
}
|
||||
@@ -183,18 +176,12 @@ impl RepairService {
|
||||
let mut repair_weight = RepairWeight::new(repair_info.bank_forks.read().unwrap().root());
|
||||
let serve_repair = ServeRepair::new(cluster_info.clone());
|
||||
let id = cluster_info.id();
|
||||
Self::initialize_lowest_slot(id, blockstore, &cluster_info);
|
||||
let mut repair_stats = RepairStats::default();
|
||||
let mut repair_timing = RepairTiming::default();
|
||||
let mut last_stats = Instant::now();
|
||||
let duplicate_slot_repair_statuses: HashMap<Slot, DuplicateSlotRepairStatus> =
|
||||
HashMap::new();
|
||||
|
||||
Self::initialize_epoch_slots(
|
||||
blockstore,
|
||||
&cluster_info,
|
||||
&repair_info.completed_slots_receiver,
|
||||
);
|
||||
loop {
|
||||
if exit.load(Ordering::Relaxed) {
|
||||
break;
|
||||
@@ -203,8 +190,6 @@ impl RepairService {
|
||||
let mut set_root_elapsed;
|
||||
let mut get_votes_elapsed;
|
||||
let mut add_votes_elapsed;
|
||||
let mut lowest_slot_elapsed;
|
||||
let mut update_completed_slots_elapsed;
|
||||
let repairs = {
|
||||
let root_bank = repair_info.bank_forks.read().unwrap().root_bank().clone();
|
||||
let new_root = root_bank.slot();
|
||||
@@ -237,15 +222,6 @@ impl RepairService {
|
||||
root_bank.epoch_schedule(),
|
||||
);
|
||||
add_votes_elapsed.stop();
|
||||
|
||||
lowest_slot_elapsed = Measure::start("lowest_slot_elapsed");
|
||||
let lowest_slot = blockstore.lowest_slot();
|
||||
Self::update_lowest_slot(&id, lowest_slot, &cluster_info);
|
||||
lowest_slot_elapsed.stop();
|
||||
update_completed_slots_elapsed = Measure::start("update_completed_slots_elapsed");
|
||||
Self::update_completed_slots(&repair_info.completed_slots_receiver, &cluster_info);
|
||||
cluster_slots.update(new_root, &cluster_info, &repair_info.bank_forks);
|
||||
update_completed_slots_elapsed.stop();
|
||||
/*let new_duplicate_slots = Self::find_new_duplicate_slots(
|
||||
&duplicate_slot_repair_statuses,
|
||||
blockstore,
|
||||
@@ -301,8 +277,6 @@ impl RepairService {
|
||||
set_root_elapsed.as_us(),
|
||||
get_votes_elapsed.as_us(),
|
||||
add_votes_elapsed.as_us(),
|
||||
lowest_slot_elapsed.as_us(),
|
||||
update_completed_slots_elapsed.as_us(),
|
||||
send_repairs_elapsed.as_us(),
|
||||
);
|
||||
|
||||
@@ -337,16 +311,6 @@ impl RepairService {
|
||||
repair_timing.get_best_shreds_elapsed,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"lowest-slot-elapsed",
|
||||
repair_timing.lowest_slot_elapsed,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"update-completed-slots-elapsed",
|
||||
repair_timing.update_completed_slots_elapsed,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"send-repairs-elapsed",
|
||||
repair_timing.send_repairs_elapsed,
|
||||
@@ -652,59 +616,6 @@ impl RepairService {
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn initialize_lowest_slot(id: Pubkey, blockstore: &Blockstore, cluster_info: &ClusterInfo) {
|
||||
// Safe to set into gossip because by this time, the leader schedule cache should
|
||||
// also be updated with the latest root (done in blockstore_processor) and thus
|
||||
// will provide a schedule to window_service for any incoming shreds up to the
|
||||
// last_confirmed_epoch.
|
||||
cluster_info.push_lowest_slot(id, blockstore.lowest_slot());
|
||||
}
|
||||
|
||||
fn update_completed_slots(
|
||||
completed_slots_receiver: &CompletedSlotsReceiver,
|
||||
cluster_info: &ClusterInfo,
|
||||
) {
|
||||
let mut slots: Vec<Slot> = vec![];
|
||||
while let Ok(mut more) = completed_slots_receiver.try_recv() {
|
||||
slots.append(&mut more);
|
||||
}
|
||||
slots.sort();
|
||||
if !slots.is_empty() {
|
||||
cluster_info.push_epoch_slots(&slots);
|
||||
}
|
||||
}
|
||||
|
||||
fn update_lowest_slot(id: &Pubkey, lowest_slot: Slot, cluster_info: &ClusterInfo) {
|
||||
cluster_info.push_lowest_slot(*id, lowest_slot);
|
||||
}
|
||||
|
||||
fn initialize_epoch_slots(
|
||||
blockstore: &Blockstore,
|
||||
cluster_info: &ClusterInfo,
|
||||
completed_slots_receiver: &CompletedSlotsReceiver,
|
||||
) {
|
||||
let root = blockstore.last_root();
|
||||
let mut slots: Vec<_> = blockstore
|
||||
.live_slots_iterator(root)
|
||||
.filter_map(|(slot, slot_meta)| {
|
||||
if slot_meta.is_full() {
|
||||
Some(slot)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
while let Ok(mut more) = completed_slots_receiver.try_recv() {
|
||||
slots.append(&mut more);
|
||||
}
|
||||
slots.sort();
|
||||
slots.dedup();
|
||||
if !slots.is_empty() {
|
||||
cluster_info.push_epoch_slots(&slots);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(self) -> thread::Result<()> {
|
||||
self.t_repair.join()
|
||||
}
|
||||
@@ -982,19 +893,6 @@ mod test {
|
||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_update_lowest_slot() {
|
||||
let node_info = Node::new_localhost_with_pubkey(&Pubkey::default());
|
||||
let cluster_info = ClusterInfo::new_with_invalid_keypair(node_info.info);
|
||||
RepairService::update_lowest_slot(&Pubkey::default(), 5, &cluster_info);
|
||||
let lowest = cluster_info
|
||||
.get_lowest_slot_for_node(&Pubkey::default(), None, |lowest_slot, _| {
|
||||
lowest_slot.clone()
|
||||
})
|
||||
.unwrap();
|
||||
assert_eq!(lowest.lowest, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_generate_duplicate_repairs_for_slot() {
|
||||
let blockstore_path = get_tmp_ledger_path!();
|
||||
|
@@ -4,6 +4,7 @@ use crate::{
|
||||
cluster_info::{compute_retransmit_peers, ClusterInfo, DATA_PLANE_FANOUT},
|
||||
cluster_info_vote_listener::VerifiedVoteReceiver,
|
||||
cluster_slots::ClusterSlots,
|
||||
cluster_slots_service::ClusterSlotsService,
|
||||
contact_info::ContactInfo,
|
||||
repair_service::DuplicateSlotsResetSender,
|
||||
repair_service::RepairInfo,
|
||||
@@ -394,6 +395,7 @@ pub fn retransmitter(
|
||||
pub struct RetransmitStage {
|
||||
thread_hdls: Vec<JoinHandle<()>>,
|
||||
window_service: WindowService,
|
||||
cluster_slots_service: ClusterSlotsService,
|
||||
}
|
||||
|
||||
impl RetransmitStage {
|
||||
@@ -427,9 +429,16 @@ impl RetransmitStage {
|
||||
retransmit_receiver,
|
||||
);
|
||||
|
||||
let cluster_slots_service = ClusterSlotsService::new(
|
||||
blockstore.clone(),
|
||||
cluster_slots.clone(),
|
||||
bank_forks.clone(),
|
||||
cluster_info.clone(),
|
||||
completed_slots_receiver,
|
||||
exit.clone(),
|
||||
);
|
||||
let repair_info = RepairInfo {
|
||||
bank_forks,
|
||||
completed_slots_receiver,
|
||||
epoch_schedule,
|
||||
duplicate_slots_reset_sender,
|
||||
};
|
||||
@@ -466,6 +475,7 @@ impl RetransmitStage {
|
||||
Self {
|
||||
thread_hdls,
|
||||
window_service,
|
||||
cluster_slots_service,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,6 +484,7 @@ impl RetransmitStage {
|
||||
thread_hdl.join()?;
|
||||
}
|
||||
self.window_service.join()?;
|
||||
self.cluster_slots_service.join()?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
274
core/src/rpc.rs
274
core/src/rpc.rs
@@ -190,10 +190,11 @@ impl JsonRpcRequestProcessor {
|
||||
let config = config.unwrap_or_default();
|
||||
let bank = self.bank(config.commitment)?;
|
||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||
check_slice_and_encoding(&encoding, config.data_slice.is_some())?;
|
||||
let mut response = None;
|
||||
if let Some(account) = bank.get_account(pubkey) {
|
||||
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed {
|
||||
response = get_parsed_token_account(bank.clone(), pubkey, account);
|
||||
response = Some(get_parsed_token_account(bank.clone(), pubkey, account));
|
||||
} else if encoding == UiAccountEncoding::Binary && account.data.len() > 128 {
|
||||
let message = "Encoded binary (base 58) data should be less than 128 bytes, please use Binary64 encoding.".to_string();
|
||||
return Err(error::Error {
|
||||
@@ -202,7 +203,13 @@ impl JsonRpcRequestProcessor {
|
||||
data: None,
|
||||
});
|
||||
} else {
|
||||
response = Some(UiAccount::encode(pubkey, account, encoding, None));
|
||||
response = Some(UiAccount::encode(
|
||||
pubkey,
|
||||
account,
|
||||
encoding,
|
||||
None,
|
||||
config.data_slice,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,19 +235,27 @@ impl JsonRpcRequestProcessor {
|
||||
let config = config.unwrap_or_default();
|
||||
let bank = self.bank(config.commitment)?;
|
||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||
let data_slice_config = config.data_slice;
|
||||
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
||||
let keyed_accounts = get_filtered_program_accounts(&bank, program_id, filters);
|
||||
let accounts =
|
||||
let result =
|
||||
if program_id == &spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed {
|
||||
get_parsed_token_accounts(bank, keyed_accounts).collect()
|
||||
} else {
|
||||
keyed_accounts
|
||||
.map(|(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(&pubkey, account, encoding.clone(), None),
|
||||
account: UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
encoding.clone(),
|
||||
None,
|
||||
data_slice_config,
|
||||
),
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
Ok(accounts)
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn get_inflation_governor(
|
||||
@@ -1058,6 +1073,8 @@ impl JsonRpcRequestProcessor {
|
||||
let config = config.unwrap_or_default();
|
||||
let bank = self.bank(config.commitment)?;
|
||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||
let data_slice_config = config.data_slice;
|
||||
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
||||
let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
|
||||
|
||||
let mut filters = vec![
|
||||
@@ -1085,7 +1102,13 @@ impl JsonRpcRequestProcessor {
|
||||
keyed_accounts
|
||||
.map(|(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(&pubkey, account, encoding.clone(), None),
|
||||
account: UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
encoding.clone(),
|
||||
None,
|
||||
data_slice_config,
|
||||
),
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
@@ -1101,6 +1124,8 @@ impl JsonRpcRequestProcessor {
|
||||
let config = config.unwrap_or_default();
|
||||
let bank = self.bank(config.commitment)?;
|
||||
let encoding = config.encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||
let data_slice_config = config.data_slice;
|
||||
check_slice_and_encoding(&encoding, data_slice_config.is_some())?;
|
||||
let (token_program_id, mint) = get_token_program_id_and_mint(&bank, token_account_filter)?;
|
||||
|
||||
let mut filters = vec![
|
||||
@@ -1136,7 +1161,13 @@ impl JsonRpcRequestProcessor {
|
||||
keyed_accounts
|
||||
.map(|(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(&pubkey, account, encoding.clone(), None),
|
||||
account: UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
encoding.clone(),
|
||||
None,
|
||||
data_slice_config,
|
||||
),
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
@@ -1196,6 +1227,26 @@ fn run_transaction_simulation(
|
||||
(executed[0].0.clone().map(|_| ()), log_collector.output())
|
||||
}
|
||||
|
||||
fn check_slice_and_encoding(encoding: &UiAccountEncoding, data_slice_is_some: bool) -> Result<()> {
|
||||
match encoding {
|
||||
UiAccountEncoding::JsonParsed => {
|
||||
if data_slice_is_some {
|
||||
let message =
|
||||
"Sliced account data can only be encoded using binary (base 58) or binary64 encoding."
|
||||
.to_string();
|
||||
Err(error::Error {
|
||||
code: error::ErrorCode::InvalidRequest,
|
||||
message,
|
||||
data: None,
|
||||
})
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
UiAccountEncoding::Binary | UiAccountEncoding::Binary64 => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Use a set of filters to get an iterator of keyed program accounts from a bank
|
||||
fn get_filtered_program_accounts(
|
||||
bank: &Arc<Bank>,
|
||||
@@ -1216,19 +1267,20 @@ pub(crate) fn get_parsed_token_account(
|
||||
bank: Arc<Bank>,
|
||||
pubkey: &Pubkey,
|
||||
account: Account,
|
||||
) -> Option<UiAccount> {
|
||||
get_token_account_mint(&account.data)
|
||||
) -> UiAccount {
|
||||
let additional_data = get_token_account_mint(&account.data)
|
||||
.and_then(|mint_pubkey| get_mint_owner_and_decimals(&bank, &mint_pubkey).ok())
|
||||
.map(|(_, decimals)| {
|
||||
UiAccount::encode(
|
||||
pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
Some(AccountAdditionalData {
|
||||
spl_token_decimals: Some(decimals),
|
||||
}),
|
||||
)
|
||||
})
|
||||
.map(|(_, decimals)| AccountAdditionalData {
|
||||
spl_token_decimals: Some(decimals),
|
||||
});
|
||||
|
||||
UiAccount::encode(
|
||||
pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
additional_data,
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn get_parsed_token_accounts<I>(
|
||||
@@ -1239,23 +1291,26 @@ where
|
||||
I: Iterator<Item = (Pubkey, Account)>,
|
||||
{
|
||||
let mut mint_decimals: HashMap<Pubkey, u8> = HashMap::new();
|
||||
keyed_accounts.filter_map(move |(pubkey, account)| {
|
||||
get_token_account_mint(&account.data).map(|mint_pubkey| {
|
||||
keyed_accounts.map(move |(pubkey, account)| {
|
||||
let additional_data = get_token_account_mint(&account.data).map(|mint_pubkey| {
|
||||
let spl_token_decimals = mint_decimals.get(&mint_pubkey).cloned().or_else(|| {
|
||||
let (_, decimals) = get_mint_owner_and_decimals(&bank, &mint_pubkey).ok()?;
|
||||
mint_decimals.insert(mint_pubkey, decimals);
|
||||
Some(decimals)
|
||||
});
|
||||
RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
Some(AccountAdditionalData { spl_token_decimals }),
|
||||
),
|
||||
}
|
||||
})
|
||||
AccountAdditionalData { spl_token_decimals }
|
||||
});
|
||||
|
||||
RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(
|
||||
&pubkey,
|
||||
account,
|
||||
UiAccountEncoding::JsonParsed,
|
||||
additional_data,
|
||||
None,
|
||||
),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2994,13 +3049,13 @@ pub mod tests {
|
||||
#[test]
|
||||
fn test_rpc_get_account_info() {
|
||||
let bob_pubkey = Pubkey::new_rand();
|
||||
let RpcHandler { io, meta, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&bob_pubkey);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}"]}}"#,
|
||||
bob_pubkey
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let expected = json!({
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
@@ -3020,6 +3075,54 @@ pub mod tests {
|
||||
let result: Response = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(expected, result);
|
||||
|
||||
let address = Pubkey::new_rand();
|
||||
let data = vec![1, 2, 3, 4, 5];
|
||||
let mut account = Account::new(42, 5, &Pubkey::default());
|
||||
account.data = data.clone();
|
||||
bank.store_account(&address, &account);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary64"}}]}}"#,
|
||||
address
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(result["result"]["value"]["data"], base64::encode(&data));
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary64", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#,
|
||||
address
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(
|
||||
result["result"]["value"]["data"],
|
||||
base64::encode(&data[1..3]),
|
||||
);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"binary", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#,
|
||||
address
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(
|
||||
result["result"]["value"]["data"],
|
||||
bs58::encode(&data[1..3]).into_string(),
|
||||
);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding":"jsonParsed", "dataSlice": {{"length": 2, "offset": 1}}}}]}}"#,
|
||||
address
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
result["error"].as_object().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -4909,4 +5012,109 @@ pub mod tests {
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_token_parsing() {
|
||||
let RpcHandler { io, meta, bank, .. } = start_rpc_handler_with_tx(&Pubkey::new_rand());
|
||||
|
||||
let mut account_data = [0; size_of::<TokenAccount>()];
|
||||
let account: &mut TokenAccount =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut account_data).unwrap();
|
||||
let mint = SplTokenPubkey::new(&[2; 32]);
|
||||
let owner = SplTokenPubkey::new(&[3; 32]);
|
||||
let delegate = SplTokenPubkey::new(&[4; 32]);
|
||||
*account = TokenAccount {
|
||||
mint,
|
||||
owner,
|
||||
delegate: COption::Some(delegate),
|
||||
amount: 420,
|
||||
is_initialized: true,
|
||||
is_native: false,
|
||||
delegated_amount: 30,
|
||||
};
|
||||
let token_account = Account {
|
||||
lamports: 111,
|
||||
data: account_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
..Account::default()
|
||||
};
|
||||
let token_account_pubkey = Pubkey::new_rand();
|
||||
bank.store_account(&token_account_pubkey, &token_account);
|
||||
|
||||
// Add the mint
|
||||
let mut mint_data = [0; size_of::<Mint>()];
|
||||
let mint_state: &mut Mint =
|
||||
spl_token_v1_0::state::unpack_unchecked(&mut mint_data).unwrap();
|
||||
*mint_state = Mint {
|
||||
owner: COption::Some(owner),
|
||||
decimals: 2,
|
||||
is_initialized: true,
|
||||
};
|
||||
let mint_account = Account {
|
||||
lamports: 111,
|
||||
data: mint_data.to_vec(),
|
||||
owner: spl_token_id_v1_0(),
|
||||
..Account::default()
|
||||
};
|
||||
bank.store_account(&Pubkey::from_str(&mint.to_string()).unwrap(), &mint_account);
|
||||
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding": "jsonParsed"}}]}}"#,
|
||||
token_account_pubkey,
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta.clone());
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(
|
||||
result["result"]["value"]["data"],
|
||||
json!({
|
||||
"program": "spl-token",
|
||||
"space": 120,
|
||||
"parsed": {
|
||||
"type": "account",
|
||||
"info": {
|
||||
"mint": mint.to_string(),
|
||||
"owner": owner.to_string(),
|
||||
"tokenAmount": {
|
||||
"uiAmount": 4.2,
|
||||
"decimals": 2,
|
||||
"amount": "420",
|
||||
},
|
||||
"delegate": delegate.to_string(),
|
||||
"isInitialized": true,
|
||||
"isNative": false,
|
||||
"delegatedAmount": {
|
||||
"uiAmount": 0.3,
|
||||
"decimals": 2,
|
||||
"amount": "30",
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// Test Mint
|
||||
let req = format!(
|
||||
r#"{{"jsonrpc":"2.0","id":1,"method":"getAccountInfo","params":["{}", {{"encoding": "jsonParsed"}}]}}"#,
|
||||
mint,
|
||||
);
|
||||
let res = io.handle_request_sync(&req, meta);
|
||||
let result: Value = serde_json::from_str(&res.expect("actual response"))
|
||||
.expect("actual response deserialization");
|
||||
assert_eq!(
|
||||
result["result"]["value"]["data"],
|
||||
json!({
|
||||
"program": "spl-token",
|
||||
"space": 40,
|
||||
"parsed": {
|
||||
"type": "mint",
|
||||
"info": {
|
||||
"owner": owner.to_string(),
|
||||
"decimals": 2,
|
||||
"isInitialized": true,
|
||||
}
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -562,6 +562,7 @@ mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::recent()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -677,6 +678,7 @@ mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::recent()),
|
||||
encoding: Some(UiAccountEncoding::JsonParsed),
|
||||
data_slice: None,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -806,6 +808,7 @@ mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::root()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -862,6 +865,7 @@ mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::root()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
);
|
||||
|
||||
|
@@ -268,13 +268,14 @@ fn filter_account_result(
|
||||
let encoding = encoding.unwrap_or(UiAccountEncoding::Binary);
|
||||
if account.owner == spl_token_id_v1_0() && encoding == UiAccountEncoding::JsonParsed {
|
||||
let bank = bank.unwrap(); // If result.is_some(), bank must also be Some
|
||||
if let Some(ui_account) = get_parsed_token_account(bank, pubkey, account) {
|
||||
return (Box::new(iter::once(ui_account)), fork);
|
||||
}
|
||||
return (
|
||||
Box::new(iter::once(get_parsed_token_account(bank, pubkey, account))),
|
||||
fork,
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
Box::new(iter::once(UiAccount::encode(
|
||||
pubkey, account, encoding, None,
|
||||
pubkey, account, encoding, None, None,
|
||||
))),
|
||||
fork,
|
||||
);
|
||||
@@ -325,7 +326,7 @@ fn filter_program_results(
|
||||
Box::new(
|
||||
keyed_accounts.map(move |(pubkey, account)| RpcKeyedAccount {
|
||||
pubkey: pubkey.to_string(),
|
||||
account: UiAccount::encode(&pubkey, account, encoding.clone(), None),
|
||||
account: UiAccount::encode(&pubkey, account, encoding.clone(), None, None),
|
||||
}),
|
||||
)
|
||||
};
|
||||
@@ -1055,6 +1056,7 @@ pub(crate) mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::recent()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
sub_id.clone(),
|
||||
subscriber,
|
||||
@@ -1551,6 +1553,7 @@ pub(crate) mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::single_gossip()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
sub_id0.clone(),
|
||||
subscriber0,
|
||||
@@ -1619,6 +1622,7 @@ pub(crate) mod tests {
|
||||
Some(RpcAccountInfoConfig {
|
||||
commitment: Some(CommitmentConfig::single_gossip()),
|
||||
encoding: None,
|
||||
data_slice: None,
|
||||
}),
|
||||
sub_id1.clone(),
|
||||
subscriber1,
|
||||
|
@@ -269,7 +269,7 @@ pub mod tests {
|
||||
|
||||
let (blockstore_path, _) = create_new_tmp_ledger!(&genesis_config);
|
||||
let (blockstore, l_receiver, completed_slots_receiver) =
|
||||
Blockstore::open_with_signal(&blockstore_path)
|
||||
Blockstore::open_with_signal(&blockstore_path, None)
|
||||
.expect("Expected to successfully open ledger");
|
||||
let blockstore = Arc::new(blockstore);
|
||||
let bank = bank_forks.working_bank();
|
||||
|
@@ -28,6 +28,7 @@ use solana_ledger::{
|
||||
bank_forks::{BankForks, SnapshotConfig},
|
||||
bank_forks_utils,
|
||||
blockstore::{Blockstore, CompletedSlotsReceiver, PurgeType},
|
||||
blockstore_db::BlockstoreRecoveryMode,
|
||||
blockstore_processor::{self, TransactionStatusSender},
|
||||
create_new_tmp_ledger,
|
||||
hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE},
|
||||
@@ -83,6 +84,7 @@ pub struct ValidatorConfig {
|
||||
pub no_rocksdb_compaction: bool,
|
||||
pub accounts_hash_interval_slots: u64,
|
||||
pub max_genesis_archive_unpacked_size: u64,
|
||||
pub wal_recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
}
|
||||
|
||||
impl Default for ValidatorConfig {
|
||||
@@ -110,6 +112,7 @@ impl Default for ValidatorConfig {
|
||||
no_rocksdb_compaction: false,
|
||||
accounts_hash_interval_slots: std::u64::MAX,
|
||||
max_genesis_archive_unpacked_size: MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
|
||||
wal_recovery_mode: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -603,7 +606,8 @@ fn new_banks_from_blockstore(
|
||||
}
|
||||
|
||||
let (mut blockstore, ledger_signal_receiver, completed_slots_receiver) =
|
||||
Blockstore::open_with_signal(blockstore_path).expect("Failed to open ledger database");
|
||||
Blockstore::open_with_signal(blockstore_path, config.wal_recovery_mode.clone())
|
||||
.expect("Failed to open ledger database");
|
||||
blockstore.set_no_compaction(config.no_rocksdb_compaction);
|
||||
|
||||
let process_options = blockstore_processor::ProcessOptions {
|
||||
|
@@ -436,7 +436,7 @@ fn network_run_pull(
|
||||
let rsp = node
|
||||
.lock()
|
||||
.unwrap()
|
||||
.generate_pull_responses(&filters)
|
||||
.generate_pull_responses(&filters, now)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
@@ -105,6 +105,7 @@ fn test_rpc_send_tx() {
|
||||
let config = RpcAccountInfoConfig {
|
||||
encoding: Some(UiAccountEncoding::Binary64),
|
||||
commitment: None,
|
||||
data_slice: None,
|
||||
};
|
||||
let req = json_req!(
|
||||
"getAccountInfo",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-crate-features"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Crate Features"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -72,6 +72,7 @@ Unstable methods may see breaking changes in patch releases and may not be suppo
|
||||
- [getTokenAccountBalance](jsonrpc-api.md#gettokenaccountbalance)
|
||||
- [getTokenAccountsByDelegate](jsonrpc-api.md#gettokenaccountsbydelegate)
|
||||
- [getTokenAccountsByOwner](jsonrpc-api.md#gettokenaccountsbyowner)
|
||||
- [getTokenLargestAccounts](jsonrpc-api.md#gettokenlargestaccounts)
|
||||
- [getTokenSupply](jsonrpc-api.md#gettokensupply)
|
||||
|
||||
## Request Formatting
|
||||
@@ -158,6 +159,7 @@ Returns all information associated with the account of provided Pubkey
|
||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- (optional) `encoding: <string>` - encoding for Account data, either "binary", "binary64", or jsonParsed". If parameter not provided, the default encoding is "binary". "binary" is base-58 encoded and limited to Account data of less than 128 bytes. "binary64" will return base64 encoded data for Account data of any size.
|
||||
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
||||
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding.
|
||||
|
||||
#### Results:
|
||||
|
||||
@@ -845,6 +847,7 @@ Returns all accounts owned by the provided program Pubkey
|
||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- (optional) `encoding: <string>` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary.
|
||||
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
||||
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding.
|
||||
- (optional) `filters: <array>` - filter results using various [filter objects](jsonrpc-api.md#filters); account must meet all filter criteria to be included in results
|
||||
|
||||
##### Filters:
|
||||
@@ -1099,6 +1102,7 @@ Returns all SPL Token accounts by approved Delegate. **UNSTABLE**
|
||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- (optional) `encoding: <string>` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary.
|
||||
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
||||
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding.
|
||||
|
||||
#### Results:
|
||||
|
||||
@@ -1135,6 +1139,7 @@ Returns all SPL Token accounts by token owner. **UNSTABLE**
|
||||
- (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
- (optional) `encoding: <string>` - encoding for Account data, either "binary" or jsonParsed". If parameter not provided, the default encoding is binary.
|
||||
Parsed-JSON encoding attempts to use program-specific state parsers to return more human-readable and explicit account state data. If parsed-JSON is requested but a parser cannot be found, the field falls back to binary encoding, detectable when the `data` field is type `<string>`. **jsonParsed encoding is UNSTABLE**
|
||||
- (optional) `dataSlice: <object>` - limit the returned account data using the provided `offset: <usize>` and `length: <usize>` fields; only available for "binary" or "binary64" encoding.
|
||||
|
||||
#### Results:
|
||||
|
||||
@@ -1157,6 +1162,33 @@ curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1114},"value":[{"data":{"program":"spl-token","parsed":{"accountType":"account","info":{"tokenAmount":{"amount":"1","uiAmount":0.1,"decimals":1},"delegate":null,"delegatedAmount":1,"isInitialized":true,"isNative":false,"mint":"3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E","owner":"4Qkev8aNZcqFNSRhQzwyLMFSsi94jHqE8WNVTJzTP99F"}}},"executable":false,"lamports":1726080,"owner":"TokenSVp5gheXUvJ6jGWGeCsgPKgnE3YgdGKRVCMY9o","rentEpoch":4},"pubkey":"CnPoSPKXu7wJqxe59Fs72tkBeALovhsCxYeFwPCQH9TD"}],"id":1}
|
||||
```
|
||||
|
||||
### getTokenLargestAccounts
|
||||
|
||||
Returns the 20 largest accounts of a particular SPL Token type. **UNSTABLE**
|
||||
|
||||
#### Parameters:
|
||||
|
||||
- `<string>` - Pubkey of token Mint to query, as base-58 encoded string
|
||||
- `<object>` - (optional) [Commitment](jsonrpc-api.md#configuring-state-commitment)
|
||||
|
||||
#### Results:
|
||||
|
||||
The result will be an RpcResponse JSON object with `value` equal to an array of JSON objects containing:
|
||||
|
||||
- `address: <string>` - the address of the token account
|
||||
- `uiAmount: <f64>` - the token account balance, using mint-prescribed decimals
|
||||
- `amount: <string>` - the raw token account balance without decimals, a string representation of u64
|
||||
- `decimals: <u8>` - number of base 10 digits to the right of the decimal place
|
||||
|
||||
#### Example:
|
||||
|
||||
```bash
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0", "id":1, "method":"getTokenLargestAccounts", "params": ["3wyAj7Rt1TWVPZVteFJPLa26JmLvdb1CAKEFZm3NY75E"]}' http://localhost:8899
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":1114},"value":[{"address":"FYjHNoFtSQ5uijKrZFyYAxvEr87hsKXkXcxkcmkBAf4r","amount":"771","decimals":2,"uiAmount":7.71},{"address":"BnsywxTcaYeNUtzrPxQUvzAWxfzZe3ZLUJ4wMMuLESnu","amount":"229","decimals":2,"uiAmount":2.29}],"id":1}
|
||||
```
|
||||
|
||||
### getTokenSupply
|
||||
|
||||
Returns the total supply of an SPL Token type. **UNSTABLE**
|
||||
@@ -1225,7 +1257,7 @@ The result field will be a JSON object with the following fields:
|
||||
// Request
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"getVersion"}' http://localhost:8899
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.2.21"},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"solana-core": "1.2.22"},"id":1}
|
||||
```
|
||||
|
||||
### getVoteAccounts
|
||||
@@ -1351,7 +1383,7 @@ Simulate sending a transaction
|
||||
An RpcResponse containing a TransactionStatus object
|
||||
The result will be an RpcResponse JSON object with `value` set to a JSON object with the following fields:
|
||||
|
||||
- `err: <object | null>` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14)
|
||||
- `err: <object | string | null>` - Error if transaction failed, null if transaction succeeded. [TransactionError definitions](https://github.com/solana-labs/solana/blob/master/sdk/src/transaction.rs#L14)
|
||||
- `logs: <array | null>` - Array of log messages the transaction instructions output during execution, null if simulation failed before the transaction was able to execute (for example due to an invalid blockhash or signature verification failure)
|
||||
|
||||
#### Example:
|
||||
@@ -1361,7 +1393,7 @@ The result will be an RpcResponse JSON object with `value` set to a JSON object
|
||||
curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1, "method":"simulateTransaction", "params":["4hXTCkRzt9WyecNzV1XPgCDfGAZzQKNxLXgynz5QDuWWPSAZBZSHptvWRL3BjCvzUXRdKvHL2b7yGrRQcWyaqsaBCncVG7BFggS8w9snUts67BSh3EqKpXLUm5UMHfD7ZBe9GhARjbNQMLJ1QD3Spr6oMTBU6EhdB4RD8CP2xUxr2u3d6fos36PD98XS6oX8TQjLpsMwncs5DAMiD4nNnR8NBfyghGCWvCVifVwvA8B8TJxE1aiyiv2L429BCWfyzAme5sZW8rDb14NeCQHhZbtNqfXhcp2tAnaAT"]}' http://localhost:8899
|
||||
|
||||
// Result
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":218},"value":{"confirmations":0,"err":null,"slot":218,"status":{"Ok":null}}},"id":1}
|
||||
{"jsonrpc":"2.0","result":{"context":{"slot":218},"value":{"err":null,"logs":["BPF program 83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri success"]},"id":1}
|
||||
```
|
||||
|
||||
### setLogFilter
|
||||
|
@@ -14,6 +14,14 @@ Currently, the rent cost is fixed at the genesis. However, it's anticipated to b
|
||||
|
||||
There are two timings of collecting rent from accounts: \(1\) when referenced by a transaction, \(2\) periodically once an epoch. \(1\) includes the transaction to create the new account itself, and it happens during the normal transaction processing by the bank as part of the load phase. \(2\) exists to ensure to collect rents from stale accounts, which aren't referenced in recent epochs at all. \(2\) requires the whole scan of accounts and is spread over an epoch based on account address prefix to avoid load spikes due to this rent collection.
|
||||
|
||||
On the contrary, rent collection isn't applied to accounts that are directly manipulated by any of protocol-level bookkeeping processes including:
|
||||
|
||||
- The distribution of rent collection itself (Otherwise, it may cause recursive rent collection handling)
|
||||
- The distribution of staking rewards at the start of every epoch (To reduce as much as processing spike at the start of new epoch)
|
||||
- The distribution of transaction fee at the end of every epoch
|
||||
|
||||
Even if those processes are out of scope of rent collection, all of manipulated accounts will eventually be handled by the \(2\) mechanism.
|
||||
|
||||
## Actual processing of collecting rent
|
||||
|
||||
Rent is due for one epoch's worth of time, and accounts always have `Account::rent_epoch` of `current_epoch + 1`.
|
||||
|
@@ -2,7 +2,7 @@
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-dos"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,14 +13,14 @@ clap = "2.33.1"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-download-utils"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Download Utils"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,8 +14,8 @@ console = "0.10.1"
|
||||
indicatif = "0.14.0"
|
||||
log = "0.4.8"
|
||||
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
tar = "0.4.28"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-faucet"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Faucet"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,11 +16,11 @@ clap = "2.33"
|
||||
log = "0.4.8"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-genesis-programs"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana genesis programs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,12 +10,12 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = { version = "0.4.8" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.2.21" }
|
||||
solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "1.2.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-genesis"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -15,14 +15,14 @@ chrono = "0.4"
|
||||
serde = "1.0.110"
|
||||
serde_json = "1.0.53"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
tempfile = "3.1.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,20 +3,20 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-gossip"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
|
||||
[dependencies]
|
||||
clap = "2.33.1"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-install"
|
||||
description = "The solana cluster software installer"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -24,12 +24,12 @@ reqwest = { version = "0.10.4", default-features = false, features = ["blocking"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
semver = "0.9.0"
|
||||
tar = "0.4.28"
|
||||
tempdir = "0.3.7"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-keygen"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana key generation utility"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,11 +13,11 @@ bs58 = "0.3.1"
|
||||
clap = "2.33"
|
||||
dirs = "2.0.2"
|
||||
num_cpus = "1.13.0"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.2.21" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-cli-config = { path = "../cli-config", version = "1.2.22" }
|
||||
solana-remote-wallet = { path = "../remote-wallet", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
tiny-bip39 = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-ledger-tool"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -19,18 +19,18 @@ log = { version = "0.4.8" }
|
||||
regex = "1"
|
||||
serde_json = "1.0.53"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-cli = { path = "../cli", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.2.21" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-cli = { path = "../cli", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "1.2.22" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
tempfile = "3.1.0"
|
||||
tokio = { version = "0.2.22", features = ["full"] }
|
||||
|
||||
|
@@ -501,7 +501,7 @@ pub fn bigtable_process_command(ledger_path: &Path, matches: &ArgMatches<'_>) {
|
||||
let ending_slot = value_t!(arg_matches, "ending_slot", Slot).ok();
|
||||
let allow_missing_metadata = arg_matches.is_present("allow_missing_metadata");
|
||||
let blockstore =
|
||||
crate::open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary);
|
||||
crate::open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary, None);
|
||||
|
||||
runtime.block_on(upload(
|
||||
blockstore,
|
||||
|
@@ -12,7 +12,7 @@ use solana_ledger::{
|
||||
bank_forks::{BankForks, SnapshotConfig},
|
||||
bank_forks_utils,
|
||||
blockstore::Blockstore,
|
||||
blockstore_db::{self, AccessType, Column, Database},
|
||||
blockstore_db::{self, AccessType, BlockstoreRecoveryMode, Column, Database},
|
||||
blockstore_processor::ProcessOptions,
|
||||
hardened_unpack::{open_genesis_config, MAX_GENESIS_ARCHIVE_UNPACKED_SIZE},
|
||||
rooted_slot_iterator::RootedSlotIterator,
|
||||
@@ -532,8 +532,12 @@ fn analyze_storage(database: &Database) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open_blockstore(ledger_path: &Path, access_type: AccessType) -> Blockstore {
|
||||
match Blockstore::open_with_access_type(ledger_path, access_type) {
|
||||
fn open_blockstore(
|
||||
ledger_path: &Path,
|
||||
access_type: AccessType,
|
||||
wal_recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Blockstore {
|
||||
match Blockstore::open_with_access_type(ledger_path, access_type, wal_recovery_mode) {
|
||||
Ok(blockstore) => blockstore,
|
||||
Err(err) => {
|
||||
eprintln!("Failed to open ledger at {:?}: {:?}", ledger_path, err);
|
||||
@@ -543,7 +547,7 @@ fn open_blockstore(ledger_path: &Path, access_type: AccessType) -> Blockstore {
|
||||
}
|
||||
|
||||
fn open_database(ledger_path: &Path, access_type: AccessType) -> Database {
|
||||
match Database::open(&ledger_path.join("rocksdb"), access_type) {
|
||||
match Database::open(&ledger_path.join("rocksdb"), access_type, None) {
|
||||
Ok(database) => database,
|
||||
Err(err) => {
|
||||
eprintln!("Unable to read the Ledger rocksdb: {:?}", err);
|
||||
@@ -567,8 +571,9 @@ fn load_bank_forks(
|
||||
genesis_config: &GenesisConfig,
|
||||
process_options: ProcessOptions,
|
||||
access_type: AccessType,
|
||||
wal_recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> bank_forks_utils::LoadResult {
|
||||
let blockstore = open_blockstore(&ledger_path, access_type);
|
||||
let blockstore = open_blockstore(&ledger_path, access_type, wal_recovery_mode);
|
||||
let snapshot_path = ledger_path.clone().join(if blockstore.is_primary_access() {
|
||||
"snapshot"
|
||||
} else {
|
||||
@@ -707,6 +712,21 @@ fn main() {
|
||||
.help("Use DIR for ledger location"),
|
||||
)
|
||||
.bigtable_subcommand()
|
||||
.arg(
|
||||
Arg::with_name("wal_recovery_mode")
|
||||
.long("wal-recovery-mode")
|
||||
.value_name("MODE")
|
||||
.takes_value(true)
|
||||
.global(true)
|
||||
.possible_values(&[
|
||||
"tolerate_corrupted_tail_records",
|
||||
"absolute_consistency",
|
||||
"point_in_time",
|
||||
"skip_any_corrupted_record"])
|
||||
.help(
|
||||
"Mode to recovery the ledger db write ahead log."
|
||||
),
|
||||
)
|
||||
.subcommand(
|
||||
SubCommand::with_name("print")
|
||||
.about("Print the ledger")
|
||||
@@ -977,13 +997,21 @@ fn main() {
|
||||
exit(1);
|
||||
});
|
||||
|
||||
let wal_recovery_mode = matches
|
||||
.value_of("wal_recovery_mode")
|
||||
.map(BlockstoreRecoveryMode::from);
|
||||
|
||||
match matches.subcommand() {
|
||||
("bigtable", Some(arg_matches)) => bigtable_process_command(&ledger_path, arg_matches),
|
||||
("print", Some(arg_matches)) => {
|
||||
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
|
||||
let allow_dead_slots = arg_matches.is_present("allow_dead_slots");
|
||||
output_ledger(
|
||||
open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary),
|
||||
open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
),
|
||||
starting_slot,
|
||||
allow_dead_slots,
|
||||
LedgerOutputMethod::Print,
|
||||
@@ -1012,6 +1040,7 @@ fn main() {
|
||||
&genesis_config,
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
) {
|
||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||
println!(
|
||||
@@ -1031,7 +1060,11 @@ fn main() {
|
||||
("slot", Some(arg_matches)) => {
|
||||
let slots = values_t_or_exit!(arg_matches, "slots", Slot);
|
||||
let allow_dead_slots = arg_matches.is_present("allow_dead_slots");
|
||||
let blockstore = open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary);
|
||||
let blockstore = open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
);
|
||||
for slot in slots {
|
||||
println!("Slot {}", slot);
|
||||
if let Err(err) = output_slot(
|
||||
@@ -1048,7 +1081,11 @@ fn main() {
|
||||
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
|
||||
let allow_dead_slots = arg_matches.is_present("allow_dead_slots");
|
||||
output_ledger(
|
||||
open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary),
|
||||
open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
),
|
||||
starting_slot,
|
||||
allow_dead_slots,
|
||||
LedgerOutputMethod::Json,
|
||||
@@ -1056,7 +1093,8 @@ fn main() {
|
||||
}
|
||||
("set-dead-slot", Some(arg_matches)) => {
|
||||
let slots = values_t_or_exit!(arg_matches, "slots", Slot);
|
||||
let blockstore = open_blockstore(&ledger_path, AccessType::PrimaryOnly);
|
||||
let blockstore =
|
||||
open_blockstore(&ledger_path, AccessType::PrimaryOnly, wal_recovery_mode);
|
||||
for slot in slots {
|
||||
match blockstore.set_dead_slot(slot) {
|
||||
Ok(_) => println!("Slot {} dead", slot),
|
||||
@@ -1067,7 +1105,11 @@ fn main() {
|
||||
("parse_full_frozen", Some(arg_matches)) => {
|
||||
let starting_slot = value_t_or_exit!(arg_matches, "starting_slot", Slot);
|
||||
let ending_slot = value_t_or_exit!(arg_matches, "ending_slot", Slot);
|
||||
let blockstore = open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary);
|
||||
let blockstore = open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
);
|
||||
let mut ancestors = BTreeSet::new();
|
||||
if blockstore.meta(ending_slot).unwrap().is_none() {
|
||||
panic!("Ending slot doesn't exist");
|
||||
@@ -1146,6 +1188,7 @@ fn main() {
|
||||
&open_genesis_config_by(&ledger_path, arg_matches),
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
)
|
||||
.unwrap_or_else(|err| {
|
||||
eprintln!("Ledger verification failed: {:?}", err);
|
||||
@@ -1169,6 +1212,7 @@ fn main() {
|
||||
&open_genesis_config_by(&ledger_path, arg_matches),
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
) {
|
||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||
let dot = graph_forks(&bank_forks, arg_matches.is_present("include_all_votes"));
|
||||
@@ -1220,6 +1264,7 @@ fn main() {
|
||||
&genesis_config,
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
) {
|
||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||
let bank = bank_forks
|
||||
@@ -1314,6 +1359,7 @@ fn main() {
|
||||
&genesis_config,
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
) {
|
||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||
let slot = bank_forks.working_bank().slot();
|
||||
@@ -1362,6 +1408,7 @@ fn main() {
|
||||
&genesis_config,
|
||||
process_options,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
) {
|
||||
Ok((bank_forks, _leader_schedule_cache, _snapshot_hash)) => {
|
||||
let slot = bank_forks.working_bank().slot();
|
||||
@@ -1472,12 +1519,17 @@ fn main() {
|
||||
("purge", Some(arg_matches)) => {
|
||||
let start_slot = value_t_or_exit!(arg_matches, "start_slot", Slot);
|
||||
let end_slot = value_t_or_exit!(arg_matches, "end_slot", Slot);
|
||||
let blockstore = open_blockstore(&ledger_path, AccessType::PrimaryOnly);
|
||||
let blockstore =
|
||||
open_blockstore(&ledger_path, AccessType::PrimaryOnly, wal_recovery_mode);
|
||||
blockstore.purge_and_compact_slots(start_slot, end_slot);
|
||||
blockstore.purge_from_next_slots(start_slot, end_slot);
|
||||
}
|
||||
("list-roots", Some(arg_matches)) => {
|
||||
let blockstore = open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary);
|
||||
let blockstore = open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
);
|
||||
let max_height = if let Some(height) = arg_matches.value_of("max_height") {
|
||||
usize::from_str(height).expect("Maximum height must be a number")
|
||||
} else {
|
||||
@@ -1530,8 +1582,12 @@ fn main() {
|
||||
});
|
||||
}
|
||||
("bounds", Some(arg_matches)) => {
|
||||
match open_blockstore(&ledger_path, AccessType::TryPrimaryThenSecondary)
|
||||
.slot_meta_iterator(0)
|
||||
match open_blockstore(
|
||||
&ledger_path,
|
||||
AccessType::TryPrimaryThenSecondary,
|
||||
wal_recovery_mode,
|
||||
)
|
||||
.slot_meta_iterator(0)
|
||||
{
|
||||
Ok(metas) => {
|
||||
let all = arg_matches.is_present("all");
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ledger"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana ledger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -32,19 +32,19 @@ reed-solomon-erasure = { version = "4.0.2", features = ["simd-accel"] }
|
||||
regex = "1.3.7"
|
||||
serde = "1.0.110"
|
||||
serde_bytes = "0.11.4"
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.21" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-perf = { path = "../perf", version = "1.2.21" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "1.2.22" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-merkle-tree = { path = "../merkle-tree", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-perf = { path = "../perf", version = "1.2.22" }
|
||||
ed25519-dalek = "1.0.0-pre.3"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
symlink = "0.1.0"
|
||||
tar = "0.4.28"
|
||||
thiserror = "1.0"
|
||||
@@ -62,7 +62,7 @@ features = ["lz4"]
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
matches = "0.1.6"
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -4,8 +4,8 @@
|
||||
pub use crate::{blockstore_db::BlockstoreError, blockstore_meta::SlotMeta};
|
||||
use crate::{
|
||||
blockstore_db::{
|
||||
columns as cf, AccessType, Column, Database, IteratorDirection, IteratorMode, LedgerColumn,
|
||||
Result, WriteBatch,
|
||||
columns as cf, AccessType, BlockstoreRecoveryMode, Column, Database, IteratorDirection,
|
||||
IteratorMode, LedgerColumn, Result, WriteBatch,
|
||||
},
|
||||
blockstore_meta::*,
|
||||
entry::{create_ticks, Entry},
|
||||
@@ -232,17 +232,22 @@ impl Blockstore {
|
||||
|
||||
/// Opens a Ledger in directory, provides "infinite" window of shreds
|
||||
pub fn open(ledger_path: &Path) -> Result<Blockstore> {
|
||||
Self::do_open(ledger_path, AccessType::PrimaryOnly)
|
||||
Self::do_open(ledger_path, AccessType::PrimaryOnly, None)
|
||||
}
|
||||
|
||||
pub fn open_with_access_type(
|
||||
ledger_path: &Path,
|
||||
access_type: AccessType,
|
||||
recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Result<Blockstore> {
|
||||
Self::do_open(ledger_path, access_type)
|
||||
Self::do_open(ledger_path, access_type, recovery_mode)
|
||||
}
|
||||
|
||||
fn do_open(ledger_path: &Path, access_type: AccessType) -> Result<Blockstore> {
|
||||
fn do_open(
|
||||
ledger_path: &Path,
|
||||
access_type: AccessType,
|
||||
recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Result<Blockstore> {
|
||||
fs::create_dir_all(&ledger_path)?;
|
||||
let blockstore_path = ledger_path.join(BLOCKSTORE_DIRECTORY);
|
||||
|
||||
@@ -251,7 +256,7 @@ impl Blockstore {
|
||||
// Open the database
|
||||
let mut measure = Measure::start("open");
|
||||
info!("Opening database at {:?}", blockstore_path);
|
||||
let db = Database::open(&blockstore_path, access_type)?;
|
||||
let db = Database::open(&blockstore_path, access_type, recovery_mode)?;
|
||||
|
||||
// Create the metadata column family
|
||||
let meta_cf = db.column();
|
||||
@@ -332,8 +337,10 @@ impl Blockstore {
|
||||
|
||||
pub fn open_with_signal(
|
||||
ledger_path: &Path,
|
||||
recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Result<(Self, Receiver<bool>, CompletedSlotsReceiver)> {
|
||||
let mut blockstore = Self::open_with_access_type(ledger_path, AccessType::PrimaryOnly)?;
|
||||
let mut blockstore =
|
||||
Self::open_with_access_type(ledger_path, AccessType::PrimaryOnly, recovery_mode)?;
|
||||
let (signal_sender, signal_receiver) = sync_channel(1);
|
||||
let (completed_slots_sender, completed_slots_receiver) =
|
||||
sync_channel(MAX_COMPLETED_SLOTS_IN_CHANNEL);
|
||||
@@ -1664,6 +1671,10 @@ impl Blockstore {
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Initializes the TransactionStatusIndex column family with two records, `0` and `1`,
|
||||
/// which are used as the primary index for entries in the TransactionStatus and
|
||||
/// AddressSignatures columns. At any given time, one primary index is active (ie. new records
|
||||
/// are stored under this index), the other is frozen.
|
||||
fn initialize_transaction_status_index(&self) -> Result<()> {
|
||||
self.transaction_status_index_cf
|
||||
.put(0, &TransactionStatusIndexMeta::default())?;
|
||||
@@ -1680,6 +1691,8 @@ impl Blockstore {
|
||||
)
|
||||
}
|
||||
|
||||
/// Toggles the active primary index between `0` and `1`, and clears the stored max-slot of the
|
||||
/// frozen index in preparation for pruning.
|
||||
fn toggle_transaction_status_index(
|
||||
&self,
|
||||
batch: &mut WriteBatch,
|
||||
@@ -1895,34 +1908,10 @@ impl Blockstore {
|
||||
}
|
||||
}
|
||||
}
|
||||
signatures.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());
|
||||
signatures.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap().then(a.1.cmp(&b.1)));
|
||||
Ok(signatures)
|
||||
}
|
||||
|
||||
fn get_lowest_slot_for_address(&self, address: Pubkey) -> Result<Option<Slot>> {
|
||||
let mut lowest_slot = None;
|
||||
for transaction_status_cf_primary_index in 0..=1 {
|
||||
let mut index_iterator = self.address_signatures_cf.iter(IteratorMode::From(
|
||||
(
|
||||
transaction_status_cf_primary_index,
|
||||
address,
|
||||
0,
|
||||
Signature::default(),
|
||||
),
|
||||
IteratorDirection::Forward,
|
||||
))?;
|
||||
if let Some(((i, key_address, slot, _), _)) = index_iterator.next() {
|
||||
if i == transaction_status_cf_primary_index
|
||||
&& key_address == address
|
||||
&& slot < lowest_slot.unwrap_or(Slot::MAX)
|
||||
{
|
||||
lowest_slot = Some(slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(lowest_slot)
|
||||
}
|
||||
|
||||
pub fn get_confirmed_signatures_for_address(
|
||||
&self,
|
||||
pubkey: Pubkey,
|
||||
@@ -1960,7 +1949,8 @@ impl Blockstore {
|
||||
// Figure the `slot` to start listing signatures at, based on the ledger location of the
|
||||
// `before` signature if present. Also generate a HashSet of signatures that should
|
||||
// be excluded from the results.
|
||||
let (mut slot, mut excluded_signatures) = match before {
|
||||
let mut get_before_slot_timer = Measure::start("get_before_slot_timer");
|
||||
let (slot, mut excluded_signatures) = match before {
|
||||
None => (highest_confirmed_root, None),
|
||||
Some(before) => {
|
||||
let transaction_status = self.get_transaction_status(before)?;
|
||||
@@ -1992,9 +1982,10 @@ impl Blockstore {
|
||||
.collect();
|
||||
|
||||
// Sort signatures as a way to entire a stable ordering within a slot, as
|
||||
// `self.find_address_signatures()` is ordered by signatures ordered and
|
||||
// the AddressSignatures column is ordered by signatures within a slot,
|
||||
// not by block ordering
|
||||
slot_signatures.sort();
|
||||
slot_signatures.reverse();
|
||||
|
||||
if let Some(pos) = slot_signatures.iter().position(|&x| x == before) {
|
||||
slot_signatures.truncate(pos + 1);
|
||||
@@ -2008,41 +1999,96 @@ impl Blockstore {
|
||||
}
|
||||
}
|
||||
};
|
||||
get_before_slot_timer.stop();
|
||||
|
||||
// Fetch the list of signatures that affect the given address
|
||||
let first_available_block = self.get_first_available_block()?;
|
||||
let first_address_slot = self.get_lowest_slot_for_address(address)?;
|
||||
if first_address_slot.is_none() {
|
||||
return Ok(vec![]);
|
||||
}
|
||||
let lower_bound = cmp::max(first_available_block, first_address_slot.unwrap());
|
||||
let mut address_signatures = vec![];
|
||||
loop {
|
||||
if address_signatures.len() >= limit {
|
||||
address_signatures.truncate(limit);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut signatures = self.find_address_signatures(address, slot, slot)?;
|
||||
if let Some(excluded_signatures) = excluded_signatures.take() {
|
||||
address_signatures.extend(
|
||||
signatures
|
||||
.into_iter()
|
||||
.filter(|(_, signature)| !excluded_signatures.contains(&signature)),
|
||||
)
|
||||
} else {
|
||||
address_signatures.append(&mut signatures);
|
||||
}
|
||||
excluded_signatures = None;
|
||||
|
||||
if slot == lower_bound {
|
||||
break;
|
||||
}
|
||||
slot -= 1;
|
||||
// Get signatures in `slot`
|
||||
let mut get_initial_slot_timer = Measure::start("get_initial_slot_timer");
|
||||
let mut signatures = self.find_address_signatures(address, slot, slot)?;
|
||||
signatures.reverse();
|
||||
if let Some(excluded_signatures) = excluded_signatures.take() {
|
||||
address_signatures.extend(
|
||||
signatures
|
||||
.into_iter()
|
||||
.filter(|(_, signature)| !excluded_signatures.contains(&signature)),
|
||||
)
|
||||
} else {
|
||||
address_signatures.append(&mut signatures);
|
||||
}
|
||||
get_initial_slot_timer.stop();
|
||||
|
||||
// Check the active_transaction_status_index to see if it contains slot. If so, start with
|
||||
// that index, as it will contain higher slots
|
||||
let starting_primary_index = *self.active_transaction_status_index.read().unwrap();
|
||||
let next_primary_index = if starting_primary_index == 0 { 1 } else { 0 };
|
||||
let next_max_slot = self
|
||||
.transaction_status_index_cf
|
||||
.get(next_primary_index)?
|
||||
.unwrap()
|
||||
.max_slot;
|
||||
|
||||
let mut starting_primary_index_iter_timer = Measure::start("starting_primary_index_iter");
|
||||
if slot > next_max_slot {
|
||||
let mut starting_iterator = self.address_signatures_cf.iter(IteratorMode::From(
|
||||
(starting_primary_index, address, slot, Signature::default()),
|
||||
IteratorDirection::Reverse,
|
||||
))?;
|
||||
|
||||
// Iterate through starting_iterator until limit is reached
|
||||
while address_signatures.len() < limit {
|
||||
if let Some(((i, key_address, slot, signature), _)) = starting_iterator.next() {
|
||||
if slot == next_max_slot {
|
||||
break;
|
||||
}
|
||||
if i == starting_primary_index
|
||||
&& key_address == address
|
||||
&& slot >= first_available_block
|
||||
{
|
||||
address_signatures.push((slot, signature));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle slots that cross primary indexes
|
||||
let mut signatures =
|
||||
self.find_address_signatures(address, next_max_slot, next_max_slot)?;
|
||||
signatures.reverse();
|
||||
address_signatures.append(&mut signatures);
|
||||
}
|
||||
starting_primary_index_iter_timer.stop();
|
||||
|
||||
// Iterate through next_iterator until limit is reached
|
||||
let mut next_primary_index_iter_timer = Measure::start("next_primary_index_iter_timer");
|
||||
let mut next_iterator = self.address_signatures_cf.iter(IteratorMode::From(
|
||||
(next_primary_index, address, slot, Signature::default()),
|
||||
IteratorDirection::Reverse,
|
||||
))?;
|
||||
while address_signatures.len() < limit {
|
||||
if let Some(((i, key_address, slot, signature), _)) = next_iterator.next() {
|
||||
// Skip next_max_slot, which is already included
|
||||
if slot == next_max_slot {
|
||||
continue;
|
||||
}
|
||||
if i == next_primary_index
|
||||
&& key_address == address
|
||||
&& slot >= first_available_block
|
||||
{
|
||||
address_signatures.push((slot, signature));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
next_primary_index_iter_timer.stop();
|
||||
address_signatures.truncate(limit);
|
||||
|
||||
// Fill in the status information for each found transaction
|
||||
let mut get_status_info_timer = Measure::start("get_status_info_timer");
|
||||
let mut infos = vec![];
|
||||
for (slot, signature) in address_signatures.into_iter() {
|
||||
let transaction_status = self.get_transaction_status(signature)?;
|
||||
@@ -2057,6 +2103,36 @@ impl Blockstore {
|
||||
memo: None,
|
||||
});
|
||||
}
|
||||
get_status_info_timer.stop();
|
||||
|
||||
datapoint_info!(
|
||||
"blockstore-get-conf-sigs-for-addr-2",
|
||||
(
|
||||
"get_before_slot_us",
|
||||
get_before_slot_timer.as_us() as i64,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"get_initial_slot_us",
|
||||
get_initial_slot_timer.as_us() as i64,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"starting_primary_index_iter_us",
|
||||
starting_primary_index_iter_timer.as_us() as i64,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"next_primary_index_iter_us",
|
||||
next_primary_index_iter_timer.as_us() as i64,
|
||||
i64
|
||||
),
|
||||
(
|
||||
"get_status_info_us",
|
||||
get_status_info_timer.as_us() as i64,
|
||||
i64
|
||||
)
|
||||
);
|
||||
|
||||
Ok(infos)
|
||||
}
|
||||
@@ -2866,7 +2942,7 @@ pub fn create_new_ledger(
|
||||
genesis_config.write(&ledger_path)?;
|
||||
|
||||
// Fill slot 0 with ticks that link back to the genesis_config to bootstrap the ledger.
|
||||
let blockstore = Blockstore::open_with_access_type(ledger_path, access_type)?;
|
||||
let blockstore = Blockstore::open_with_access_type(ledger_path, access_type, None)?;
|
||||
let ticks_per_slot = genesis_config.ticks_per_slot;
|
||||
let hashes_per_tick = genesis_config.poh_config.hashes_per_tick.unwrap_or(0);
|
||||
let entries = create_ticks(ticks_per_slot, hashes_per_tick, genesis_config.hash());
|
||||
@@ -3803,7 +3879,7 @@ pub mod tests {
|
||||
pub fn test_new_shreds_signal() {
|
||||
// Initialize ledger
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let (ledger, recvr, _) = Blockstore::open_with_signal(&ledger_path).unwrap();
|
||||
let (ledger, recvr, _) = Blockstore::open_with_signal(&ledger_path, None).unwrap();
|
||||
let ledger = Arc::new(ledger);
|
||||
|
||||
let entries_per_slot = 50;
|
||||
@@ -3883,7 +3959,7 @@ pub mod tests {
|
||||
pub fn test_completed_shreds_signal() {
|
||||
// Initialize ledger
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path).unwrap();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path, None).unwrap();
|
||||
let ledger = Arc::new(ledger);
|
||||
|
||||
let entries_per_slot = 10;
|
||||
@@ -3905,7 +3981,7 @@ pub mod tests {
|
||||
pub fn test_completed_shreds_signal_orphans() {
|
||||
// Initialize ledger
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path).unwrap();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path, None).unwrap();
|
||||
let ledger = Arc::new(ledger);
|
||||
|
||||
let entries_per_slot = 10;
|
||||
@@ -3945,7 +4021,7 @@ pub mod tests {
|
||||
pub fn test_completed_shreds_signal_many() {
|
||||
// Initialize ledger
|
||||
let ledger_path = get_tmp_ledger_path!();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path).unwrap();
|
||||
let (ledger, _, recvr) = Blockstore::open_with_signal(&ledger_path, None).unwrap();
|
||||
let ledger = Arc::new(ledger);
|
||||
|
||||
let entries_per_slot = 10;
|
||||
@@ -6242,82 +6318,6 @@ pub mod tests {
|
||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_lowest_slot_for_address() {
|
||||
let blockstore_path = get_tmp_ledger_path!();
|
||||
{
|
||||
let blockstore = Blockstore::open(&blockstore_path).unwrap();
|
||||
let address = Pubkey::new_rand();
|
||||
let address2 = Pubkey::new_rand();
|
||||
let slot = 5;
|
||||
// Add an additional to record to ensure that existent or lower slots in entries for
|
||||
// other addresses do not affect return
|
||||
blockstore
|
||||
.address_signatures_cf
|
||||
.put(
|
||||
(0, address2, slot, Signature::default()),
|
||||
&AddressSignatureMeta { writeable: false },
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
blockstore.get_lowest_slot_for_address(address).unwrap(),
|
||||
None
|
||||
);
|
||||
|
||||
let slot = 200;
|
||||
blockstore
|
||||
.address_signatures_cf
|
||||
.put(
|
||||
(0, address, slot, Signature::default()),
|
||||
&AddressSignatureMeta { writeable: false },
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
blockstore.get_lowest_slot_for_address(address).unwrap(),
|
||||
Some(200)
|
||||
);
|
||||
|
||||
blockstore
|
||||
.address_signatures_cf
|
||||
.put(
|
||||
(1, address, slot, Signature::default()),
|
||||
&AddressSignatureMeta { writeable: false },
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
blockstore.get_lowest_slot_for_address(address).unwrap(),
|
||||
Some(200)
|
||||
);
|
||||
|
||||
let slot = 300;
|
||||
blockstore
|
||||
.address_signatures_cf
|
||||
.put(
|
||||
(1, address, slot, Signature::default()),
|
||||
&AddressSignatureMeta { writeable: false },
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
blockstore.get_lowest_slot_for_address(address).unwrap(),
|
||||
Some(200)
|
||||
);
|
||||
|
||||
let slot = 100;
|
||||
blockstore
|
||||
.address_signatures_cf
|
||||
.put(
|
||||
(1, address, slot, Signature::default()),
|
||||
&AddressSignatureMeta { writeable: false },
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
blockstore.get_lowest_slot_for_address(address).unwrap(),
|
||||
Some(100)
|
||||
);
|
||||
}
|
||||
Blockstore::destroy(&blockstore_path).expect("Expected successful database destruction");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_confirmed_signatures_for_address2() {
|
||||
let blockstore_path = get_tmp_ledger_path!();
|
||||
@@ -6344,14 +6344,18 @@ pub mod tests {
|
||||
let address0 = Pubkey::new_rand();
|
||||
let address1 = Pubkey::new_rand();
|
||||
|
||||
for slot in 2..=4 {
|
||||
for slot in 2..=7 {
|
||||
let entries = make_slot_entries_with_transaction_addresses(&[
|
||||
address0, address1, address0, address1,
|
||||
]);
|
||||
let shreds = entries_to_test_shreds(entries.clone(), slot, slot - 1, true, 0);
|
||||
blockstore.insert_shreds(shreds, None, false).unwrap();
|
||||
|
||||
for entry in &entries {
|
||||
for (i, entry) in entries.iter().enumerate() {
|
||||
if slot == 4 && i == 2 {
|
||||
// Purge to freeze index 0 and write address-signatures in new primary index
|
||||
blockstore.run_purge(0, 1, PurgeType::PrimaryIndex).unwrap();
|
||||
}
|
||||
for transaction in &entry.transactions {
|
||||
assert_eq!(transaction.signatures.len(), 1);
|
||||
blockstore
|
||||
@@ -6366,8 +6370,8 @@ pub mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
blockstore.set_roots(&[1, 2, 3, 4]).unwrap();
|
||||
let highest_confirmed_root = 4;
|
||||
blockstore.set_roots(&[1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||
let highest_confirmed_root = 7;
|
||||
|
||||
// Fetch all signatures for address 0 at once...
|
||||
let all0 = blockstore
|
||||
@@ -6378,7 +6382,7 @@ pub mod tests {
|
||||
usize::MAX,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(all0.len(), 6);
|
||||
assert_eq!(all0.len(), 12);
|
||||
|
||||
// Fetch all signatures for address 1 at once...
|
||||
let all1 = blockstore
|
||||
@@ -6389,7 +6393,7 @@ pub mod tests {
|
||||
usize::MAX,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(all1.len(), 6);
|
||||
assert_eq!(all1.len(), 12);
|
||||
|
||||
assert!(all0 != all1);
|
||||
|
||||
@@ -6442,7 +6446,7 @@ pub mod tests {
|
||||
assert_eq!(results[2], all0[i + 2]);
|
||||
}
|
||||
|
||||
// Ensure that the signatures within a slot are ordered by signature
|
||||
// Ensure that the signatures within a slot are reverse ordered by signature
|
||||
// (current limitation of the .get_confirmed_signatures_for_address2())
|
||||
for i in (0..all1.len()).step_by(2) {
|
||||
let results = blockstore
|
||||
@@ -6459,7 +6463,7 @@ pub mod tests {
|
||||
.unwrap();
|
||||
assert_eq!(results.len(), 2);
|
||||
assert_eq!(results[0].slot, results[1].slot);
|
||||
assert!(results[0].signature <= results[1].signature);
|
||||
assert!(results[0].signature >= results[1].signature);
|
||||
assert_eq!(results[0], all1[i]);
|
||||
assert_eq!(results[1], all1[i + 1]);
|
||||
}
|
||||
|
@@ -235,6 +235,9 @@ impl Blockstore {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Purges special columns (using a non-Slot primary-index) exactly, by deserializing each slot
|
||||
/// being purged and iterating through all transactions to determine the keys of individual
|
||||
/// records. **This method is very slow.**
|
||||
fn purge_special_columns_exact(
|
||||
&self,
|
||||
batch: &mut WriteBatch,
|
||||
@@ -279,6 +282,8 @@ impl Blockstore {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Purges special columns (using a non-Slot primary-index) by range. Purge occurs if frozen
|
||||
/// primary index has a max-slot less than the highest slot being purged.
|
||||
fn purge_special_columns_with_primary_index(
|
||||
&self,
|
||||
write_batch: &mut WriteBatch,
|
||||
|
@@ -4,7 +4,7 @@ use byteorder::{BigEndian, ByteOrder};
|
||||
use log::*;
|
||||
pub use rocksdb::Direction as IteratorDirection;
|
||||
use rocksdb::{
|
||||
self, ColumnFamily, ColumnFamilyDescriptor, DBIterator, DBRawIterator,
|
||||
self, ColumnFamily, ColumnFamilyDescriptor, DBIterator, DBRawIterator, DBRecoveryMode,
|
||||
IteratorMode as RocksIteratorMode, Options, WriteBatch as RWriteBatch, DB,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
@@ -39,7 +39,9 @@ const CODE_SHRED_CF: &str = "code_shred";
|
||||
const TRANSACTION_STATUS_CF: &str = "transaction_status";
|
||||
/// Column family for Address Signatures
|
||||
const ADDRESS_SIGNATURES_CF: &str = "address_signatures";
|
||||
/// Column family for Transaction Status Index
|
||||
/// Column family for the Transaction Status Index.
|
||||
/// This column family is used for tracking the active primary index for columns that for
|
||||
/// query performance reasons should not be indexed by Slot.
|
||||
const TRANSACTION_STATUS_INDEX_CF: &str = "transaction_status_index";
|
||||
/// Column family for Rewards
|
||||
const REWARDS_CF: &str = "rewards";
|
||||
@@ -138,11 +140,51 @@ pub enum ActualAccessType {
|
||||
Secondary,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BlockstoreRecoveryMode {
|
||||
TolerateCorruptedTailRecords,
|
||||
AbsoluteConsistency,
|
||||
PointInTime,
|
||||
SkipAnyCorruptedRecord,
|
||||
}
|
||||
|
||||
impl From<&str> for BlockstoreRecoveryMode {
|
||||
fn from(string: &str) -> Self {
|
||||
match string {
|
||||
"tolerate_corrupted_tail_records" => {
|
||||
BlockstoreRecoveryMode::TolerateCorruptedTailRecords
|
||||
}
|
||||
"absolute_consistency" => BlockstoreRecoveryMode::AbsoluteConsistency,
|
||||
"point_in_time" => BlockstoreRecoveryMode::PointInTime,
|
||||
"skip_any_corrupted_record" => BlockstoreRecoveryMode::SkipAnyCorruptedRecord,
|
||||
bad_mode => panic!("Invalid recovery mode: {}", bad_mode),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl Into<DBRecoveryMode> for BlockstoreRecoveryMode {
|
||||
fn into(self) -> DBRecoveryMode {
|
||||
match self {
|
||||
BlockstoreRecoveryMode::TolerateCorruptedTailRecords => {
|
||||
DBRecoveryMode::TolerateCorruptedTailRecords
|
||||
}
|
||||
BlockstoreRecoveryMode::AbsoluteConsistency => DBRecoveryMode::AbsoluteConsistency,
|
||||
BlockstoreRecoveryMode::PointInTime => DBRecoveryMode::PointInTime,
|
||||
BlockstoreRecoveryMode::SkipAnyCorruptedRecord => {
|
||||
DBRecoveryMode::SkipAnyCorruptedRecord
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Rocks(rocksdb::DB, ActualAccessType);
|
||||
|
||||
impl Rocks {
|
||||
fn open(path: &Path, access_type: AccessType) -> Result<Rocks> {
|
||||
fn open(
|
||||
path: &Path,
|
||||
access_type: AccessType,
|
||||
recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Result<Rocks> {
|
||||
use columns::{
|
||||
AddressSignatures, DeadSlots, DuplicateSlots, ErasureMeta, Index, Orphans, Rewards,
|
||||
Root, ShredCode, ShredData, SlotMeta, TransactionStatus, TransactionStatusIndex,
|
||||
@@ -152,6 +194,9 @@ impl Rocks {
|
||||
|
||||
// Use default database options
|
||||
let mut db_options = get_db_options();
|
||||
if let Some(recovery_mode) = recovery_mode {
|
||||
db_options.set_wal_recovery_mode(recovery_mode.into());
|
||||
}
|
||||
|
||||
// Column family names
|
||||
let meta_cf_descriptor = ColumnFamilyDescriptor::new(SlotMeta::NAME, get_cf_options());
|
||||
@@ -627,8 +672,12 @@ pub struct WriteBatch<'a> {
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub fn open(path: &Path, access_type: AccessType) -> Result<Self> {
|
||||
let backend = Arc::new(Rocks::open(path, access_type)?);
|
||||
pub fn open(
|
||||
path: &Path,
|
||||
access_type: AccessType,
|
||||
recovery_mode: Option<BlockstoreRecoveryMode>,
|
||||
) -> Result<Self> {
|
||||
let backend = Arc::new(Rocks::open(path, access_type, recovery_mode)?);
|
||||
|
||||
Ok(Database {
|
||||
backend,
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-local-cluster"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -12,22 +12,22 @@ homepage = "https://solana.com/"
|
||||
itertools = "0.9.0"
|
||||
log = "0.4.8"
|
||||
rand = "0.7.0"
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-download-utils = { path = "../download-utils", version = "1.2.21" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.21" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.21" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.21" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.22" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-download-utils = { path = "../download-utils", version = "1.2.22" }
|
||||
solana-faucet = { path = "../faucet", version = "1.2.22" }
|
||||
solana-exchange-program = { path = "../programs/exchange", version = "1.2.22" }
|
||||
solana-genesis-programs = { path = "../genesis-programs", version = "1.2.22" }
|
||||
solana-ledger = { path = "../ledger", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-runtime = { path = "../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-vest-program = { path = "../programs/vest", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
tempfile = "3.1.0"
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.21" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-log-analyzer"
|
||||
description = "The solana cluster network analysis tool"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -14,9 +14,9 @@ byte-unit = "3.1.1"
|
||||
clap = "2.33.1"
|
||||
serde = "1.0.110"
|
||||
serde_json = "1.0.53"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
|
||||
[[bin]]
|
||||
name = "solana-log-analyzer"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-logger"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Logger"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-measure"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
@@ -12,8 +12,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
jemallocator = "0.3.2"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-merkle-tree"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Merkle Tree"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -9,7 +9,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
fast-math = "0.1"
|
||||
|
||||
[dev-dependencies]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-metrics"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Metrics"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,7 +14,7 @@ gethostname = "0.2.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
reqwest = { version = "0.10.4", default-features = false, features = ["blocking", "rustls-tls", "json"] }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7.0"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-net-shaper"
|
||||
description = "The solana cluster network shaping tool"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -13,8 +13,8 @@ publish = false
|
||||
clap = "2.33.1"
|
||||
serde = "1.0.110"
|
||||
serde_json = "1.0.53"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
rand = "0.7.0"
|
||||
|
||||
[[bin]]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-net-utils"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Network Utilities"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -18,9 +18,9 @@ rand = "0.7.0"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
socket2 = "0.3.12"
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-version = { path = "../version", version = "1.2.21" }
|
||||
solana-clap-utils = { path = "../clap-utils", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-version = { path = "../version", version = "1.2.22" }
|
||||
tokio = "0.1"
|
||||
tokio-codec = "0.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-notifier"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Notifier"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-perf"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Performance APIs"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -17,11 +17,11 @@ serde = "1.0.110"
|
||||
dlopen_derive = "0.1.4"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.8"
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.21" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.22" }
|
||||
solana-budget-program = { path = "../programs/budget", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
curve25519-dalek = { version = "2" }
|
||||
|
||||
[lib]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "solana-bpf-programs"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
documentation = "https://docs.rs/solana"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "README.md"
|
||||
@@ -22,10 +22,10 @@ walkdir = "2"
|
||||
bincode = "1.1.4"
|
||||
byteorder = "1.3.2"
|
||||
elf = "0.0.10"
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-bpf-loader-program = { path = "../bpf_loader", version = "1.2.22" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
solana_rbpf = "=0.1.28"
|
||||
|
||||
[[bench]]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,8 +12,8 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
solana-bpf-rust-128bit-dep = { path = "../128bit_dep", version = "1.2.22" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-128bit-dep"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-alloc"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-dep-crate"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,7 +13,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
byteorder = { version = "1", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-dup-accounts"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-error-handling"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,7 +14,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
num-derive = "0.2"
|
||||
num-traits = "0.2"
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
thiserror = "1.0"
|
||||
|
||||
[features]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-external-spend"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoke"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -13,7 +13,7 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-bpf-rust-invoked = { path = "../invoked"}
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-invoked"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-iter"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,8 +12,8 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
solana-bpf-rust-many-args-dep = { path = "../many_args_dep", version = "1.2.22" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-many-args-dep"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-noop"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-panic"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,8 +12,8 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
solana-bpf-rust-param-passing-dep = { path = "../param_passing_dep", version = "1.2.22" }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-param-passing-dep"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
[package]
|
||||
name = "solana-bpf-rust-sysval"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF test program written in Rust"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -12,7 +12,7 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.21", default-features = false }
|
||||
solana-sdk = { path = "../../../../sdk/", version = "1.2.22", default-features = false }
|
||||
|
||||
[features]
|
||||
program = ["solana-sdk/program"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-bpf-loader-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana BPF loader"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,9 +15,9 @@ jemalloc-sys = { version = "0.3.2", features = ["disable_initial_exec_tls"] }
|
||||
log = "0.4.8"
|
||||
num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
solana_rbpf = "=0.1.28"
|
||||
thiserror = "1.0"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-btc-spv-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,7 +15,7 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21"}
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22"}
|
||||
hex = "0.4.2"
|
||||
|
||||
[lib]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "btc_spv_bin"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Bitcoin spv parsing program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-budget-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Budget program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -16,11 +16,11 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-config-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Config program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -14,10 +14,10 @@ chrono = { version = "0.4.11", features = ["serde"] }
|
||||
log = "0.4.8"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-exchange-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Exchange program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,13 +15,13 @@ num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-failure-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana failure program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -9,10 +9,10 @@ homepage = "https://solana.com/"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-noop-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Noop program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,8 +10,8 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4.8"
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-ownable"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "ownable program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -10,13 +10,13 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bincode = "1.2.1"
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-stake-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Stake program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,14 +15,14 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../vote", version = "1.2.21" }
|
||||
solana-config-program = { path = "../config", version = "1.2.21" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../vote", version = "1.2.22" }
|
||||
solana-config-program = { path = "../config", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-logger = { path = "../../logger", version = "1.2.21" }
|
||||
solana-logger = { path = "../../logger", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-vest-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Vest program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,12 +15,12 @@ num-derive = "0.2"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-config-program = { path = "../config", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
solana-config-program = { path = "../config", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.21" }
|
||||
solana-runtime = { path = "../../runtime", version = "1.2.22" }
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib"]
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-vote-program"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana Vote program"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -15,8 +15,8 @@ num-derive = "0.3"
|
||||
num-traits = "0.2"
|
||||
serde = "1.0.110"
|
||||
serde_derive = "1.0.103"
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.21" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.21" }
|
||||
solana-metrics = { path = "../../metrics", version = "1.2.22" }
|
||||
solana-sdk = { path = "../../sdk", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
|
||||
[lib]
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-ramp-tps"
|
||||
description = "Solana Tour de SOL - TPS ramp up"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/tour-de-sol"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -16,12 +16,12 @@ reqwest = { version = "0.10.4", default-features = false }
|
||||
serde = "1.0.110"
|
||||
serde_json = "1.0.53"
|
||||
serde_yaml = "0.8.12"
|
||||
solana-core = { path = "../core", version = "1.2.21" }
|
||||
solana-client = { path = "../client", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.21" }
|
||||
solana-notifier = { path = "../notifier", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-core = { path = "../core", version = "1.2.22" }
|
||||
solana-client = { path = "../client", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-net-utils = { path = "../net-utils", version = "1.2.22" }
|
||||
solana-notifier = { path = "../notifier", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
tar = "0.4.28"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-rayon-threadlimit"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "solana-rayon-threadlimit"
|
||||
homepage = "https://solana.com/"
|
||||
readme = "../README.md"
|
||||
|
@@ -3,7 +3,7 @@ authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
edition = "2018"
|
||||
name = "solana-remote-wallet"
|
||||
description = "Blockchain, Rebuilt for Scale"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://solana.com/"
|
||||
@@ -18,7 +18,7 @@ num-derive = { version = "0.3" }
|
||||
num-traits = { version = "0.2" }
|
||||
parking_lot = "0.10"
|
||||
semver = "0.9"
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
thiserror = "1.0"
|
||||
url = "2.1.1"
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "solana-runtime"
|
||||
version = "1.2.21"
|
||||
version = "1.2.22"
|
||||
description = "Solana runtime"
|
||||
authors = ["Solana Maintainers <maintainers@solana.com>"]
|
||||
repository = "https://github.com/solana-labs/solana"
|
||||
@@ -27,14 +27,14 @@ rand = "0.7.0"
|
||||
rayon = "1.3.0"
|
||||
serde = { version = "1.0.110", features = ["rc"] }
|
||||
serde_derive = "1.0.103"
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.21" }
|
||||
solana-logger = { path = "../logger", version = "1.2.21" }
|
||||
solana-measure = { path = "../measure", version = "1.2.21" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.21" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.21" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.21" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.21" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.21" }
|
||||
solana-config-program = { path = "../programs/config", version = "1.2.22" }
|
||||
solana-logger = { path = "../logger", version = "1.2.22" }
|
||||
solana-measure = { path = "../measure", version = "1.2.22" }
|
||||
solana-metrics = { path = "../metrics", version = "1.2.22" }
|
||||
solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "1.2.22" }
|
||||
solana-sdk = { path = "../sdk", version = "1.2.22" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "1.2.22" }
|
||||
solana-vote-program = { path = "../programs/vote", version = "1.2.22" }
|
||||
tempfile = "3.1.0"
|
||||
thiserror = "1.0"
|
||||
|
||||
@@ -44,7 +44,7 @@ name = "solana_runtime"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.3.0"
|
||||
solana-noop-program = { path = "../programs/noop", version = "1.2.21" }
|
||||
solana-noop-program = { path = "../programs/noop", version = "1.2.22" }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
targets = ["x86_64-unknown-linux-gnu"]
|
||||
|
@@ -155,8 +155,9 @@ impl Accounts {
|
||||
let (account, rent) =
|
||||
AccountsDB::load(storage, ancestors, accounts_index, key)
|
||||
.and_then(|(mut account, _)| {
|
||||
if message.is_writable(i) && !account.executable {
|
||||
let rent_due = rent_collector.update(&key, &mut account);
|
||||
if message.is_writable(i) {
|
||||
let rent_due = rent_collector
|
||||
.collect_from_existing_account(&key, &mut account);
|
||||
Some((account, rent_due))
|
||||
} else {
|
||||
Some((account, 0))
|
||||
@@ -751,8 +752,7 @@ impl Accounts {
|
||||
);
|
||||
if message.is_writable(i) {
|
||||
if account.rent_epoch == 0 {
|
||||
account.rent_epoch = rent_collector.epoch;
|
||||
acc.2 += rent_collector.update(&key, account);
|
||||
acc.2 += rent_collector.collect_from_created_account(&key, account);
|
||||
}
|
||||
accounts.push((key, &*account));
|
||||
}
|
||||
|
@@ -54,7 +54,6 @@ use solana_sdk::{
|
||||
slot_history::SlotHistory,
|
||||
system_transaction,
|
||||
sysvar::{self, Sysvar},
|
||||
timing::years_as_slots,
|
||||
transaction::{Result, Transaction, TransactionError},
|
||||
};
|
||||
use solana_stake_program::stake_state::{self, Delegation, PointValue};
|
||||
@@ -945,18 +944,13 @@ impl Bank {
|
||||
.unwrap()
|
||||
.genesis_hash(&genesis_config.hash(), &self.fee_calculator);
|
||||
|
||||
self.hashes_per_tick = genesis_config.poh_config.hashes_per_tick;
|
||||
self.ticks_per_slot = genesis_config.ticks_per_slot;
|
||||
self.ns_per_slot = genesis_config.poh_config.target_tick_duration.as_nanos()
|
||||
* genesis_config.ticks_per_slot as u128;
|
||||
self.hashes_per_tick = genesis_config.hashes_per_tick();
|
||||
self.ticks_per_slot = genesis_config.ticks_per_slot();
|
||||
self.ns_per_slot = genesis_config.ns_per_slot();
|
||||
self.genesis_creation_time = genesis_config.creation_time;
|
||||
self.unused = genesis_config.unused;
|
||||
self.max_tick_height = (self.slot + 1) * self.ticks_per_slot;
|
||||
self.slots_per_year = years_as_slots(
|
||||
1.0,
|
||||
&genesis_config.poh_config.target_tick_duration,
|
||||
self.ticks_per_slot,
|
||||
);
|
||||
self.slots_per_year = genesis_config.slots_per_year();
|
||||
|
||||
self.epoch_schedule = genesis_config.epoch_schedule;
|
||||
|
||||
@@ -1859,7 +1853,9 @@ impl Bank {
|
||||
// parallelize?
|
||||
let mut rent = 0;
|
||||
for (pubkey, mut account) in accounts {
|
||||
rent += self.rent_collector.update(&pubkey, &mut account);
|
||||
rent += self
|
||||
.rent_collector
|
||||
.collect_from_existing_account(&pubkey, &mut account);
|
||||
// Store all of them unconditionally to purge old AppendVec,
|
||||
// even if collected rent is 0 (= not updated).
|
||||
self.store_account(&pubkey, &account);
|
||||
@@ -2296,10 +2292,25 @@ impl Bank {
|
||||
|
||||
pub fn deposit(&self, pubkey: &Pubkey, lamports: u64) {
|
||||
let mut account = self.get_account(pubkey).unwrap_or_default();
|
||||
self.collected_rent.fetch_add(
|
||||
self.rent_collector.update(pubkey, &mut account),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
|
||||
let should_be_in_new_behavior = match self.operating_mode() {
|
||||
OperatingMode::Development => true,
|
||||
OperatingMode::Preview => self.epoch() >= Epoch::max_value(),
|
||||
OperatingMode::Stable => self.epoch() >= Epoch::max_value(),
|
||||
};
|
||||
|
||||
// don't collect rents if we're in the new behavior;
|
||||
// in genral, it's not worthwhile to account for rents outside the runtime (transactions)
|
||||
// there are too many and subtly nuanced modification codepaths
|
||||
if !should_be_in_new_behavior {
|
||||
// previously we're too much collecting rents as if it existed since epoch 0...
|
||||
self.collected_rent.fetch_add(
|
||||
self.rent_collector
|
||||
.collect_from_existing_account(pubkey, &mut account),
|
||||
Ordering::Relaxed,
|
||||
);
|
||||
}
|
||||
|
||||
account.lamports += lamports;
|
||||
self.store_account(pubkey, &account);
|
||||
}
|
||||
@@ -2899,7 +2910,7 @@ mod tests {
|
||||
signature::{Keypair, Signer},
|
||||
system_instruction, system_program,
|
||||
sysvar::{fees::Fees, rewards::Rewards},
|
||||
timing::duration_as_s,
|
||||
timing::{duration_as_s, years_as_slots},
|
||||
};
|
||||
use solana_stake_program::{
|
||||
stake_instruction,
|
||||
|
@@ -108,14 +108,12 @@ impl NativeLoader {
|
||||
Ok(entrypoint)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Unable to find program entrypoint in {:?}: {:?})", name, e);
|
||||
Err(NativeLoaderError::EntrypointNotFound.into())
|
||||
panic!("Unable to find program entrypoint in {:?}: {:?})", name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to load: {:?}", e);
|
||||
Err(NativeLoaderError::FailedToLoad.into())
|
||||
panic!("Failed to load: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,8 +133,7 @@ impl NativeLoader {
|
||||
let name = match str::from_utf8(name_vec) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
warn!("Invalid UTF-8 sequence: {}", e);
|
||||
return Err(NativeLoaderError::InvalidEntrypointName.into());
|
||||
panic!("Invalid UTF-8 sequence: {}", e);
|
||||
}
|
||||
};
|
||||
trace!("Call native {:?}", name);
|
||||
|
@@ -1,10 +1,10 @@
|
||||
//! calculate and collect rent from Accounts
|
||||
use solana_sdk::{
|
||||
account::Account, clock::Epoch, epoch_schedule::EpochSchedule, incinerator, pubkey::Pubkey,
|
||||
rent::Rent, sysvar,
|
||||
account::Account, clock::Epoch, epoch_schedule::EpochSchedule, genesis_config::GenesisConfig,
|
||||
incinerator, pubkey::Pubkey, rent::Rent, sysvar,
|
||||
};
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct RentCollector {
|
||||
pub epoch: Epoch,
|
||||
pub epoch_schedule: EpochSchedule,
|
||||
@@ -12,6 +12,18 @@ pub struct RentCollector {
|
||||
pub rent: Rent,
|
||||
}
|
||||
|
||||
impl Default for RentCollector {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
epoch: Epoch::default(),
|
||||
epoch_schedule: EpochSchedule::default(),
|
||||
// derive default value using GenesisConfig::default()
|
||||
slots_per_year: GenesisConfig::default().slots_per_year(),
|
||||
rent: Rent::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RentCollector {
|
||||
pub fn new(
|
||||
epoch: Epoch,
|
||||
@@ -36,7 +48,8 @@ impl RentCollector {
|
||||
// updates this account's lamports and status and returns
|
||||
// the account rent collected, if any
|
||||
//
|
||||
pub fn update(&self, address: &Pubkey, account: &mut Account) -> u64 {
|
||||
#[must_use = "add to Bank::collected_rent"]
|
||||
pub fn collect_from_existing_account(&self, address: &Pubkey, account: &mut Account) -> u64 {
|
||||
if account.executable
|
||||
|| account.rent_epoch > self.epoch
|
||||
|| sysvar::check_id(&account.owner)
|
||||
@@ -70,4 +83,48 @@ impl RentCollector {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "add to Bank::collected_rent"]
|
||||
pub fn collect_from_created_account(&self, address: &Pubkey, account: &mut Account) -> u64 {
|
||||
// initialize rent_epoch as created at this epoch
|
||||
account.rent_epoch = self.epoch;
|
||||
self.collect_from_existing_account(address, account)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_collect_from_account_created_and_existing() {
|
||||
let old_lamports = 1000;
|
||||
let old_epoch = 1;
|
||||
let new_epoch = 3;
|
||||
|
||||
let (mut created_account, mut existing_account) = {
|
||||
let mut account = Account::default();
|
||||
account.lamports = old_lamports;
|
||||
account.rent_epoch = old_epoch;
|
||||
|
||||
(account.clone(), account)
|
||||
};
|
||||
|
||||
let rent_collector = RentCollector::default().clone_with_epoch(new_epoch);
|
||||
|
||||
let collected =
|
||||
rent_collector.collect_from_created_account(&Pubkey::new_rand(), &mut created_account);
|
||||
assert!(created_account.lamports < old_lamports);
|
||||
assert_eq!(created_account.lamports + collected, old_lamports);
|
||||
assert_ne!(created_account.rent_epoch, old_epoch);
|
||||
|
||||
let collected = rent_collector
|
||||
.collect_from_existing_account(&Pubkey::new_rand(), &mut existing_account);
|
||||
assert!(existing_account.lamports < old_lamports);
|
||||
assert_eq!(existing_account.lamports + collected, old_lamports);
|
||||
assert_ne!(existing_account.rent_epoch, old_epoch);
|
||||
|
||||
assert!(created_account.lamports > existing_account.lamports);
|
||||
assert_eq!(created_account.rent_epoch, existing_account.rent_epoch);
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user