Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,234 changes: 629 additions & 605 deletions Cargo.lock

Large diffs are not rendered by default.

238 changes: 119 additions & 119 deletions Cargo.toml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions node/src/fake_runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ sp_api::impl_runtime_apis! {
unimplemented!()
}

fn execute_block(_: Block) {
fn execute_block(_: <Block as BlockT>::LazyBlock) {
unimplemented!()
}

Expand Down Expand Up @@ -78,7 +78,7 @@ sp_api::impl_runtime_apis! {
}

fn check_inherents(
_: Block,
_: <Block as BlockT>::LazyBlock,
_: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
unimplemented!()
Expand Down
42 changes: 20 additions & 22 deletions pallets/transaction-storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use polkadot_sdk_frame::{
prelude::*,
};
use sp_transaction_storage_proof::{
encode_index, random_chunk, InherentError, TransactionStorageProof, CHUNK_SIZE,
encode_index, random_chunk, ChunkIndex, InherentError, TransactionStorageProof, CHUNK_SIZE,
INHERENT_IDENTIFIER,
};

Expand Down Expand Up @@ -117,7 +117,16 @@ pub struct TransactionInfo {
///
/// Cumulative value of all previous transactions in the block; the last transaction holds the
/// total chunk value.
block_chunks: u32,
block_chunks: ChunkIndex,
}

impl TransactionInfo {
/// Get the number of total chunks.
///
/// See the `block_chunks` field of [`TransactionInfo`] for details.
pub fn total_chunks(txs: &[TransactionInfo]) -> ChunkIndex {
txs.last().map_or(0, |t| t.block_chunks)
}
}

/// Context of a `check_signed`/`check_unsigned` call.
Expand Down Expand Up @@ -228,7 +237,6 @@ pub mod pallet {
if obsolete > Zero::zero() {
weight.saturating_accrue(db_weight.writes(2));
<Transactions<T>>::remove(obsolete);
<ChunkCount<T>>::remove(obsolete);
}

// For `on_finalize`
Expand All @@ -244,7 +252,12 @@ pub mod pallet {
let number = <frame_system::Pallet<T>>::block_number();
let period = T::StoragePeriod::get();
let target_number = number.saturating_sub(period);
target_number.is_zero() || <ChunkCount<T>>::get(target_number) == 0

target_number.is_zero() || {
// An empty block means no transactions were stored, relying on the fact
// below that we store transactions only if they contain chunks.
!Transactions::<T>::contains_key(target_number)
}
},
"Storage proof must be checked once in the block"
);
Expand All @@ -253,7 +266,6 @@ pub mod pallet {
let transactions = <BlockTransactions<T>>::take();
let total_chunks = transactions.last().map_or(0, |t| t.block_chunks);
if total_chunks != 0 {
<ChunkCount<T>>::insert(n, total_chunks);
<Transactions<T>>::insert(n, transactions);
}
}
Expand Down Expand Up @@ -394,20 +406,12 @@ pub mod pallet {
let period = T::StoragePeriod::get();
let target_number = number.saturating_sub(period);
ensure!(!target_number.is_zero(), Error::<T>::UnexpectedProof);
let total_chunks = <ChunkCount<T>>::get(target_number);
ensure!(total_chunks != 0, Error::<T>::UnexpectedProof);
let total_chunks = ChunkCount::<T>::get(target_number);
let transactions =
Transactions::<T>::get(target_number).ok_or(Error::<T>::MissingStateData)?;

// Verify the proof with a "random" chunk (randomness is based on the parent hash).
let parent_hash = frame_system::Pallet::<T>::parent_hash();
Self::verify_chunk_proof(
proof,
parent_hash.as_ref(),
transactions.to_vec(),
total_chunks,
)?;
Self::verify_chunk_proof(proof, parent_hash.as_ref(), transactions.to_vec())?;
ProofChecked::<T>::put(true);
Self::deposit_event(Event::ProofChecked);
Ok(().into())
Expand Down Expand Up @@ -594,11 +598,6 @@ pub mod pallet {
OptionQuery,
>;

/// Count indexed chunks for each block.
#[pallet::storage]
pub(super) type ChunkCount<T: Config> =
StorageMap<_, Blake2_128Concat, BlockNumberFor<T>, u32, ValueQuery>;

// Intermediates
#[pallet::storage]
pub(super) type BlockTransactions<T: Config> =
Expand Down Expand Up @@ -998,12 +997,11 @@ pub mod pallet {
proof: TransactionStorageProof,
random_hash: &[u8],
infos: Vec<TransactionInfo>,
total_chunks: u32,
) -> Result<(), Error<T>> {
// Get the random chunk index - from all transactions in the block = [0..total_chunks).
let total_chunks: ChunkIndex = TransactionInfo::total_chunks(&infos);
ensure!(total_chunks != 0, Error::<T>::UnexpectedProof);
ensure!(!infos.is_empty(), Error::<T>::UnexpectedProof);

// Get the random chunk index (from all transactions in the block = 0..total_chunks).
let selected_block_chunk_index = random_chunk(random_hash, total_chunks);

// Let's find the corresponding transaction and its "local" chunk index for "global"
Expand Down
35 changes: 16 additions & 19 deletions pallets/transaction-storage/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use super::{
new_test_ext, run_to_block, RuntimeCall, RuntimeEvent, RuntimeOrigin, System, Test,
TransactionStorage,
},
AuthorizationExtent, AuthorizationScope, Event, AUTHORIZATION_NOT_EXPIRED, BAD_DATA_SIZE,
DEFAULT_MAX_TRANSACTION_SIZE,
AuthorizationExtent, AuthorizationScope, Event, TransactionInfo, AUTHORIZATION_NOT_EXPIRED,
BAD_DATA_SIZE, DEFAULT_MAX_TRANSACTION_SIZE,
};
use polkadot_sdk_frame::{
prelude::{frame_system::RawOrigin, *},
Expand All @@ -36,7 +36,6 @@ type Error = super::Error<Test>;

type Authorizations = super::Authorizations<Test>;
type BlockTransactions = super::BlockTransactions<Test>;
type ChunkCount = super::ChunkCount<Test>;
type Transactions = super::Transactions<Test>;

const MAX_DATA_SIZE: u32 = DEFAULT_MAX_TRANSACTION_SIZE;
Expand All @@ -51,10 +50,7 @@ fn discards_data() {
let block_num = System::block_number();
if block_num == 11 {
let parent_hash = System::parent_hash();
Some(
build_proof(parent_hash.as_ref(), vec![vec![0u8; 2000], vec![0u8; 2000]])
.unwrap(),
)
build_proof(parent_hash.as_ref(), vec![vec![0u8; 2000], vec![0u8; 2000]]).unwrap()
} else {
None
}
Expand All @@ -63,10 +59,8 @@ fn discards_data() {
assert!(Transactions::get(1).is_some());
let transactions = Transactions::get(1).unwrap();
assert_eq!(transactions.len(), 2);
assert_eq!(ChunkCount::get(1), 16);
run_to_block(12, proof_provider);
assert!(Transactions::get(1).is_none());
assert_eq!(ChunkCount::get(1), 0);
});
}

Expand Down Expand Up @@ -140,23 +134,26 @@ fn checks_proof() {
));
run_to_block(10, || None);
let parent_hash = System::parent_hash();
let proof =
build_proof(parent_hash.as_ref(), vec![vec![0u8; MAX_DATA_SIZE as usize]]).unwrap();
let proof = build_proof(parent_hash.as_ref(), vec![vec![0u8; MAX_DATA_SIZE as usize]])
.unwrap()
.unwrap();
assert_noop!(
TransactionStorage::check_proof(RuntimeOrigin::none(), proof),
Error::UnexpectedProof,
);
run_to_block(11, || None);
let parent_hash = System::parent_hash();

let invalid_proof = build_proof(parent_hash.as_ref(), vec![vec![0u8; 1000]]).unwrap();
let invalid_proof =
build_proof(parent_hash.as_ref(), vec![vec![0u8; 1000]]).unwrap().unwrap();
assert_noop!(
TransactionStorage::check_proof(RuntimeOrigin::none(), invalid_proof),
Error::InvalidProof,
);

let proof =
build_proof(parent_hash.as_ref(), vec![vec![0u8; MAX_DATA_SIZE as usize]]).unwrap();
let proof = build_proof(parent_hash.as_ref(), vec![vec![0u8; MAX_DATA_SIZE as usize]])
.unwrap()
.unwrap();
assert_ok!(TransactionStorage::check_proof(RuntimeOrigin::none(), proof));
});
}
Expand Down Expand Up @@ -188,8 +185,8 @@ fn verify_chunk_proof_works() {
run_to_block(2, || None);

// Read all the block transactions metadata.
let total_chunks = ChunkCount::get(1);
let tx_infos = Transactions::get(1).unwrap();
let total_chunks = TransactionInfo::total_chunks(&tx_infos);
assert_eq!(expected_total_chunks, total_chunks);
assert_eq!(9, tx_infos.len());

Expand All @@ -202,13 +199,13 @@ fn verify_chunk_proof_works() {
assert_eq!(selected_chunk_index, chunk_index);

// build/check chunk proof roundtrip
let proof =
build_proof(random_hash.as_ref(), transactions.clone()).expect("valid proof");
let proof = build_proof(random_hash.as_ref(), transactions.clone())
.expect("valid proof")
.unwrap();
assert_ok!(TransactionStorage::verify_chunk_proof(
proof,
random_hash.as_ref(),
tx_infos.to_vec(),
total_chunks
));
}
});
Expand All @@ -230,7 +227,7 @@ fn renews_data() {
let block_num = System::block_number();
if block_num == 11 || block_num == 16 {
let parent_hash = System::parent_hash();
Some(build_proof(parent_hash.as_ref(), vec![vec![0u8; 2000]]).unwrap())
build_proof(parent_hash.as_ref(), vec![vec![0u8; 2000]]).unwrap()
} else {
None
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ impl_runtime_apis! {
VERSION
}

fn execute_block(block: Block) {
fn execute_block(block: <Block as BlockT>::LazyBlock) {
Executive::execute_block(block);
}

Expand Down Expand Up @@ -703,7 +703,7 @@ impl_runtime_apis! {
}

fn check_inherents(
block: Block,
block: <Block as BlockT>::LazyBlock,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
Expand Down
4 changes: 2 additions & 2 deletions runtimes/bulletin-polkadot/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ impl_runtime_apis! {
VERSION
}

fn execute_block(block: Block) {
fn execute_block(block: <Block as BlockT>::LazyBlock) {
Executive::execute_block(block);
}

Expand Down Expand Up @@ -890,7 +890,7 @@ impl_runtime_apis! {
}

fn check_inherents(
block: Block,
block: <Block as BlockT>::LazyBlock,
data: sp_inherents::InherentData,
) -> sp_inherents::CheckInherentsResult {
data.check_extrinsics(&block)
Expand Down
Loading
Loading