Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Ensure to digest non-empty snapshot_storages and add asserts (#11021)
Browse files Browse the repository at this point in the history
* Add asserts to detect not-digestable example data

* Ensure to digest non-empty snapshot_storages
  • Loading branch information
ryoqun authored Jul 13, 2020
1 parent e95e7a9 commit de379a8
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 20 deletions.
19 changes: 18 additions & 1 deletion runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,21 @@ pub struct BankRc {
pub(crate) slot: Slot,
}

#[cfg(RUSTC_WITH_SPECIALIZATION)]
use solana_sdk::abi_example::AbiExample;
#[cfg(RUSTC_WITH_SPECIALIZATION)]
impl AbiExample for BankRc {
fn example() -> Self {
BankRc {
// Set parent to None to cut the recursion into another Bank
parent: RwLock::new(None),
// AbiExample for Accounts is specially implemented to contain a storage example
accounts: AbiExample::example(),
slot: AbiExample::example(),
}
}
}

impl BankRc {
pub(crate) fn new(accounts: Accounts, slot: Slot) -> Self {
Self {
Expand Down Expand Up @@ -265,7 +280,9 @@ pub(crate) struct BankFieldsToSerialize<'a> {
}

/// Manager for the state of all accounts and programs after processing its entries.
#[derive(Default)]
/// AbiExample is needed even without Serialize/Deserialize; actual (de-)serializeaion
/// are implemented elsewhere for versioning
#[derive(Default, AbiExample)]
pub struct Bank {
/// References to accounts, parent and signature status
pub rc: BankRc,
Expand Down
27 changes: 10 additions & 17 deletions runtime/src/serde_snapshot/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,28 +279,24 @@ fn test_bank_serialize_older() {
#[cfg(all(test, RUSTC_WITH_SPECIALIZATION))]
mod test_bank_serialize {
use super::*;
use solana_sdk::abi_example::AbiExample;

// These some what long test harness is required to freeze the ABI of
// Bank's serialization due to versioned nature
#[frozen_abi(digest = "9BGkhttaVsELn1zoHMKXLvi3Qty51nY1yz584Fao2Ev9")]
#[derive(Default, Serialize)]
#[frozen_abi(digest = "6MnT4MzuLHe4Uq96YaF3JF2gL1RvprzQHCaV9TaWgYLe")]
#[derive(Serialize, AbiExample)]
pub struct BankAbiTestWrapperFuture {
#[serde(serialize_with = "wrapper_future")]
bank: Bank,
}

impl AbiExample for BankAbiTestWrapperFuture {
fn example() -> Self {
Self::default()
}
}

pub fn wrapper_future<S>(bank: &Bank, s: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let snapshot_storages = bank.rc.accounts.accounts_db.get_snapshot_storages(0);
// ensure there is a single snapshot storage example for ABI digesting
assert_eq!(snapshot_storages.len(), 1);

(SerializableBankAndStorage::<future::Context> {
bank,
snapshot_storages: &snapshot_storages,
Expand All @@ -309,24 +305,21 @@ mod test_bank_serialize {
.serialize(s)
}

#[frozen_abi(digest = "HYmXta1fhiHe6hZLGJriMqKx9N2U8YRJY51AGZmxzM5m")]
#[derive(Default, Serialize)]
#[frozen_abi(digest = "92KVEUQ8PwKe5DgZ6AyDQGAi9pvi7kfHdMBE4hcs5EQ4")]
#[derive(Serialize, AbiExample)]
pub struct BankAbiTestWrapperLegacy {
#[serde(serialize_with = "wrapper_legacy")]
bank: Bank,
}

impl AbiExample for BankAbiTestWrapperLegacy {
fn example() -> Self {
Self::default()
}
}

pub fn wrapper_legacy<S>(bank: &Bank, s: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let snapshot_storages = bank.rc.accounts.accounts_db.get_snapshot_storages(0);
// ensure there is a single snapshot storage example for ABI digesting
assert_eq!(snapshot_storages.len(), 1);

(SerializableBankAndStorage::<legacy::Context> {
bank,
snapshot_storages: &snapshot_storages,
Expand Down
14 changes: 12 additions & 2 deletions sdk/src/abi_digester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,12 @@ impl Serializer for AbiDigester {
}

fn serialize_seq(mut self, len: Option<usize>) -> DigestResult {
self.update_with_string(format!("seq (elements = {})", len.unwrap()));
let len = len.unwrap();
assert_eq!(
len, 1,
"Exactly 1 seq element is needed to generate the ABI digest precisely"
);
self.update_with_string(format!("seq (elements = {})", len));
Ok(self.create_child())
}

Expand All @@ -367,7 +372,12 @@ impl Serializer for AbiDigester {
}

fn serialize_map(mut self, len: Option<usize>) -> DigestResult {
self.update_with_string(format!("map (entries = {})", len.unwrap()));
let len = len.unwrap();
assert_eq!(
len, 1,
"Exactly 1 map entry is needed to generate the ABI digest precisely"
);
self.update_with_string(format!("map (entries = {})", len));
Ok(self.create_child())
}

Expand Down

0 comments on commit de379a8

Please sign in to comment.