Compare commits

...

16 Commits

Author SHA1 Message Date
mergify[bot]
3124a88284 Move cluster slots update to separate thread (bp #11523) (#11557)
* Move cluster slots update to separate thread (#11523)

* Add cluster_slots_service

Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 7ef50a9352)

# Conflicts:
#	core/src/repair_service.rs
#	core/src/retransmit_stage.rs

* Fix conflicts

Co-authored-by: carllin <wumu727@gmail.com>
Co-authored-by: Carl <carl@solana.com>
2020-08-11 22:54:29 +00:00
mergify[bot]
e76a2065e3 Gossip log (#11555) (#11561)
Co-authored-by: Carl <carl@solana.com>
(cherry picked from commit 1b238dd63e)

Co-authored-by: carllin <wumu727@gmail.com>
2020-08-11 22:27:35 +00:00
mergify[bot]
45f8e453a9 Add getTokenLargestAccounts to docs (#11560) (#11563)
(cherry picked from commit 697a0e2947)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-11 21:21:44 +00:00
mergify[bot]
20f9c12855 panic on native load failure (#11182) (#11554)
(cherry picked from commit e75f0bdfd3)

Co-authored-by: Jack May <jack@solana.com>
2020-08-11 19:56:23 +00:00
mergify[bot]
4218414c87 filter out old gossip pull requests (#11448) (#11552)
* init

* builds

* stats

* revert

* tests

* clippy

* add some jitter

* shorter jitter timer

* update

* fixup! update

* use saturating_sub

* fix filters

(cherry picked from commit 713851b68d)

Co-authored-by: anatoly yakovenko <anatoly@solana.com>
2020-08-11 19:50:49 +00:00
mergify[bot]
60c91d386f Adapt RpcClient to recent token method changes (bp #11519) (#11547)
* Adapt RpcClient to recent token method changes (#11519)

* Avoid skip_serializing_if since that breaks deserialization

* Adapt RpcClient to recent token method changes

(cherry picked from commit 17645ee20c)

# Conflicts:
#	client/src/rpc_client.rs

* Fix conflicts

Co-authored-by: Michael Vines <mvines@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 18:00:35 +00:00
mergify[bot]
e477501687 Fix bad rent in Bank::deposit as if since epoch 0 (bp #10468) (#11538)
* Fix bad rent in Bank::deposit as if since epoch 0 (#10468)

* Fix bad rent in Bank::deposit as if since epoch 0

* Remove redundant predicate

* Rename

* Start to add tests with some cleanup

* Forgot to add refactor code...

* Enchance test

* Really fix rent timing in deposit with robust test

* Simplify new behavior by disabling rent altogether

(cherry picked from commit 6c242f3fec)

# Conflicts:
#	runtime/src/accounts.rs
#	runtime/src/rent_collector.rs

* Fix conflict

* Fix clippy

Co-authored-by: Ryo Onodera <ryoqun@gmail.com>
2020-08-11 16:55:19 +00:00
mergify[bot]
20463e141e Fix simulateTransaction JSON-RPC docs (#11533) (#11534)
(cherry picked from commit f12fc66a69)

Co-authored-by: Justin Starry <justin@solana.com>
2020-08-11 10:24:44 +00:00
mergify[bot]
e699462ed3 Fix solana CLI deploy (bp #11520) (#11529)
* Fix solana CLI deploy (#11520)

* Refresh blockhash for program writes and finalize transactions

* Refactor to use current api, eliminating an rpc call

* Review comment

(cherry picked from commit c0d6761f63)

# Conflicts:
#	cli/src/cli.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 10:20:15 +00:00
mergify[bot]
8b345f3258 Add config param to specify offset/length for single and program account info (bp #11515) (#11517)
* Add config param to specify offset/length for single and program account info (#11515)

* Add config param to specify dataSlice for account info and program accounts

* Use match instead of if

(cherry picked from commit 88ca04dbdb)

# Conflicts:
#	core/src/rpc.rs

* Fix conflicts

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
2020-08-11 00:21:47 +00:00
mergify[bot]
56436a6271 Fix parsing of spl-token Mint (#11512) (#11513)
* Add failing test

* Fix jsonParsed mint

(cherry picked from commit da210ddd51)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 22:08:19 +00:00
mergify[bot]
805ea6f469 Return account data size with parsed accounts (#11506) (#11510)
(cherry picked from commit 1925b0bd0b)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 20:31:58 +00:00
mergify[bot]
1db1d173fc Blockstore address signatures: handle slots that cross primary indexes, and refactor get_confirmed_signatures_for_address2 (#11497) (#11507)
* Freeze address-signature index in the middle of slot to show failure case

* Secondary filter on signature

* Use AddressSignatures iterator instead of manually decrementing slots

* Remove unused method

* Add metrics

* Add transaction-status-index doccumentation

(cherry picked from commit de5fb3ba0e)

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
2020-08-10 17:50:05 +00:00
sakridge
11476038cd Add db recovery methods (#10838) (#11496) 2020-08-10 08:20:12 -07:00
mergify[bot]
a669ef3abb account subcommand now requests binary64 (#11494)
(cherry picked from commit a4f5f3e978)

Co-authored-by: Michael Vines <mvines@gmail.com>
2020-08-09 22:35:19 +00:00
Michael Vines
dbbdfa1dbb Bump version to v1.2.22 2020-08-09 18:02:02 +00:00
119 changed files with 1771 additions and 1174 deletions

299
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -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"

View File

@@ -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]);
}
}

View File

@@ -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);
}
}

View File

@@ -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,
}),
);

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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

View File

@@ -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"

View File

@@ -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/"

View File

@@ -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]]

View File

@@ -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(

View File

@@ -350,6 +350,7 @@ mod tests {
nonce_account,
UiAccountEncoding::Binary64,
None,
None,
);
let get_account_response = json!(Response {
context: RpcResponseContext { slot: 1 },

View File

@@ -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"]

View File

@@ -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,

View File

@@ -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>,
}

View File

@@ -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"

View File

@@ -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",

View 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);
}
}

View File

@@ -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(

View File

@@ -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

View File

@@ -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;

View File

@@ -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!();

View File

@@ -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(())
}
}

View File

@@ -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,
}
}
})
);
}
}

View File

@@ -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,
}),
);

View File

@@ -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,

View File

@@ -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();

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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",

View File

@@ -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"

View File

@@ -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

View File

@@ -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`.

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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]]

View File

@@ -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"]

View File

@@ -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"

View File

@@ -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]]

View File

@@ -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"] }

View File

@@ -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,

View File

@@ -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");

View File

@@ -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"]

View File

@@ -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]);
}

View File

@@ -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,

View File

@@ -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,

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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"

View File

@@ -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]]

View File

@@ -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"

View File

@@ -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"

View File

@@ -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]

View File

@@ -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]]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"

View File

@@ -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]

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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"]

View File

@@ -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]

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"]

View File

@@ -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));
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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