Skip to content

Commit

Permalink
Buffer account's fields for hash (solana-labs#33788)
Browse files Browse the repository at this point in the history
* buffer accounts field for hash

* use smallvec to allocate hash buffer on stack

* sort deps

* more opt

* clippy

---------

Co-authored-by: HaoranYi <haoran.yi@solana.com>
  • Loading branch information
HaoranYi and HaoranYi authored Oct 23, 2023
1 parent a41b24f commit 669bc43
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 13 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ sha2 = "0.10.8"
sha3 = "0.10.4"
signal-hook = "0.3.17"
siphasher = "0.3.11"
smallvec = "1.11.1"
smpl_jwt = "0.7.1"
socket2 = "0.5.5"
soketto = "0.7"
Expand Down
1 change: 1 addition & 0 deletions accounts-db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ regex = { workspace = true }
seqlock = { workspace = true }
serde = { workspace = true, features = ["rc"] }
serde_derive = { workspace = true }
smallvec = { workspace = true }
solana-bucket-map = { workspace = true }
solana-config-program = { workspace = true }
solana-frozen-abi = { workspace = true }
Expand Down
37 changes: 28 additions & 9 deletions accounts-db/src/accounts_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ use {
rand::{thread_rng, Rng},
rayon::{prelude::*, ThreadPool},
serde::{Deserialize, Serialize},
smallvec::SmallVec,
solana_measure::{measure::Measure, measure_us},
solana_nohash_hasher::IntSet,
solana_rayon_threadlimit::get_thread_count,
Expand Down Expand Up @@ -6274,31 +6275,49 @@ impl AccountsDb {
}
let mut hasher = blake3::Hasher::new();

hasher.update(&lamports.to_le_bytes());
// allocate 128 bytes buffer on the stack
const BUF_SIZE: usize = 128;
const TOTAL_FIELD_SIZE: usize = 8 /* lamports */ + 8 /* slot */ + 8 /* rent_epoch */ + 1 /* exec_flag */ + 32 /* owner_key */ + 32 /* pubkey */;
const DATA_SIZE_CAN_FIT: usize = BUF_SIZE - TOTAL_FIELD_SIZE;

let mut buffer = SmallVec::<[u8; BUF_SIZE]>::new();

// collect lamports, slot, rent_epoch into buffer to hash
buffer.extend_from_slice(&lamports.to_le_bytes());

match include_slot {
IncludeSlotInHash::IncludeSlot => {
// upon feature activation, stop including slot# in the account hash
hasher.update(&slot.to_le_bytes());
buffer.extend_from_slice(&slot.to_le_bytes());
}
IncludeSlotInHash::RemoveSlot => {}
IncludeSlotInHash::IrrelevantAssertOnUse => {
panic!("IncludeSlotInHash is irrelevant, but we are calculating hash");
}
}
buffer.extend_from_slice(&rent_epoch.to_le_bytes());

hasher.update(&rent_epoch.to_le_bytes());
if data.len() > DATA_SIZE_CAN_FIT {
// For larger accounts whose data can't fit into the buffer, update the hash now.
hasher.update(&buffer);
buffer.clear();

hasher.update(data);
// hash account's data
hasher.update(data);
} else {
// For small accounts whose data can fit into the buffer, append it to the buffer.
buffer.extend_from_slice(data);
}

// collect exec_flag, owner, pubkey into buffer to hash
if executable {
hasher.update(&[1u8; 1]);
buffer.push(1_u8);
} else {
hasher.update(&[0u8; 1]);
buffer.push(0_u8);
}

hasher.update(owner.as_ref());
hasher.update(pubkey.as_ref());
buffer.extend_from_slice(owner.as_ref());
buffer.extend_from_slice(pubkey.as_ref());
hasher.update(&buffer);

AccountHash(Hash::new_from_array(hasher.finalize().into()))
}
Expand Down
5 changes: 3 additions & 2 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 669bc43

Please sign in to comment.