Skip to content

Commit feabb75

Browse files
committed
Merge remote-tracking branch 'raymondkfcheung/ray-align-storage-period' into ray-align-common-fn
2 parents 16a7ca5 + 74ec72d commit feabb75

File tree

11 files changed

+229
-58
lines changed

11 files changed

+229
-58
lines changed

.github/workflows/integration-test.yml

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ jobs:
2626
timeout-minutes: 60
2727

2828
steps:
29+
- name: Free Disk Space (Ubuntu)
30+
if: ${{ runner.environment == 'github-hosted' }}
31+
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
32+
with:
33+
tool-cache: false
34+
2935
- name: Checkout sources
3036
uses: actions/checkout@v4
3137

@@ -65,14 +71,32 @@ jobs:
6571
chmod +x zombienet-linux-x64
6672
echo "ZOMBIENET_BINARY=$GITHUB_WORKSPACE/zombienet-linux-x64" >> $GITHUB_ENV
6773
68-
- name: Run authorize and store (PAPI, smoldot)
74+
- name: Run authorize and store (PAPI, RPC node)
6975
working-directory: examples
70-
run: just run-authorize-and-store "smoldot"
76+
run: |
77+
export TEST_DIR="$(mktemp -d $GITHUB_WORKSPACE/bulletin-tests-run-XXXXX)/test"
78+
echo "TEST_DIR=$TEST_DIR" >> $GITHUB_ENV
79+
just run-authorize-and-store "ws"
7180
72-
- name: Run authorize and store (PAPI, RPC node)
81+
- name: Run authorize and store (PAPI, smoldot)
7382
working-directory: examples
74-
run: just run-authorize-and-store "ws"
83+
run: |
84+
export TEST_DIR="$(mktemp -d $GITHUB_WORKSPACE/bulletin-tests-run-XXXXX)/test"
85+
echo "TEST_DIR=$TEST_DIR" >> $GITHUB_ENV
86+
just run-authorize-and-store "smoldot"
7587
7688
- name: Run store chunked data + DAG-PB (PJS-API, RPC node)
7789
working-directory: examples
78-
run: just run-store-chunked-data
90+
run: |
91+
export TEST_DIR="$(mktemp -d $GITHUB_WORKSPACE/bulletin-tests-run-XXXXX)/test"
92+
echo "TEST_DIR=$TEST_DIR" >> $GITHUB_ENV
93+
just run-store-chunked-data
94+
95+
# Collects logs from the last failed zombienet run.
96+
- name: Upload Zombienet logs (on failure)
97+
if: failure()
98+
uses: actions/upload-artifact@v4
99+
with:
100+
name: failed-zombienet-logs
101+
path: |
102+
${{ env.TEST_DIR }}/*.log

examples/justfile

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,19 @@ bulletin-solo-zombienet-start:
5050
echo " Set ZOMBIENET_BINARY environment variable or ensure zombienet-* exists in parent directory"
5151
exit 1
5252
fi
53-
54-
echo " Using zombienet: $ZOMBIENET_BIN"
55-
56-
# Get absolute paths for bulletin binary and config
53+
54+
# Get absolute paths, base dir, bulletin binary and config
55+
if [ -n "$TEST_DIR" ]; then
56+
TEST_DIR="$TEST_DIR"
57+
else
58+
# TEST_DIR is not set, create a new temp directory
59+
TEST_DIR="$(mktemp -d /tmp/bulletin-tests-run-XXXXX)/test"
60+
fi
5761
BULLETIN_BINARY=$(cd .. && pwd)/target/release/polkadot-bulletin-chain
5862
ZOMBIENET_CONFIG=$(cd .. && pwd)/zombienet/bulletin-polkadot-local.toml
59-
60-
POLKADOT_BULLETIN_BINARY_PATH=$BULLETIN_BINARY $ZOMBIENET_BIN -p native spawn $ZOMBIENET_CONFIG > /tmp/zombienet.log 2>&1 &
63+
echo " Using zombienet: $ZOMBIENET_BIN, working directory: $TEST_DIR, zombienet config: $ZOMBIENET_CONFIG"
64+
65+
POLKADOT_BULLETIN_BINARY_PATH=$BULLETIN_BINARY $ZOMBIENET_BIN --dir $TEST_DIR -p native spawn $ZOMBIENET_CONFIG > /tmp/zombienet.log 2>&1 &
6166
ZOMBIENET_PID=$!
6267
echo $ZOMBIENET_PID > {{ PID_DIR }}/zombienet.pid
6368
echo " Zombienet PID: $ZOMBIENET_PID"
@@ -185,9 +190,7 @@ setup-services:
185190
sleep 10
186191
echo " Zombienet process check:"
187192
ps aux | grep zombienet | grep -v grep || echo " ⚠ No zombienet process found"
188-
echo " Checking zombienet log:"
189-
tail -20 /tmp/zombienet.log || echo " ⚠ Could not read zombienet log"
190-
193+
191194
just ipfs-connect
192195
just ipfs-reconnect-start
193196
just papi-generate

pallets/transaction-storage/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
Indexes transactions and manages storage proofs.
44

5-
Allows storing arbitrary data on the chain. Data is automatically removed after `StoragePeriod` blocks, unless the storage is renewed.
6-
Validators must submit proof of storing a random chunk of data for block `N - StoragePeriod` when producing block `N`.
5+
Allows storing arbitrary data on the chain. Data is automatically removed after `RetentionPeriod` blocks, unless the storage is renewed.
6+
Validators must submit proof of storing a random chunk of data for block `N - RetentionPeriod` when producing block `N`.
77

88
# Running a chain
99

@@ -16,7 +16,7 @@ cargo run --release -- build-spec --chain=local > sc_init.json
1616
```
1717

1818
Edit the json chain spec file to customise the chain. The storage chain genesis params are configured in the `transactionStorage` section.
19-
Note that `storagePeriod` is specified in blocks and changing it also requires code changes at the moment.
19+
Note that `retentionPeriod` is specified in blocks and changing it also requires code changes at the moment.
2020

2121
Build a raw spec from the init spec.
2222

@@ -32,7 +32,7 @@ cargo run --release -- --chain=sc.json -d /tmp/bob --storage-chain --keep-blocks
3232
```
3333

3434
`--storage-chain` enables transaction indexing.
35-
`--keep-blocks=100800` enables block pruning. The value here should be greater or equal than the storage period.
35+
`--keep-blocks=100800` enables block pruning. The value here should be greater or equal than the retention period.
3636
`--ipfs-server` enables serving stored content over IPFS.
3737

3838
Once the network is started, any other joining nodes need to sync with `--sync=fast`. Regular sync will fail because block pruning removes old blocks. The chain does not keep full block history.
@@ -75,7 +75,7 @@ ipfs swarm connect <substrate peer address>
7575
ipfs block get /ipfs/<CID> > kitten.jpeg
7676
```
7777

78-
To renew data and prevent it from being disposed after the storage period, use `transactionStorage.renew(block, index)`
78+
To renew data and prevent it from being disposed after the retention period, use `transactionStorage.renew(block, index)`
7979
where `block` is the block number of the previous store or renew transction, and index is the index of that transaction in the block.
8080

8181

pallets/transaction-storage/src/benchmarking.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ mod benchmarks {
157157
vec![0u8; T::MaxTransactionSize::get() as usize],
158158
)?;
159159
}
160-
run_to_block::<T>(StoragePeriod::<T>::get() + BlockNumberFor::<T>::one());
160+
run_to_block::<T>(crate::Pallet::<T>::retention_period() + BlockNumberFor::<T>::one());
161161
let encoded_proof = proof();
162162
let proof = TransactionStorageProof::decode(&mut &*encoded_proof).unwrap();
163163

pallets/transaction-storage/src/lib.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
// Ensure we're `no_std` when compiling for Wasm.
2525
#![cfg_attr(not(feature = "std"), no_std)]
2626

27+
extern crate alloc;
28+
2729
mod benchmarking;
2830
pub mod weights;
2931

32+
pub mod migrations;
3033
#[cfg(test)]
3134
mod mock;
3235
#[cfg(test)]
@@ -37,7 +40,10 @@ use core::fmt::Debug;
3740
use polkadot_sdk_frame::{
3841
deps::{sp_core::sp_std::prelude::*, *},
3942
prelude::*,
40-
traits::fungible::{Balanced, Credit, Inspect, Mutate, MutateHold},
43+
traits::{
44+
fungible::{Balanced, Credit, Inspect, Mutate, MutateHold},
45+
parameter_types,
46+
},
4147
};
4248
use sp_transaction_storage_proof::{
4349
encode_index, num_chunks, random_chunk, ChunkIndex, InherentError, TransactionStorageProof,
@@ -55,6 +61,12 @@ pub use weights::WeightInfo;
5561

5662
const LOG_TARGET: &str = "runtime::transaction-storage";
5763

64+
/// Default retention period for data (in blocks).
65+
pub const DEFAULT_RETENTION_PERIOD: u32 = 100800;
66+
parameter_types! {
67+
pub const DefaultRetentionPeriod: u32 = DEFAULT_RETENTION_PERIOD;
68+
}
69+
5870
// TODO: https://github.com/paritytech/polkadot-bulletin-chain/issues/139 - Clarify purpose of allocator limits and decide whether to remove or use these constants.
5971
/// Maximum bytes that can be stored in one transaction.
6072
// Setting higher limit also requires raising the allocator limit.
@@ -253,7 +265,7 @@ pub mod pallet {
253265
// Drop obsolete roots. The proof for `obsolete` will be checked later
254266
// in this block, so we drop `obsolete` - 1.
255267
weight.saturating_accrue(db_weight.reads(1));
256-
let period = StoragePeriod::<T>::get();
268+
let period = Self::retention_period();
257269
let obsolete = n.saturating_sub(period.saturating_add(One::one()));
258270
if obsolete > Zero::zero() {
259271
weight.saturating_accrue(db_weight.writes(2));
@@ -271,7 +283,7 @@ pub mod pallet {
271283
<ProofChecked<T>>::take() || {
272284
// Proof is not required for early or empty blocks.
273285
let number = <frame_system::Pallet<T>>::block_number();
274-
let period = StoragePeriod::<T>::get();
286+
let period = Self::retention_period();
275287
let target_number = number.saturating_sub(period);
276288

277289
target_number.is_zero() || {
@@ -300,11 +312,11 @@ pub mod pallet {
300312
!T::MaxTransactionSize::get().is_zero(),
301313
"MaxTransactionSize must be greater than zero"
302314
);
303-
let default_period = sp_transaction_storage_proof::DEFAULT_STORAGE_PERIOD.into();
304-
let storage_period = GenesisConfig::<T>::default().storage_period;
315+
let default_period = DEFAULT_RETENTION_PERIOD.into();
316+
let retention_period = GenesisConfig::<T>::default().retention_period;
305317
assert_eq!(
306-
storage_period, default_period,
307-
"GenesisConfig.storage_period must match DEFAULT_STORAGE_PERIOD"
318+
retention_period, default_period,
319+
"GenesisConfig.retention_period must match DEFAULT_RETENTION_PERIOD"
308320
);
309321
assert!(
310322
!T::AuthorizationPeriod::get().is_zero(),
@@ -316,8 +328,8 @@ pub mod pallet {
316328
#[pallet::call]
317329
impl<T: Config> Pallet<T> {
318330
/// Index and store data off chain. Minimum data size is 1 byte, maximum is
319-
/// `MaxTransactionSize`. Data will be removed after `StoragePeriod` blocks, unless `renew`
320-
/// is called.
331+
/// `MaxTransactionSize`. Data will be removed after `RetentionPeriod` blocks, unless
332+
/// `renew` is called.
321333
///
322334
/// Authorization is required to store data using regular signed/unsigned transactions.
323335
/// Regular signed transactions require account authorization (see
@@ -420,7 +432,7 @@ pub mod pallet {
420432
Ok(().into())
421433
}
422434

423-
/// Check storage proof for block number `block_number() - StoragePeriod`. If such a block
435+
/// Check storage proof for block number `block_number() - RetentionPeriod`. If such a block
424436
/// does not exist, the proof is expected to be `None`.
425437
///
426438
/// ## Complexity
@@ -438,7 +450,7 @@ pub mod pallet {
438450

439451
// Get the target block metadata.
440452
let number = <frame_system::Pallet<T>>::block_number();
441-
let period = StoragePeriod::<T>::get();
453+
let period = Self::retention_period();
442454
let target_number = number.saturating_sub(period);
443455
ensure!(!target_number.is_zero(), Error::<T>::UnexpectedProof);
444456
let transactions =
@@ -641,10 +653,13 @@ pub mod pallet {
641653
/// Storage fee per transaction.
642654
pub type EntryFee<T: Config> = StorageValue<_, BalanceOf<T>>;
643655

644-
/// Storage period for data in blocks. Should match `sp_storage_proof::DEFAULT_STORAGE_PERIOD`
645-
/// for block authoring.
656+
/// Number of blocks for which stored data must be retained.
657+
///
658+
/// Data older than `RetentionPeriod` blocks is eligible for removal unless it
659+
/// has been explicitly renewed. Validators are required to prove possession of
660+
/// data corresponding to block `N - RetentionPeriod` when producing block `N`.
646661
#[pallet::storage]
647-
pub type StoragePeriod<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
662+
pub type RetentionPeriod<T: Config> = StorageValue<_, BlockNumberFor<T>, ValueQuery>;
648663

649664
// Intermediates
650665
#[pallet::storage]
@@ -659,15 +674,15 @@ pub mod pallet {
659674
pub struct GenesisConfig<T: Config> {
660675
pub byte_fee: BalanceOf<T>,
661676
pub entry_fee: BalanceOf<T>,
662-
pub storage_period: BlockNumberFor<T>,
677+
pub retention_period: BlockNumberFor<T>,
663678
}
664679

665680
impl<T: Config> Default for GenesisConfig<T> {
666681
fn default() -> Self {
667682
Self {
668683
byte_fee: 10u32.into(),
669684
entry_fee: 1000u32.into(),
670-
storage_period: sp_transaction_storage_proof::DEFAULT_STORAGE_PERIOD.into(),
685+
retention_period: DEFAULT_RETENTION_PERIOD.into(),
671686
}
672687
}
673688
}
@@ -677,7 +692,7 @@ pub mod pallet {
677692
fn build(&self) {
678693
ByteFee::<T>::put(self.byte_fee);
679694
EntryFee::<T>::put(self.entry_fee);
680-
StoragePeriod::<T>::put(self.storage_period);
695+
RetentionPeriod::<T>::put(self.retention_period);
681696
}
682697
}
683698

@@ -868,6 +883,11 @@ pub mod pallet {
868883
Self::check_signed(who, call, CheckContext::PreDispatch).map(|_| ())
869884
}
870885

886+
/// Get RetentionPeriod storage information from the outside of this pallet.
887+
pub fn retention_period() -> BlockNumberFor<T> {
888+
RetentionPeriod::<T>::get()
889+
}
890+
871891
/// Returns `true` if a blob of the given size can be stored.
872892
fn data_size_ok(size: usize) -> bool {
873893
(size > 0) && (size <= T::MaxTransactionSize::get() as usize)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright (C) Parity Technologies (UK) Ltd.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
use crate::{Config, RetentionPeriod, LOG_TARGET};
17+
use core::marker::PhantomData;
18+
use polkadot_sdk_frame::{
19+
prelude::{BlockNumberFor, Weight},
20+
traits::{Get, OnRuntimeUpgrade, Zero},
21+
};
22+
23+
/// Runtime migration that sets the `RetentionPeriod` storage item to a
24+
/// non-zero `NewValue` value **only if it is currently zero**.
25+
///
26+
/// Idempotent migration: safe to run multiple times
27+
pub struct SetRetentionPeriodIfZero<T, NewValue>(PhantomData<(T, NewValue)>);
28+
impl<T: Config, NewValue: Get<BlockNumberFor<T>>> OnRuntimeUpgrade
29+
for SetRetentionPeriodIfZero<T, NewValue>
30+
{
31+
fn on_runtime_upgrade() -> Weight {
32+
let mut weight = T::DbWeight::get().reads(1);
33+
34+
// If zero, let's reset.
35+
if RetentionPeriod::<T>::get().is_zero() {
36+
RetentionPeriod::<T>::set(NewValue::get());
37+
weight.saturating_accrue(T::DbWeight::get().writes(1));
38+
39+
tracing::warn!(
40+
target: LOG_TARGET,
41+
new_value = ?NewValue::get(),
42+
"[SetRetentionPeriodIfZero] RetentionPeriod was zero, resetting to:",
43+
);
44+
}
45+
46+
weight
47+
}
48+
49+
#[cfg(feature = "try-runtime")]
50+
fn post_upgrade(
51+
_state: alloc::vec::Vec<u8>,
52+
) -> Result<(), polkadot_sdk_frame::deps::sp_runtime::DispatchError> {
53+
polkadot_sdk_frame::prelude::ensure!(
54+
!RetentionPeriod::<T>::get().is_zero(),
55+
"must be migrate to the `NewValue`."
56+
);
57+
58+
tracing::info!(target: LOG_TARGET, "SetRetentionPeriodIfZero is OK!");
59+
Ok(())
60+
}
61+
}

pallets/transaction-storage/src/mock.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ pub fn new_test_ext() -> TestExternalities {
7171
let t = RuntimeGenesisConfig {
7272
system: Default::default(),
7373
transaction_storage: pallet_transaction_storage::GenesisConfig::<Test> {
74-
storage_period: 10,
74+
retention_period: 10,
7575
byte_fee: 2,
7676
entry_fee: 200,
7777
},

0 commit comments

Comments
 (0)