Skip to content

Commit 2cd564b

Browse files
Add runtime API for authorizations (#491)
* feat: add runtime api for authorizations * feat: add more functions to the api * fix: clippy * chore: remove can_enable_auto_renew * feat: use TransactionRef in the runtime API --------- Co-authored-by: Branislav Kontur <bkontur@gmail.com>
1 parent 22b944b commit 2cd564b

15 files changed

Lines changed: 484 additions & 27 deletions

File tree

.github/workflows/publish-crates.yml

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# This workflow publishes bulletin-pallets-common, pallet-bulletin-transaction-storage,
2-
# bulletin-transaction-storage-primitives crates to crates.io.
1+
# This workflow publishes bulletin-pallets-common, bulletin-transaction-storage-primitives,
2+
# pallet-bulletin-transaction-storage-runtime-api, pallet-bulletin-transaction-storage, and
3+
# pallet-bulletin-hop-promotion crates to crates.io.
34
# The workflow uses a manual trigger.
45
# On triggering the workflow, the release branch name and the versions of the crates should
56
# be provided as input parameters.
@@ -28,6 +29,10 @@ on:
2829
description: "Version for bulletin-transaction-storage-primitives"
2930
type: string
3031
required: true
32+
runtime_api_version:
33+
description: "Version for pallet-bulletin-transaction-storage-runtime-api"
34+
type: string
35+
required: true
3136
pallet_version:
3237
description: "Version for pallet-bulletin-transaction-storage"
3338
type: string
@@ -62,10 +67,11 @@ jobs:
6267
RELEASE_BRANCH: ${{ inputs.release_branch }}
6368
COMMON_VERSION: ${{ inputs.common_version }}
6469
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
70+
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
6571
PALLET_VERSION: ${{ inputs.pallet_version }}
6672
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
6773
run: |
68-
for v in "$COMMON_VERSION" "$PRIMITIVES_VERSION" "$PALLET_VERSION" "$HOP_PROMOTION_VERSION"; do
74+
for v in "$COMMON_VERSION" "$PRIMITIVES_VERSION" "$RUNTIME_API_VERSION" "$PALLET_VERSION" "$HOP_PROMOTION_VERSION"; do
6975
echo "$v" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.-]+)?$' || {
7076
echo "Invalid semver: $v" >&2; exit 1;
7177
}
@@ -102,46 +108,51 @@ jobs:
102108
env:
103109
COMMON_VERSION: ${{ inputs.common_version }}
104110
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
111+
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
105112
PALLET_VERSION: ${{ inputs.pallet_version }}
106113
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
107114
run: |
108115
# Update versions in individual crate Cargo.toml files
109116
sed -i "s/^version = \".*\"/version = \"$COMMON_VERSION\"/" pallets/common/Cargo.toml
110117
sed -i "s/^version = \".*\"/version = \"$PRIMITIVES_VERSION\"/" pallets/transaction-storage/primitives/Cargo.toml
118+
sed -i "s/^version = \".*\"/version = \"$RUNTIME_API_VERSION\"/" pallets/transaction-storage/runtime-api/Cargo.toml
111119
sed -i "s/^version = \".*\"/version = \"$PALLET_VERSION\"/" pallets/transaction-storage/Cargo.toml
112120
sed -i "s/^version = \".*\"/version = \"$HOP_PROMOTION_VERSION\"/" pallets/hop-promotion/Cargo.toml
113121
114122
# Add or update versions in workspace path dependencies
115123
sed -i "s|bulletin-pallets-common = { \(version = \"[^\"]*\", \)\?path = \"pallets/common\"|bulletin-pallets-common = { version = \"$COMMON_VERSION\", path = \"pallets/common\"|" Cargo.toml
116124
sed -i "s|bulletin-transaction-storage-primitives = { \(version = \"[^\"]*\", \)\?path = \"pallets/transaction-storage/primitives\"|bulletin-transaction-storage-primitives = { version = \"$PRIMITIVES_VERSION\", path = \"pallets/transaction-storage/primitives\"|" Cargo.toml
125+
sed -i "s|pallet-bulletin-transaction-storage-runtime-api = { \(version = \"[^\"]*\", \)\?path = \"pallets/transaction-storage/runtime-api\"|pallet-bulletin-transaction-storage-runtime-api = { version = \"$RUNTIME_API_VERSION\", path = \"pallets/transaction-storage/runtime-api\"|" Cargo.toml
117126
sed -i "s|pallet-bulletin-transaction-storage = { \(version = \"[^\"]*\", \)\?path = \"pallets/transaction-storage\"|pallet-bulletin-transaction-storage = { version = \"$PALLET_VERSION\", path = \"pallets/transaction-storage\"|" Cargo.toml
118127
sed -i "s|pallet-bulletin-hop-promotion = { \(version = \"[^\"]*\", \)\?path = \"pallets/hop-promotion\"|pallet-bulletin-hop-promotion = { version = \"$HOP_PROMOTION_VERSION\", path = \"pallets/hop-promotion\"|" Cargo.toml
119128
120129
echo "--- Updated crate versions ---"
121130
grep '^version' pallets/common/Cargo.toml
122131
grep '^version' pallets/transaction-storage/primitives/Cargo.toml
132+
grep '^version' pallets/transaction-storage/runtime-api/Cargo.toml
123133
grep '^version' pallets/transaction-storage/Cargo.toml
124134
grep '^version' pallets/hop-promotion/Cargo.toml
125135
echo "--- Updated workspace dependencies ---"
126136
grep -E 'bulletin-pallets-common|bulletin-transaction-storage-primitives|pallet-bulletin-transaction-storage|pallet-bulletin-hop-promotion' Cargo.toml
127137
128138
# Regenerate Cargo.lock so the pinned path-dep versions match the bumped Cargo.toml files.
129-
cargo check -p bulletin-pallets-common -p bulletin-transaction-storage-primitives -p pallet-bulletin-transaction-storage -p pallet-bulletin-hop-promotion
139+
cargo check -p bulletin-pallets-common -p bulletin-transaction-storage-primitives -p pallet-bulletin-transaction-storage-runtime-api -p pallet-bulletin-transaction-storage -p pallet-bulletin-hop-promotion
130140
131141
- name: Commit and push release branch
132142
if: ${{ !inputs.dry_run }}
133143
env:
134144
RELEASE_BRANCH: ${{ inputs.release_branch }}
135145
COMMON_VERSION: ${{ inputs.common_version }}
136146
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
147+
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
137148
PALLET_VERSION: ${{ inputs.pallet_version }}
138149
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
139150
run: |
140-
git add Cargo.toml Cargo.lock pallets/common/Cargo.toml pallets/transaction-storage/Cargo.toml pallets/transaction-storage/primitives/Cargo.toml pallets/hop-promotion/Cargo.toml
151+
git add Cargo.toml Cargo.lock pallets/common/Cargo.toml pallets/transaction-storage/Cargo.toml pallets/transaction-storage/primitives/Cargo.toml pallets/transaction-storage/runtime-api/Cargo.toml pallets/hop-promotion/Cargo.toml
141152
if git diff --cached --quiet; then
142153
echo "No version changes to commit — branch already at requested versions"
143154
else
144-
git commit -m "Prepare crates release: common=$COMMON_VERSION, primitives=$PRIMITIVES_VERSION, pallet=$PALLET_VERSION, hop-promotion=$HOP_PROMOTION_VERSION"
155+
git commit -m "Prepare crates release: common=$COMMON_VERSION, primitives=$PRIMITIVES_VERSION, runtime-api=$RUNTIME_API_VERSION, pallet=$PALLET_VERSION, hop-promotion=$HOP_PROMOTION_VERSION"
145156
git push origin "$RELEASE_BRANCH"
146157
fi
147158
@@ -173,14 +184,36 @@ jobs:
173184
cargo publish --locked -p "$NAME"
174185
fi
175186
176-
# pallet-bulletin-transaction-storage depends on both bulletin-pallets-common and
177-
# bulletin-transaction-storage-primitives, so both must be indexed on crates.io before
178-
# it can resolve them. Common was published first (~10s+ ago by now) and primitives
179-
# immediately before this sleep — 30s covers both.
187+
# pallet-bulletin-transaction-storage-runtime-api depends on
188+
# bulletin-transaction-storage-primitives, which was published immediately
189+
# before this sleep — 30s covers its crates.io indexing.
180190
- name: Wait for crates.io to index common and primitives
181191
if: ${{ !inputs.dry_run }}
182192
run: sleep 30
183193

194+
- name: Publish pallet-bulletin-transaction-storage-runtime-api
195+
if: ${{ !inputs.dry_run }}
196+
env:
197+
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
198+
NAME: pallet-bulletin-transaction-storage-runtime-api
199+
VERSION: ${{ inputs.runtime_api_version }}
200+
run: |
201+
status=$(curl -so /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/${NAME}/${VERSION}")
202+
if [ "$status" = "200" ]; then
203+
echo "$NAME $VERSION already on crates.io — skipping"
204+
else
205+
cargo publish --locked -p "$NAME"
206+
fi
207+
208+
# pallet-bulletin-transaction-storage depends on bulletin-pallets-common,
209+
# bulletin-transaction-storage-primitives, and
210+
# pallet-bulletin-transaction-storage-runtime-api. The first two were indexed
211+
# by the prior sleep; the runtime-api was just published and needs its own
212+
# indexing window before the pallet can resolve it.
213+
- name: Wait for crates.io to index runtime-api
214+
if: ${{ !inputs.dry_run }}
215+
run: sleep 30
216+
184217
- name: Publish pallet-bulletin-transaction-storage
185218
if: ${{ !inputs.dry_run }}
186219
env:
@@ -221,13 +254,15 @@ jobs:
221254
env:
222255
COMMON_VERSION: ${{ inputs.common_version }}
223256
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
257+
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
224258
PALLET_VERSION: ${{ inputs.pallet_version }}
225259
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
226260
run: |
227261
set -e
228262
for tag in \
229263
"bulletin-pallets-common-v$COMMON_VERSION" \
230264
"bulletin-transaction-storage-primitives-v$PRIMITIVES_VERSION" \
265+
"pallet-bulletin-transaction-storage-runtime-api-v$RUNTIME_API_VERSION" \
231266
"pallet-bulletin-transaction-storage-v$PALLET_VERSION" \
232267
"pallet-bulletin-hop-promotion-v$HOP_PROMOTION_VERSION"; do
233268
if git ls-remote --exit-code --tags origin "$tag" > /dev/null 2>&1; then
@@ -247,6 +282,7 @@ jobs:
247282
# because the verification build resolves bulletin-* deps from crates.io at the
248283
# new (not-yet-published) version. The real publish path handles this via
249284
# sequential publish + index wait.
285+
cargo package --locked --no-verify -p pallet-bulletin-transaction-storage-runtime-api --allow-dirty
250286
cargo package --locked --no-verify -p pallet-bulletin-transaction-storage --allow-dirty
251287
cargo package --locked --no-verify -p pallet-bulletin-hop-promotion --allow-dirty
252288
echo "Dry run complete - all crates packaged successfully"

Cargo.lock

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ bulletin-transaction-storage-primitives = { version = "0.1.0", path = "pallets/t
4141
bulletin-westend-runtime = { path = "runtimes/bulletin-westend" }
4242
pallet-bulletin-hop-promotion = { version = "0.1.0", path = "pallets/hop-promotion", default-features = false }
4343
pallet-bulletin-transaction-storage = { version = "0.1.0", path = "pallets/transaction-storage", default-features = false }
44+
pallet-bulletin-transaction-storage-runtime-api = { version = "0.1.0", path = "pallets/transaction-storage/runtime-api", default-features = false }
4445

4546
# Polkadot SDK crates (shared git revision)
4647
frame-benchmarking = { version = "47.0.0", default-features = false }
@@ -125,6 +126,7 @@ members = [
125126
"pallets/hop-promotion",
126127
"pallets/transaction-storage",
127128
"pallets/transaction-storage/primitives",
129+
"pallets/transaction-storage/runtime-api",
128130
"runtimes/bulletin-paseo",
129131
"runtimes/bulletin-westend",
130132
"runtimes/bulletin-westend/integration-tests",

pallets/transaction-storage/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ codec = { workspace = true }
1818
scale-info = { features = ["derive"], workspace = true }
1919
tracing = { workspace = true }
2020
bulletin-transaction-storage-primitives = { workspace = true }
21+
pallet-bulletin-transaction-storage-runtime-api = { workspace = true }
2122

2223
polkadot-sdk-frame = { workspace = true, default-features = false, features = [
2324
"runtime",
@@ -38,6 +39,7 @@ std = [
3839
"bulletin-pallets-common/std",
3940
"bulletin-transaction-storage-primitives/std",
4041
"codec/std",
42+
"pallet-bulletin-transaction-storage-runtime-api/std",
4143
"polkadot-sdk-frame/std",
4244
"scale-info/std",
4345
"sp-transaction-storage-proof/std",

pallets/transaction-storage/primitives/src/lib.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,27 @@
1919

2020
extern crate alloc;
2121

22+
use codec::{Decode, Encode, MaxEncodedLen};
23+
use scale_info::TypeInfo;
24+
2225
pub mod cids;
2326

2427
/// 32-byte hash of a stored blob of data.
2528
pub type ContentHash = [u8; 32];
29+
30+
/// Identifies a previously-stored entry in the pallet's `Transactions` map.
31+
#[derive(
32+
Clone,
33+
PartialEq,
34+
Eq,
35+
Debug,
36+
Encode,
37+
Decode,
38+
codec::DecodeWithMemTracking,
39+
TypeInfo,
40+
MaxEncodedLen,
41+
)]
42+
pub enum TransactionRef<BlockNumber> {
43+
Position { block: BlockNumber, index: u32 },
44+
ContentHash(ContentHash),
45+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "pallet-bulletin-transaction-storage-runtime-api"
3+
version = "0.1.0"
4+
authors.workspace = true
5+
edition.workspace = true
6+
license = "Apache-2.0"
7+
homepage.workspace = true
8+
repository.workspace = true
9+
description = "Runtime API for the Bulletin Chain transaction-storage pallet"
10+
11+
[package.metadata.docs.rs]
12+
targets = ["x86_64-unknown-linux-gnu"]
13+
14+
[dependencies]
15+
bulletin-transaction-storage-primitives = { workspace = true }
16+
codec = { workspace = true }
17+
scale-info = { features = ["derive"], workspace = true }
18+
sp-api = { workspace = true }
19+
20+
[features]
21+
default = ["std"]
22+
std = [
23+
"bulletin-transaction-storage-primitives/std",
24+
"codec/std",
25+
"scale-info/std",
26+
"sp-api/std",
27+
]
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Runtime API for the Bulletin Chain transaction-storage pallet.
2+
//!
3+
//! Exposes one summary call and two boolean predicates that mirror the
4+
//! validation logic of `store` and `renew`. Clients can use these to preview
5+
//! whether a call will be accepted before signing it.
6+
7+
#![cfg_attr(not(feature = "std"), no_std)]
8+
9+
use bulletin_transaction_storage_primitives::TransactionRef;
10+
use codec::{Codec, Decode, Encode};
11+
use scale_info::TypeInfo;
12+
13+
/// Active-authorization summary for an account. Returned by
14+
/// [`BulletinTransactionStorageApi::account_authorization`] when the account
15+
/// has an unexpired authorization entry.
16+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Encode, Decode, TypeInfo)]
17+
pub struct AccountAuthorization<BlockNumber> {
18+
/// Block at which this account's authorization expires.
19+
pub expires_at: BlockNumber,
20+
/// Total byte cap granted by the authorizer.
21+
pub bytes_allowance: u64,
22+
/// Bytes already consumed by `store` calls.
23+
pub bytes_used: u64,
24+
/// Bytes already consumed by `renew` calls (counts against the same
25+
/// `bytes_allowance` cap).
26+
pub bytes_permanent_used: u64,
27+
}
28+
29+
sp_api::decl_runtime_apis! {
30+
/// Runtime API for the Bulletin Chain transaction-storage pallet.
31+
pub trait BulletinTransactionStorageApi<AccountId, BlockNumber>
32+
where
33+
AccountId: Codec,
34+
BlockNumber: Codec,
35+
{
36+
/// Authorization summary for `account`, or `None` if the account has
37+
/// no unexpired authorization.
38+
fn account_authorization(account: AccountId) -> Option<AccountAuthorization<BlockNumber>>;
39+
40+
/// Returns `true` iff a `store(data)` call where `data.len() == data_len`
41+
/// would currently pass transaction validation for `account`.
42+
fn can_store(account: AccountId, data_len: u32) -> bool;
43+
44+
/// Returns `true` iff a `renew(entry)` call would currently pass transaction
45+
/// validation for `account`.
46+
fn can_renew(account: AccountId, entry: TransactionRef<BlockNumber>) -> bool;
47+
}
48+
}

0 commit comments

Comments
 (0)