sdk: Upgrade to borsh 1.2.1 (#34355)

* sdk: Update to borsh 1, revert borsh 0.9 / 0.10

* Restore borsh 0.10 and 0.9 support

* Update sbf lockfile

* Add borsh 0.10 implementations for stake types

* Fix weirdness on whitespace

* Update to borsh 1.2.1

* Update changelog

* compute-budget: Move `pack` under dev-context-only-utils

* Revert test to use HashMap

* transaction-status: Add comment about borsh version
This commit is contained in:
Jon Cinque 2023-12-08 13:18:10 +01:00 committed by GitHub
parent 132c910f81
commit cfb16ab76a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 840 additions and 176 deletions

View File

@ -18,7 +18,10 @@ Release channels have their own copy of this changelog:
* The default for `--use-snapshot-archives-at-startup` is now `when-newest` (#33883)
* The default for `solana-ledger-tool`, however, remains `always` (#34228)
* Added `central-scheduler` option for `--block-production-method` (#33890)
* Updated to Borsh v1
* Upgrade Notes
* `solana-program` and `solana-sdk` default to support for Borsh v1, with
limited backward compatibility for v0.10 and v0.9. Please upgrade to Borsh v1.
## [1.17.0]
* Changes

79
Cargo.lock generated
View File

@ -726,6 +726,16 @@ dependencies = [
"hashbrown 0.13.2",
]
[[package]]
name = "borsh"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9897ef0f1bd2362169de6d7e436ea2237dc1085d7d1e4db75f4be34d86f309d1"
dependencies = [
"borsh-derive 1.2.1",
"cfg_aliases",
]
[[package]]
name = "borsh-derive"
version = "0.9.3"
@ -752,6 +762,20 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "borsh-derive"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478b41ff04256c5c8330f3dfdaaae2a5cc976a8e75088bafa4625b0d0208de8c"
dependencies = [
"once_cell",
"proc-macro-crate 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn_derive",
]
[[package]]
name = "borsh-derive-internal"
version = "0.9.3"
@ -1029,6 +1053,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.31"
@ -1530,7 +1560,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if 1.0.0",
"hashbrown 0.14.1",
"hashbrown 0.14.3",
"lock_api",
"once_cell",
"parking_lot_core 0.9.8",
@ -2341,9 +2371,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.14.1"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
name = "headers"
@ -2670,7 +2700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
dependencies = [
"equivalent",
"hashbrown 0.14.1",
"hashbrown 0.14.3",
"rayon",
]
@ -3488,7 +3518,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e"
dependencies = [
"proc-macro-crate 1.1.0",
"proc-macro-crate 2.0.0",
"proc-macro2",
"quote",
"syn 2.0.39",
@ -4026,6 +4056,15 @@ dependencies = [
"toml 0.5.8",
]
[[package]]
name = "proc-macro-crate"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8"
dependencies = [
"toml_edit 0.20.7",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -5395,7 +5434,7 @@ dependencies = [
name = "solana-banks-client"
version = "1.18.0"
dependencies = [
"borsh 0.10.3",
"borsh 1.2.1",
"futures 0.3.29",
"solana-banks-interface",
"solana-banks-server",
@ -6652,6 +6691,7 @@ dependencies = [
"blake3",
"borsh 0.10.3",
"borsh 0.9.3",
"borsh 1.2.1",
"bs58",
"bv",
"bytemuck",
@ -7089,7 +7129,7 @@ dependencies = [
"base64 0.21.5",
"bincode",
"bitflags 2.4.1",
"borsh 0.10.3",
"borsh 1.2.1",
"bs58",
"bytemuck",
"byteorder",
@ -8073,6 +8113,18 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "syn_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]]
name = "sync_wrapper"
version = "0.1.1"
@ -8542,7 +8594,7 @@ dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
"toml_edit 0.21.0",
]
[[package]]
@ -8554,6 +8606,17 @@ dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81"
dependencies = [
"indexmap 2.1.0",
"toml_datetime",
"winnow",
]
[[package]]
name = "toml_edit"
version = "0.21.0"

View File

@ -155,7 +155,7 @@ bincode = "1.3.3"
bitflags = { version = "2.3.3", features = ["serde"] }
blake3 = "1.5.0"
block-buffer = "0.10.4"
borsh = "0.10.3"
borsh = { version = "1.2.1", features = ["derive", "unstable__schema"] }
bs58 = "0.4.0"
bv = "0.11.1"
byte-unit = "4.0.19"

View File

@ -32,6 +32,7 @@ name = "solana_cost_model"
[dev-dependencies]
solana-logger = { workspace = true }
solana-sdk = { workspace = true, features = ["dev-context-only-utils"] }
static_assertions = { workspace = true }
test-case = { workspace = true }

View File

@ -16,7 +16,7 @@ use {
},
},
solana_sdk::{
borsh0_10::try_from_slice_unchecked,
borsh1::try_from_slice_unchecked,
compute_budget::{self, ComputeBudgetInstruction},
feature_set::{include_loaded_accounts_data_size_in_fee_calculation, FeatureSet},
fee::FeeStructure,

View File

@ -5,7 +5,7 @@ use {
prioritization_fee::{PrioritizationFeeDetails, PrioritizationFeeType},
},
solana_sdk::{
borsh0_10::try_from_slice_unchecked,
borsh1::try_from_slice_unchecked,
compute_budget::{self, ComputeBudgetInstruction},
entrypoint::HEAP_LENGTH as MIN_HEAP_FRAME_BYTES,
feature_set::{

View File

@ -686,6 +686,16 @@ dependencies = [
"hashbrown 0.13.2",
]
[[package]]
name = "borsh"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9897ef0f1bd2362169de6d7e436ea2237dc1085d7d1e4db75f4be34d86f309d1"
dependencies = [
"borsh-derive 1.2.1",
"cfg_aliases",
]
[[package]]
name = "borsh-derive"
version = "0.9.3"
@ -712,6 +722,20 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "borsh-derive"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478b41ff04256c5c8330f3dfdaaae2a5cc976a8e75088bafa4625b0d0208de8c"
dependencies = [
"once_cell",
"proc-macro-crate 2.0.1",
"proc-macro2",
"quote",
"syn 2.0.39",
"syn_derive",
]
[[package]]
name = "borsh-derive-internal"
version = "0.9.3"
@ -914,6 +938,12 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.31"
@ -3119,7 +3149,7 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e"
dependencies = [
"proc-macro-crate 1.1.3",
"proc-macro-crate 2.0.1",
"proc-macro2",
"quote",
"syn 2.0.39",
@ -3616,6 +3646,16 @@ dependencies = [
"toml",
]
[[package]]
name = "proc-macro-crate"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a"
dependencies = [
"toml_datetime",
"toml_edit",
]
[[package]]
name = "proc-macro-error"
version = "1.0.4"
@ -4718,7 +4758,7 @@ dependencies = [
name = "solana-banks-client"
version = "1.18.0"
dependencies = [
"borsh 0.10.3",
"borsh 1.2.1",
"futures 0.3.29",
"solana-banks-interface",
"solana-program",
@ -5415,6 +5455,7 @@ dependencies = [
"blake3",
"borsh 0.10.3",
"borsh 0.9.3",
"borsh 1.2.1",
"bs58",
"bv",
"bytemuck",
@ -6197,7 +6238,7 @@ dependencies = [
"base64 0.21.5",
"bincode",
"bitflags 2.4.1",
"borsh 0.10.3",
"borsh 1.2.1",
"bs58",
"bytemuck",
"byteorder 1.5.0",
@ -6993,6 +7034,18 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "syn_derive"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]]
name = "sync_wrapper"
version = "0.1.1"
@ -7423,6 +7476,23 @@ dependencies = [
"serde",
]
[[package]]
name = "toml_datetime"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
[[package]]
name = "toml_edit"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338"
dependencies = [
"indexmap 2.1.0",
"toml_datetime",
"winnow",
]
[[package]]
name = "tonic"
version = "0.9.2"
@ -8058,6 +8128,15 @@ version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.5.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e87b8dfbe3baffbe687eef2e164e32286eff31a5ee16463ce03d991643ec94"
dependencies = [
"memchr",
]
[[package]]
name = "winreg"
version = "0.50.0"

View File

@ -15,6 +15,7 @@ rust-version = "1.72.0" # solana platform-tools rust version
bincode = { workspace = true }
blake3 = { workspace = true, features = ["digest", "traits-preview"] }
borsh = { workspace = true }
borsh0-10 = { package = "borsh", version = "0.10.3" }
borsh0-9 = { package = "borsh", version = "0.9.3" }
bs58 = { workspace = true }
bv = { workspace = true, features = ["serde"] }

View File

@ -31,6 +31,7 @@ const MAX_BASE58_LEN: usize = 44;
Hash,
AbiExample,
)]
#[borsh(crate = "borsh")]
#[repr(transparent)]
pub struct Hash(pub [u8; HASH_BYTES]);

View File

@ -8,7 +8,7 @@
//! be removed in a future release
//!
//! [borsh]: https://borsh.io/
use borsh::{maybestd::io::Error, BorshDeserialize, BorshSchema, BorshSerialize};
use borsh0_10::{maybestd::io::Error, BorshDeserialize, BorshSchema, BorshSerialize};
/// Get the worst-case packed length for the given BorshSchema
///
@ -19,6 +19,7 @@ use borsh::{maybestd::io::Error, BorshDeserialize, BorshSchema, BorshSerialize};
note = "Please use `borsh0_10::get_packed_len` instead"
)]
pub fn get_packed_len<S: BorshSchema>() -> usize {
#[allow(deprecated)]
crate::borsh0_10::get_packed_len::<S>()
}
@ -36,6 +37,7 @@ pub fn get_packed_len<S: BorshSchema>() -> usize {
note = "Please use `borsh0_10::try_from_slice_unchecked` instead"
)]
pub fn try_from_slice_unchecked<T: BorshDeserialize>(data: &[u8]) -> Result<T, Error> {
#[allow(deprecated)]
crate::borsh0_10::try_from_slice_unchecked::<T>(data)
}
@ -50,10 +52,11 @@ pub fn try_from_slice_unchecked<T: BorshDeserialize>(data: &[u8]) -> Result<T, E
note = "Please use `borsh0_10::get_instance_packed_len` instead"
)]
pub fn get_instance_packed_len<T: BorshSerialize>(instance: &T) -> Result<usize, Error> {
#[allow(deprecated)]
crate::borsh0_10::get_instance_packed_len(instance)
}
macro_rules! impl_get_packed_len {
macro_rules! impl_get_packed_len_v0 {
($borsh:ident $(,#[$meta:meta])?) => {
/// Get the worst-case packed length for the given BorshSchema
///
@ -113,10 +116,72 @@ macro_rules! impl_get_packed_len {
}
}
}
pub(crate) use impl_get_packed_len;
pub(crate) use impl_get_packed_len_v0;
macro_rules! impl_get_packed_len_v1 {
($borsh:ident $(,#[$meta:meta])?) => {
/// Get the worst-case packed length for the given BorshSchema
///
/// Note: due to the serializer currently used by Borsh, this function cannot
/// be used on-chain in the Solana SBF execution environment.
$(#[$meta])?
pub fn get_packed_len<S: $borsh::BorshSchema>() -> usize {
let container = $borsh::schema_container_of::<S>();
get_declaration_packed_len(container.declaration(), &container)
}
/// Get packed length for the given BorshSchema Declaration
fn get_declaration_packed_len(
declaration: &str,
container: &$borsh::schema::BorshSchemaContainer,
) -> usize {
match container.get_definition(declaration) {
Some($borsh::schema::Definition::Sequence { length_width, length_range, elements }) if *length_width == 0 => {
*length_range.end() as usize * get_declaration_packed_len(elements, container)
}
Some($borsh::schema::Definition::Enum { tag_width, variants }) => {
(*tag_width as usize) + variants
.iter()
.map(|(_, _, declaration)| get_declaration_packed_len(declaration, container))
.max()
.unwrap_or(0)
}
Some($borsh::schema::Definition::Struct { fields }) => match fields {
$borsh::schema::Fields::NamedFields(named_fields) => named_fields
.iter()
.map(|(_, declaration)| get_declaration_packed_len(declaration, container))
.sum(),
$borsh::schema::Fields::UnnamedFields(declarations) => declarations
.iter()
.map(|declaration| get_declaration_packed_len(declaration, container))
.sum(),
$borsh::schema::Fields::Empty => 0,
},
Some($borsh::schema::Definition::Sequence {
..
}) => panic!("Missing support for Definition::Sequence"),
Some($borsh::schema::Definition::Tuple { elements }) => elements
.iter()
.map(|element| get_declaration_packed_len(element, container))
.sum(),
Some($borsh::schema::Definition::Primitive(size)) => *size as usize,
None => match declaration {
"bool" | "u8" | "i8" => 1,
"u16" | "i16" => 2,
"u32" | "i32" => 4,
"u64" | "i64" => 8,
"u128" | "i128" => 16,
"nil" => 0,
_ => panic!("Missing primitive type: {declaration}"),
},
}
}
}
}
pub(crate) use impl_get_packed_len_v1;
macro_rules! impl_try_from_slice_unchecked {
($borsh:ident $(,#[$meta:meta])?) => {
($borsh:ident, $borsh_io:ident $(,#[$meta:meta])?) => {
/// Deserializes without checking that the entire slice has been consumed
///
/// Normally, `try_from_slice` checks the length of the final slice to ensure
@ -127,7 +192,7 @@ macro_rules! impl_try_from_slice_unchecked {
/// user passes a buffer destined for a different type, the error won't get caught
/// as easily.
$(#[$meta])?
pub fn try_from_slice_unchecked<T: $borsh::BorshDeserialize>(data: &[u8]) -> Result<T, $borsh::maybestd::io::Error> {
pub fn try_from_slice_unchecked<T: $borsh::BorshDeserialize>(data: &[u8]) -> Result<T, $borsh_io::Error> {
let mut data_mut = data;
let result = T::deserialize(&mut data_mut)?;
Ok(result)
@ -137,21 +202,21 @@ macro_rules! impl_try_from_slice_unchecked {
pub(crate) use impl_try_from_slice_unchecked;
macro_rules! impl_get_instance_packed_len {
($borsh:ident $(,#[$meta:meta])?) => {
($borsh:ident, $borsh_io:ident $(,#[$meta:meta])?) => {
/// Helper struct which to count how much data would be written during serialization
#[derive(Default)]
struct WriteCounter {
count: usize,
}
impl $borsh::maybestd::io::Write for WriteCounter {
fn write(&mut self, data: &[u8]) -> Result<usize, $borsh::maybestd::io::Error> {
impl $borsh_io::Write for WriteCounter {
fn write(&mut self, data: &[u8]) -> Result<usize, $borsh_io::Error> {
let amount = data.len();
self.count += amount;
Ok(amount)
}
fn flush(&mut self) -> Result<(), $borsh::maybestd::io::Error> {
fn flush(&mut self) -> Result<(), $borsh_io::Error> {
Ok(())
}
}
@ -163,7 +228,7 @@ macro_rules! impl_get_instance_packed_len {
/// length only from the type's schema, this can be used when an instance already
/// exists, to figure out how much space to allocate in an account.
$(#[$meta])?
pub fn get_instance_packed_len<T: $borsh::BorshSerialize>(instance: &T) -> Result<usize, $borsh::maybestd::io::Error> {
pub fn get_instance_packed_len<T: $borsh::BorshSerialize>(instance: &T) -> Result<usize, $borsh_io::Error> {
let mut counter = WriteCounter::default();
instance.serialize(&mut counter)?;
Ok(counter.count)
@ -174,11 +239,13 @@ pub(crate) use impl_get_instance_packed_len;
#[cfg(test)]
macro_rules! impl_tests {
($borsh:ident) => {
($borsh:ident, $borsh_io:ident) => {
extern crate alloc;
use {
super::*,
std::{collections::HashMap, mem::size_of},
$borsh::{maybestd::io::ErrorKind, BorshDeserialize, BorshSerialize},
$borsh::{BorshDeserialize, BorshSerialize},
$borsh_io::ErrorKind,
};
type Child = [u8; 64];

View File

@ -2,16 +2,40 @@
//! Utilities for the [borsh] serialization format, version 0.10.
//!
//! [borsh]: https://borsh.io/
use crate::borsh::{
impl_get_instance_packed_len, impl_get_packed_len, impl_try_from_slice_unchecked,
use {
crate::borsh::{
impl_get_instance_packed_len, impl_get_packed_len_v0, impl_try_from_slice_unchecked,
},
borsh0_10::maybestd::io,
};
impl_get_packed_len!(borsh);
impl_try_from_slice_unchecked!(borsh);
impl_get_instance_packed_len!(borsh);
impl_get_packed_len_v0!(
borsh0_10,
#[deprecated(
since = "1.18.0",
note = "Please upgrade to Borsh 1.X and use `borsh1::get_packed_len` instead"
)]
);
impl_try_from_slice_unchecked!(
borsh0_10,
io,
#[deprecated(
since = "1.18.0",
note = "Please upgrade to Borsh 1.X and use `borsh1::try_from_slice_unchecked` instead"
)]
);
impl_get_instance_packed_len!(
borsh0_10,
io,
#[deprecated(
since = "1.18.0",
note = "Please upgrade to Borsh 1.X and use `borsh1::get_instance_packed_len` instead"
)]
);
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use crate::borsh::impl_tests;
impl_tests!(borsh);
use {crate::borsh::impl_tests, borsh0_10::maybestd::io};
impl_tests!(borsh0_10, io);
}

View File

@ -5,35 +5,40 @@
//! borsh 0.9, even though this crate canonically uses borsh 0.10.
//!
//! [borsh]: https://borsh.io/
use crate::borsh::{
impl_get_instance_packed_len, impl_get_packed_len, impl_try_from_slice_unchecked,
use {
crate::borsh::{
impl_get_instance_packed_len, impl_get_packed_len_v0, impl_try_from_slice_unchecked,
},
borsh0_9::maybestd::io,
};
impl_get_packed_len!(
impl_get_packed_len_v0!(
borsh0_9,
#[deprecated(
since = "1.17.0",
note = "Please upgrade to Borsh 0.10 and use `borsh0_10::get_packed_len` instead"
note = "Please upgrade to Borsh 1.X and use `borsh1::get_packed_len` instead"
)]
);
impl_try_from_slice_unchecked!(
borsh0_9,
io,
#[deprecated(
since = "1.17.0",
note = "Please upgrade to Borsh 0.10 and use `borsh0_10::try_from_slice_unchecked` instead"
note = "Please upgrade to Borsh 1.X and use `borsh1::try_from_slice_unchecked` instead"
)]
);
impl_get_instance_packed_len!(
borsh0_9,
io,
#[deprecated(
since = "1.17.0",
note = "Please upgrade to Borsh 0.10 and use `borsh0_10::get_instance_packed_len` instead"
note = "Please upgrade to Borsh 1.X and use `borsh1::get_instance_packed_len` instead"
)]
);
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use crate::borsh::impl_tests;
impl_tests!(borsh0_9);
use {crate::borsh::impl_tests, borsh0_9::maybestd::io};
impl_tests!(borsh0_9, io);
}

20
sdk/program/src/borsh1.rs Normal file
View File

@ -0,0 +1,20 @@
#![allow(clippy::arithmetic_side_effects)]
//! Utilities for the [borsh] serialization format, version 1.
//!
//! [borsh]: https://borsh.io/
use {
crate::borsh::{
impl_get_instance_packed_len, impl_get_packed_len_v1, impl_try_from_slice_unchecked,
},
borsh::io,
};
impl_get_packed_len_v1!(borsh);
impl_try_from_slice_unchecked!(borsh, io);
impl_get_instance_packed_len!(borsh, io);
#[cfg(test)]
mod tests {
use {crate::borsh::impl_tests, borsh::io};
impl_tests!(borsh, io);
}

View File

@ -46,6 +46,7 @@ const MAX_BASE58_LEN: usize = 44;
Pod,
Zeroable,
)]
#[borsh(crate = "borsh")]
#[repr(transparent)]
pub struct Hash(pub(crate) [u8; HASH_BYTES]);

View File

@ -364,6 +364,7 @@ impl Instruction {
/// # use borsh::{BorshSerialize, BorshDeserialize};
/// #
/// #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// pub struct MyInstruction {
/// pub lamports: u64,
/// }
@ -391,7 +392,7 @@ impl Instruction {
data: &T,
accounts: Vec<AccountMeta>,
) -> Self {
let data = data.try_to_vec().unwrap();
let data = borsh::to_vec(data).unwrap();
Self {
program_id,
accounts,
@ -466,10 +467,10 @@ impl Instruction {
/// # pubkey::Pubkey,
/// # instruction::{AccountMeta, Instruction},
/// # };
/// # use borsh::{BorshSerialize, BorshDeserialize};
/// # use anyhow::Result;
/// # use borsh::{io::Error, BorshSerialize, BorshDeserialize};
/// #
/// #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// pub struct MyInstruction {
/// pub lamports: u64,
/// }
@ -479,7 +480,7 @@ impl Instruction {
/// from: &Pubkey,
/// to: &Pubkey,
/// lamports: u64,
/// ) -> Result<Instruction> {
/// ) -> Result<Instruction, Error> {
/// let instr = MyInstruction { lamports };
///
/// let mut instr_in_bytes: Vec<u8> = Vec::new();
@ -558,6 +559,7 @@ impl AccountMeta {
/// # use borsh::{BorshSerialize, BorshDeserialize};
/// #
/// # #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// # pub struct MyInstruction;
/// #
/// # let instruction = MyInstruction;
@ -593,6 +595,7 @@ impl AccountMeta {
/// # use borsh::{BorshSerialize, BorshDeserialize};
/// #
/// # #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// # pub struct MyInstruction;
/// #
/// # let instruction = MyInstruction;

View File

@ -29,6 +29,7 @@ const MAX_BASE58_LEN: usize = 44;
Hash,
AbiExample,
)]
#[borsh(crate = "borsh")]
#[repr(transparent)]
pub struct Hash(pub [u8; HASH_BYTES]);

View File

@ -479,6 +479,7 @@ pub mod blake3;
pub mod borsh;
pub mod borsh0_10;
pub mod borsh0_9;
pub mod borsh1;
pub mod bpf_loader;
pub mod bpf_loader_deprecated;
pub mod bpf_loader_upgradeable;

View File

@ -193,6 +193,7 @@ impl Message {
/// // another crate so it can be shared between the on-chain program and
/// // the client.
/// #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// enum BankInstruction {
/// Initialize,
/// Deposit { lamports: u64 },
@ -264,6 +265,7 @@ impl Message {
/// // another crate so it can be shared between the on-chain program and
/// // the client.
/// #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// enum BankInstruction {
/// Initialize,
/// Deposit { lamports: u64 },
@ -363,6 +365,7 @@ impl Message {
/// // another crate so it can be shared between the on-chain program and
/// // the client.
/// #[derive(BorshSerialize, BorshDeserialize)]
/// # #[borsh(crate = "borsh")]
/// enum BankInstruction {
/// Initialize,
/// Deposit { lamports: u64 },

View File

@ -3,7 +3,7 @@
#![allow(clippy::arithmetic_side_effects)]
use {
crate::{decode_error::DecodeError, instruction::InstructionError, msg, pubkey::PubkeyError},
borsh::maybestd::io::Error as BorshIoError,
borsh::io::Error as BorshIoError,
num_traits::{FromPrimitive, ToPrimitive},
std::convert::TryFrom,
thiserror::Error,

View File

@ -84,6 +84,7 @@ impl From<u64> for PubkeyError {
Serialize,
Zeroable,
)]
#[borsh(crate = "borsh")]
pub struct Pubkey(pub(crate) [u8; 32]);
impl crate::sanitize::Sanitize for Pubkey {}
@ -328,6 +329,7 @@ impl Pubkey {
/// // The computed address of the PDA will be passed to this program via
/// // the `accounts` vector of the `Instruction` type.
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct InstructionData {
/// pub vault_bump_seed: u8,
/// pub lamports: u64,
@ -409,6 +411,7 @@ impl Pubkey {
/// # use anyhow::Result;
/// #
/// # #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// # struct InstructionData {
/// # pub vault_bump_seed: u8,
/// # pub lamports: u64,
@ -668,47 +671,70 @@ impl fmt::Display for Pubkey {
}
}
impl borsh0_10::de::BorshDeserialize for Pubkey {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self(borsh0_10::BorshDeserialize::deserialize_reader(
reader,
)?))
}
}
impl borsh0_9::de::BorshDeserialize for Pubkey {
fn deserialize(buf: &mut &[u8]) -> ::core::result::Result<Self, borsh0_9::maybestd::io::Error> {
Ok(Self(borsh0_9::BorshDeserialize::deserialize(buf)?))
}
}
impl borsh0_9::BorshSchema for Pubkey
where
[u8; 32]: borsh0_9::BorshSchema,
{
fn declaration() -> borsh0_9::schema::Declaration {
"Pubkey".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_9::maybestd::collections::HashMap<
borsh0_9::schema::Declaration,
borsh0_9::schema::Definition,
>,
) {
let fields = borsh0_9::schema::Fields::UnnamedFields(<[_]>::into_vec(
borsh0_9::maybestd::boxed::Box::new([
<[u8; 32] as borsh0_9::BorshSchema>::declaration(),
]),
));
let definition = borsh0_9::schema::Definition::Struct { fields };
<Self as borsh0_9::BorshSchema>::add_definition(
<Self as borsh0_9::BorshSchema>::declaration(),
definition,
definitions,
);
<[u8; 32] as borsh0_9::BorshSchema>::add_definitions_recursively(definitions);
}
macro_rules! impl_borsh_schema {
($borsh:ident) => {
impl $borsh::BorshSchema for Pubkey
where
[u8; 32]: $borsh::BorshSchema,
{
fn declaration() -> $borsh::schema::Declaration {
"Pubkey".to_string()
}
fn add_definitions_recursively(
definitions: &mut $borsh::maybestd::collections::HashMap<
$borsh::schema::Declaration,
$borsh::schema::Definition,
>,
) {
let fields = $borsh::schema::Fields::UnnamedFields(<[_]>::into_vec(
$borsh::maybestd::boxed::Box::new([
<[u8; 32] as $borsh::BorshSchema>::declaration(),
]),
));
let definition = $borsh::schema::Definition::Struct { fields };
<Self as $borsh::BorshSchema>::add_definition(
<Self as $borsh::BorshSchema>::declaration(),
definition,
definitions,
);
<[u8; 32] as $borsh::BorshSchema>::add_definitions_recursively(definitions);
}
}
};
}
impl borsh0_9::ser::BorshSerialize for Pubkey {
fn serialize<W: borsh0_9::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_9::maybestd::io::Error> {
borsh0_9::BorshSerialize::serialize(&self.0, writer)?;
Ok(())
}
impl_borsh_schema!(borsh0_10);
impl_borsh_schema!(borsh0_9);
macro_rules! impl_borsh_serialize {
($borsh:ident) => {
impl $borsh::ser::BorshSerialize for Pubkey {
fn serialize<W: $borsh::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), $borsh::maybestd::io::Error> {
$borsh::BorshSerialize::serialize(&self.0, writer)?;
Ok(())
}
}
};
}
impl_borsh_serialize!(borsh0_10);
impl_borsh_serialize!(borsh0_9);
#[cfg(test)]
mod tests {

View File

@ -78,6 +78,7 @@ pub const SECP256K1_PUBLIC_KEY_LENGTH: usize = 64;
Hash,
AbiExample,
)]
#[borsh(crate = "borsh")]
pub struct Secp256k1Pubkey(pub [u8; SECP256K1_PUBLIC_KEY_LENGTH]);
impl Secp256k1Pubkey {
@ -254,6 +255,7 @@ impl Secp256k1Pubkey {
/// use borsh::{BorshDeserialize, BorshSerialize};
///
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct DemoSecp256k1RecoverInstruction {
/// pub message: Vec<u8>,
/// pub signature: [u8; 64],
@ -348,6 +350,7 @@ impl Secp256k1Pubkey {
/// };
/// # use borsh::{BorshDeserialize, BorshSerialize};
/// # #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// # pub struct DemoSecp256k1RecoverInstruction {
/// # pub message: Vec<u8>,
/// # pub signature: [u8; 64],

View File

@ -17,9 +17,53 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize};
Hash,
Debug,
)]
#[borsh(crate = "borsh")]
pub struct StakeFlags {
bits: u8,
}
impl borsh0_10::de::BorshDeserialize for StakeFlags {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
bits: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for StakeFlags {
fn declaration() -> borsh0_10::schema::Declaration {
"StakeFlags".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([(
"bits".to_string(),
<u8 as borsh0_10::BorshSchema>::declaration(),
)]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<u8 as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for StakeFlags {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.bits, writer)?;
Ok(())
}
}
/// Currently, only bit 1 is used. The other 7 bits are reserved for future usage.
impl StakeFlags {

View File

@ -14,7 +14,7 @@ use {
},
stake_history::{StakeHistory, StakeHistoryEntry},
},
borsh::{maybestd::io, BorshDeserialize, BorshSchema, BorshSerialize},
borsh::{io, BorshDeserialize, BorshSchema, BorshSerialize},
std::collections::HashSet,
};
@ -34,6 +34,49 @@ pub fn warmup_cooldown_rate(current_epoch: Epoch, new_rate_activation_epoch: Opt
}
}
macro_rules! impl_borsh_stake_state {
($borsh:ident) => {
impl $borsh::BorshDeserialize for StakeState {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let enum_value: u32 = $borsh::BorshDeserialize::deserialize_reader(reader)?;
match enum_value {
0 => Ok(StakeState::Uninitialized),
1 => {
let meta: Meta = $borsh::BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeState::Initialized(meta))
}
2 => {
let meta: Meta = $borsh::BorshDeserialize::deserialize_reader(reader)?;
let stake: Stake = $borsh::BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeState::Stake(meta, stake))
}
3 => Ok(StakeState::RewardsPool),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid enum value",
)),
}
}
}
impl $borsh::BorshSerialize for StakeState {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
match self {
StakeState::Uninitialized => writer.write_all(&0u32.to_le_bytes()),
StakeState::Initialized(meta) => {
writer.write_all(&1u32.to_le_bytes())?;
$borsh::BorshSerialize::serialize(&meta, writer)
}
StakeState::Stake(meta, stake) => {
writer.write_all(&2u32.to_le_bytes())?;
$borsh::BorshSerialize::serialize(&meta, writer)?;
$borsh::BorshSerialize::serialize(&stake, writer)
}
StakeState::RewardsPool => writer.write_all(&3u32.to_le_bytes()),
}
}
}
};
}
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[allow(clippy::large_enum_variant)]
#[deprecated(
@ -47,45 +90,8 @@ pub enum StakeState {
Stake(Meta, Stake),
RewardsPool,
}
impl BorshDeserialize for StakeState {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let enum_value = u32::deserialize_reader(reader)?;
match enum_value {
0 => Ok(StakeState::Uninitialized),
1 => {
let meta = Meta::deserialize_reader(reader)?;
Ok(StakeState::Initialized(meta))
}
2 => {
let meta: Meta = BorshDeserialize::deserialize_reader(reader)?;
let stake: Stake = BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeState::Stake(meta, stake))
}
3 => Ok(StakeState::RewardsPool),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid enum value",
)),
}
}
}
impl BorshSerialize for StakeState {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
match self {
StakeState::Uninitialized => writer.write_all(&0u32.to_le_bytes()),
StakeState::Initialized(meta) => {
writer.write_all(&1u32.to_le_bytes())?;
meta.serialize(writer)
}
StakeState::Stake(meta, stake) => {
writer.write_all(&2u32.to_le_bytes())?;
meta.serialize(writer)?;
stake.serialize(writer)
}
StakeState::RewardsPool => writer.write_all(&3u32.to_le_bytes()),
}
}
}
impl_borsh_stake_state!(borsh);
impl_borsh_stake_state!(borsh0_10);
impl StakeState {
/// The fixed number of bytes used to serialize each stake account
pub const fn size_of() -> usize {
@ -136,49 +142,54 @@ pub enum StakeStateV2 {
Stake(Meta, Stake, StakeFlags),
RewardsPool,
}
impl BorshDeserialize for StakeStateV2 {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let enum_value = u32::deserialize_reader(reader)?;
match enum_value {
0 => Ok(StakeStateV2::Uninitialized),
1 => {
let meta = Meta::deserialize_reader(reader)?;
Ok(StakeStateV2::Initialized(meta))
macro_rules! impl_borsh_stake_state_v2 {
($borsh:ident) => {
impl $borsh::BorshDeserialize for StakeStateV2 {
fn deserialize_reader<R: io::Read>(reader: &mut R) -> io::Result<Self> {
let enum_value: u32 = $borsh::BorshDeserialize::deserialize_reader(reader)?;
match enum_value {
0 => Ok(StakeStateV2::Uninitialized),
1 => {
let meta: Meta = $borsh::BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeStateV2::Initialized(meta))
}
2 => {
let meta: Meta = $borsh::BorshDeserialize::deserialize_reader(reader)?;
let stake: Stake = $borsh::BorshDeserialize::deserialize_reader(reader)?;
let stake_flags: StakeFlags =
$borsh::BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeStateV2::Stake(meta, stake, stake_flags))
}
3 => Ok(StakeStateV2::RewardsPool),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid enum value",
)),
}
}
2 => {
let meta: Meta = BorshDeserialize::deserialize_reader(reader)?;
let stake: Stake = BorshDeserialize::deserialize_reader(reader)?;
let stake_flags: StakeFlags = BorshDeserialize::deserialize_reader(reader)?;
Ok(StakeStateV2::Stake(meta, stake, stake_flags))
}
3 => Ok(StakeStateV2::RewardsPool),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid enum value",
)),
}
}
}
impl BorshSerialize for StakeStateV2 {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
match self {
StakeStateV2::Uninitialized => writer.write_all(&0u32.to_le_bytes()),
StakeStateV2::Initialized(meta) => {
writer.write_all(&1u32.to_le_bytes())?;
meta.serialize(writer)
impl $borsh::BorshSerialize for StakeStateV2 {
fn serialize<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
match self {
StakeStateV2::Uninitialized => writer.write_all(&0u32.to_le_bytes()),
StakeStateV2::Initialized(meta) => {
writer.write_all(&1u32.to_le_bytes())?;
$borsh::BorshSerialize::serialize(&meta, writer)
}
StakeStateV2::Stake(meta, stake, stake_flags) => {
writer.write_all(&2u32.to_le_bytes())?;
$borsh::BorshSerialize::serialize(&meta, writer)?;
$borsh::BorshSerialize::serialize(&stake, writer)?;
$borsh::BorshSerialize::serialize(&stake_flags, writer)
}
StakeStateV2::RewardsPool => writer.write_all(&3u32.to_le_bytes()),
}
}
StakeStateV2::Stake(meta, stake, stake_flags) => {
writer.write_all(&2u32.to_le_bytes())?;
meta.serialize(writer)?;
stake.serialize(writer)?;
stake_flags.serialize(writer)
}
StakeStateV2::RewardsPool => writer.write_all(&3u32.to_le_bytes()),
}
}
};
}
impl_borsh_stake_state_v2!(borsh);
impl_borsh_stake_state_v2!(borsh0_10);
impl StakeStateV2 {
/// The fixed number of bytes used to serialize each stake account
@ -241,6 +252,7 @@ pub enum StakeAuthorize {
BorshSchema,
BorshSerialize,
)]
#[borsh(crate = "borsh")]
pub struct Lockup {
/// UnixTimestamp at which this stake will allow withdrawal, unless the
/// transaction is signed by the custodian
@ -252,7 +264,6 @@ pub struct Lockup {
/// lockup constraints
pub custodian: Pubkey,
}
impl Lockup {
pub fn is_in_force(&self, clock: &Clock, custodian: Option<&Pubkey>) -> bool {
if custodian == Some(&self.custodian) {
@ -261,6 +272,65 @@ impl Lockup {
self.unix_timestamp > clock.unix_timestamp || self.epoch > clock.epoch
}
}
impl borsh0_10::de::BorshDeserialize for Lockup {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
unix_timestamp: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
epoch: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
custodian: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for Lockup {
fn declaration() -> borsh0_10::schema::Declaration {
"Lockup".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([
(
"unix_timestamp".to_string(),
<UnixTimestamp as borsh0_10::BorshSchema>::declaration(),
),
(
"epoch".to_string(),
<Epoch as borsh0_10::BorshSchema>::declaration(),
),
(
"custodian".to_string(),
<Pubkey as borsh0_10::BorshSchema>::declaration(),
),
]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<UnixTimestamp as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Epoch as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Pubkey as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for Lockup {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.unix_timestamp, writer)?;
borsh0_10::BorshSerialize::serialize(&self.epoch, writer)?;
borsh0_10::BorshSerialize::serialize(&self.custodian, writer)?;
Ok(())
}
}
#[derive(
Default,
@ -276,6 +346,7 @@ impl Lockup {
BorshSchema,
BorshSerialize,
)]
#[borsh(crate = "borsh")]
pub struct Authorized {
pub staker: Pubkey,
pub withdrawer: Pubkey,
@ -341,6 +412,58 @@ impl Authorized {
Ok(())
}
}
impl borsh0_10::de::BorshDeserialize for Authorized {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
staker: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
withdrawer: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for Authorized {
fn declaration() -> borsh0_10::schema::Declaration {
"Authorized".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([
(
"staker".to_string(),
<Pubkey as borsh0_10::BorshSchema>::declaration(),
),
(
"withdrawer".to_string(),
<Pubkey as borsh0_10::BorshSchema>::declaration(),
),
]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<Pubkey as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Pubkey as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for Authorized {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.staker, writer)?;
borsh0_10::BorshSerialize::serialize(&self.withdrawer, writer)?;
Ok(())
}
}
#[derive(
Default,
@ -356,6 +479,7 @@ impl Authorized {
BorshSchema,
BorshSerialize,
)]
#[borsh(crate = "borsh")]
pub struct Meta {
pub rent_exempt_reserve: u64,
pub authorized: Authorized,
@ -398,6 +522,65 @@ impl Meta {
}
}
}
impl borsh0_10::de::BorshDeserialize for Meta {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
rent_exempt_reserve: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
authorized: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
lockup: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for Meta {
fn declaration() -> borsh0_10::schema::Declaration {
"Meta".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([
(
"rent_exempt_reserve".to_string(),
<u64 as borsh0_10::BorshSchema>::declaration(),
),
(
"authorized".to_string(),
<Authorized as borsh0_10::BorshSchema>::declaration(),
),
(
"lockup".to_string(),
<Lockup as borsh0_10::BorshSchema>::declaration(),
),
]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<u64 as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Authorized as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Lockup as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for Meta {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.rent_exempt_reserve, writer)?;
borsh0_10::BorshSerialize::serialize(&self.authorized, writer)?;
borsh0_10::BorshSerialize::serialize(&self.lockup, writer)?;
Ok(())
}
}
#[derive(
Debug,
@ -411,6 +594,7 @@ impl Meta {
BorshSchema,
BorshSerialize,
)]
#[borsh(crate = "borsh")]
pub struct Delegation {
/// to whom the stake is delegated
pub voter_pubkey: Pubkey,
@ -644,6 +828,79 @@ impl Delegation {
}
}
}
impl borsh0_10::de::BorshDeserialize for Delegation {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
voter_pubkey: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
stake: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
activation_epoch: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
deactivation_epoch: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
warmup_cooldown_rate: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for Delegation {
fn declaration() -> borsh0_10::schema::Declaration {
"Delegation".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([
(
"voter_pubkey".to_string(),
<Pubkey as borsh0_10::BorshSchema>::declaration(),
),
(
"stake".to_string(),
<u64 as borsh0_10::BorshSchema>::declaration(),
),
(
"activation_epoch".to_string(),
<Epoch as borsh0_10::BorshSchema>::declaration(),
),
(
"deactivation_epoch".to_string(),
<Epoch as borsh0_10::BorshSchema>::declaration(),
),
(
"warmup_cooldown_rate".to_string(),
<f64 as borsh0_10::BorshSchema>::declaration(),
),
]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<Pubkey as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<u64 as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Epoch as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<Epoch as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<f64 as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for Delegation {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.voter_pubkey, writer)?;
borsh0_10::BorshSerialize::serialize(&self.stake, writer)?;
borsh0_10::BorshSerialize::serialize(&self.activation_epoch, writer)?;
borsh0_10::BorshSerialize::serialize(&self.deactivation_epoch, writer)?;
borsh0_10::BorshSerialize::serialize(&self.warmup_cooldown_rate, writer)?;
Ok(())
}
}
#[derive(
Debug,
@ -658,6 +915,7 @@ impl Delegation {
BorshSchema,
BorshSerialize,
)]
#[borsh(crate = "borsh")]
pub struct Stake {
pub delegation: Delegation,
/// credits observed is credits from vote account state when delegated or redeemed
@ -703,11 +961,63 @@ impl Stake {
}
}
}
impl borsh0_10::de::BorshDeserialize for Stake {
fn deserialize_reader<R: borsh0_10::maybestd::io::Read>(
reader: &mut R,
) -> ::core::result::Result<Self, borsh0_10::maybestd::io::Error> {
Ok(Self {
delegation: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
credits_observed: borsh0_10::BorshDeserialize::deserialize_reader(reader)?,
})
}
}
impl borsh0_10::BorshSchema for Stake {
fn declaration() -> borsh0_10::schema::Declaration {
"Stake".to_string()
}
fn add_definitions_recursively(
definitions: &mut borsh0_10::maybestd::collections::HashMap<
borsh0_10::schema::Declaration,
borsh0_10::schema::Definition,
>,
) {
let fields = borsh0_10::schema::Fields::NamedFields(<[_]>::into_vec(
borsh0_10::maybestd::boxed::Box::new([
(
"delegation".to_string(),
<Delegation as borsh0_10::BorshSchema>::declaration(),
),
(
"credits_observed".to_string(),
<u64 as borsh0_10::BorshSchema>::declaration(),
),
]),
));
let definition = borsh0_10::schema::Definition::Struct { fields };
Self::add_definition(
<Self as borsh0_10::BorshSchema>::declaration(),
definition,
definitions,
);
<Delegation as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
<u64 as borsh0_10::BorshSchema>::add_definitions_recursively(definitions);
}
}
impl borsh0_10::ser::BorshSerialize for Stake {
fn serialize<W: borsh0_10::maybestd::io::Write>(
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh0_10::maybestd::io::Error> {
borsh0_10::BorshSerialize::serialize(&self.delegation, writer)?;
borsh0_10::BorshSerialize::serialize(&self.credits_observed, writer)?;
Ok(())
}
}
#[cfg(test)]
mod test {
use {
super::*, crate::borsh0_10::try_from_slice_unchecked, assert_matches::assert_matches,
super::*, crate::borsh1::try_from_slice_unchecked, assert_matches::assert_matches,
bincode::serialize,
};
@ -719,7 +1029,7 @@ mod test {
fn check_borsh_serialization(stake: StakeStateV2) {
let bincode_serialized = serialize(&stake).unwrap();
let borsh_serialized = StakeStateV2::try_to_vec(&stake).unwrap();
let borsh_serialized = borsh::to_vec(&stake).unwrap();
assert_eq!(bincode_serialized, borsh_serialized);
}
@ -850,7 +1160,7 @@ mod test {
);
let bincode_serialized = serialize(&stake).unwrap();
let borsh_serialized = StakeStateV2::try_to_vec(&stake).unwrap();
let borsh_serialized = borsh::to_vec(&stake).unwrap();
assert_eq!(bincode_serialized[FLAG_OFFSET], expected);
assert_eq!(borsh_serialized[FLAG_OFFSET], expected);
@ -872,7 +1182,7 @@ mod test {
fn check_borsh_serialization(stake: StakeState) {
let bincode_serialized = serialize(&stake).unwrap();
let borsh_serialized = StakeState::try_to_vec(&stake).unwrap();
let borsh_serialized = borsh::to_vec(&stake).unwrap();
assert_eq!(bincode_serialized, borsh_serialized);
}

View File

@ -378,6 +378,7 @@ pub enum SystemInstruction {
/// };
///
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct CreateAccountInstruction {
/// /// The PDA seed used to distinguish the new account from other PDAs
/// pub new_account_seed: [u8; 16],
@ -594,6 +595,7 @@ pub fn create_account_with_seed(
/// };
///
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct CreateAccountInstruction {
/// /// The PDA seed used to distinguish the new account from other PDAs
/// pub new_account_seed: [u8; 16],
@ -804,6 +806,7 @@ pub fn assign_with_seed(
/// };
///
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct CreateAccountInstruction {
/// /// The PDA seed used to distinguish the new account from other PDAs
/// pub new_account_seed: [u8; 16],
@ -1023,6 +1026,7 @@ pub fn transfer_with_seed(
/// };
///
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct CreateAccountInstruction {
/// /// The PDA seed used to distinguish the new account from other PDAs
/// pub new_account_seed: [u8; 16],
@ -1220,6 +1224,7 @@ pub fn allocate_with_seed(
/// /// - 1: system_program - executable
/// /// - *: to - writable
/// #[derive(BorshSerialize, BorshDeserialize, Debug)]
/// # #[borsh(crate = "borsh")]
/// pub struct TransferLamportsToManyInstruction {
/// pub bank_pda_bump_seed: u8,
/// pub amount_list: Vec<u64>,

View File

@ -63,9 +63,9 @@ impl ComputeBudgetInstruction {
/// Serialize Instruction using borsh, this is only used in runtime::cost_model::tests but compilation
/// can't be restricted as it's used across packages
// #[cfg(test)]
pub fn pack(self) -> Result<Vec<u8>, std::io::Error> {
self.try_to_vec()
#[cfg(feature = "dev-context-only-utils")]
pub fn pack(self) -> Result<Vec<u8>, borsh::io::Error> {
borsh::to_vec(&self)
}
/// Create a `ComputeBudgetInstruction::SetLoadedAccountsDataSizeLimit` `Instruction`

View File

@ -46,15 +46,16 @@ pub use solana_program::address_lookup_table_account;
pub use solana_program::program_stubs;
pub use solana_program::{
account_info, address_lookup_table, alt_bn128, big_mod_exp, blake3, borsh, borsh0_10, borsh0_9,
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock, config, custom_heap_default,
custom_panic_default, debug_account_data, declare_deprecated_sysvar_id, declare_sysvar_id,
decode_error, ed25519_program, epoch_rewards, epoch_schedule, fee_calculator, impl_sysvar_get,
incinerator, instruction, keccak, lamports, loader_instruction, loader_upgradeable_instruction,
loader_v4, loader_v4_instruction, message, msg, native_token, nonce, poseidon, program,
program_error, program_memory, program_option, program_pack, rent, sanitize, sdk_ids,
secp256k1_program, secp256k1_recover, serde_varint, serialize_utils, short_vec, slot_hashes,
slot_history, stable_layout, stake, stake_history, syscalls, system_instruction,
system_program, sysvar, unchecked_div_by_const, vote, wasm_bindgen,
borsh1, bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable, clock, config,
custom_heap_default, custom_panic_default, debug_account_data, declare_deprecated_sysvar_id,
declare_sysvar_id, decode_error, ed25519_program, epoch_rewards, epoch_schedule,
fee_calculator, impl_sysvar_get, incinerator, instruction, keccak, lamports,
loader_instruction, loader_upgradeable_instruction, loader_v4, loader_v4_instruction, message,
msg, native_token, nonce, poseidon, program, program_error, program_memory, program_option,
program_pack, rent, sanitize, sdk_ids, secp256k1_program, secp256k1_recover, serde_varint,
serialize_utils, short_vec, slot_hashes, slot_history, stable_layout, stake, stake_history,
syscalls, system_instruction, system_program, sysvar, unchecked_div_by_const, vote,
wasm_bindgen,
};
pub mod account;

View File

@ -13,7 +13,9 @@ edition = { workspace = true }
Inflector = { workspace = true }
base64 = { workspace = true }
bincode = { workspace = true }
borsh = { workspace = true }
# Update this borsh dependency to the workspace version once
# spl-associated-token-account is upgraded and used in the monorepo.
borsh = { version = "0.10.3" }
bs58 = { workspace = true }
lazy_static = { workspace = true }
log = { workspace = true }