Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
56 changes: 46 additions & 10 deletions .github/workflows/publish-crates.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# This workflow publishes bulletin-pallets-common, pallet-bulletin-transaction-storage,
# bulletin-transaction-storage-primitives crates to crates.io.
# This workflow publishes bulletin-pallets-common, bulletin-transaction-storage-primitives,
# pallet-bulletin-transaction-storage-runtime-api, pallet-bulletin-transaction-storage, and
# pallet-bulletin-hop-promotion crates to crates.io.
# The workflow uses a manual trigger.
# On triggering the workflow, the release branch name and the versions of the crates should
# be provided as input parameters.
Expand Down Expand Up @@ -28,6 +29,10 @@ on:
description: "Version for bulletin-transaction-storage-primitives"
type: string
required: true
runtime_api_version:
description: "Version for pallet-bulletin-transaction-storage-runtime-api"
type: string
required: true
pallet_version:
description: "Version for pallet-bulletin-transaction-storage"
type: string
Expand Down Expand Up @@ -62,10 +67,11 @@ jobs:
RELEASE_BRANCH: ${{ inputs.release_branch }}
COMMON_VERSION: ${{ inputs.common_version }}
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
PALLET_VERSION: ${{ inputs.pallet_version }}
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
run: |
for v in "$COMMON_VERSION" "$PRIMITIVES_VERSION" "$PALLET_VERSION" "$HOP_PROMOTION_VERSION"; do
for v in "$COMMON_VERSION" "$PRIMITIVES_VERSION" "$RUNTIME_API_VERSION" "$PALLET_VERSION" "$HOP_PROMOTION_VERSION"; do
echo "$v" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-[A-Za-z0-9.-]+)?$' || {
echo "Invalid semver: $v" >&2; exit 1;
}
Expand Down Expand Up @@ -102,46 +108,51 @@ jobs:
env:
COMMON_VERSION: ${{ inputs.common_version }}
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
PALLET_VERSION: ${{ inputs.pallet_version }}
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
run: |
# Update versions in individual crate Cargo.toml files
sed -i "s/^version = \".*\"/version = \"$COMMON_VERSION\"/" pallets/common/Cargo.toml
sed -i "s/^version = \".*\"/version = \"$PRIMITIVES_VERSION\"/" pallets/transaction-storage/primitives/Cargo.toml
sed -i "s/^version = \".*\"/version = \"$RUNTIME_API_VERSION\"/" pallets/transaction-storage/runtime-api/Cargo.toml
sed -i "s/^version = \".*\"/version = \"$PALLET_VERSION\"/" pallets/transaction-storage/Cargo.toml
sed -i "s/^version = \".*\"/version = \"$HOP_PROMOTION_VERSION\"/" pallets/hop-promotion/Cargo.toml

# Add or update versions in workspace path dependencies
sed -i "s|bulletin-pallets-common = { \(version = \"[^\"]*\", \)\?path = \"pallets/common\"|bulletin-pallets-common = { version = \"$COMMON_VERSION\", path = \"pallets/common\"|" Cargo.toml
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
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
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
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

echo "--- Updated crate versions ---"
grep '^version' pallets/common/Cargo.toml
grep '^version' pallets/transaction-storage/primitives/Cargo.toml
grep '^version' pallets/transaction-storage/runtime-api/Cargo.toml
grep '^version' pallets/transaction-storage/Cargo.toml
grep '^version' pallets/hop-promotion/Cargo.toml
echo "--- Updated workspace dependencies ---"
grep -E 'bulletin-pallets-common|bulletin-transaction-storage-primitives|pallet-bulletin-transaction-storage|pallet-bulletin-hop-promotion' Cargo.toml

# Regenerate Cargo.lock so the pinned path-dep versions match the bumped Cargo.toml files.
cargo check -p bulletin-pallets-common -p bulletin-transaction-storage-primitives -p pallet-bulletin-transaction-storage -p pallet-bulletin-hop-promotion
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

- name: Commit and push release branch
if: ${{ !inputs.dry_run }}
env:
RELEASE_BRANCH: ${{ inputs.release_branch }}
COMMON_VERSION: ${{ inputs.common_version }}
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
PALLET_VERSION: ${{ inputs.pallet_version }}
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
run: |
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
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
if git diff --cached --quiet; then
echo "No version changes to commit — branch already at requested versions"
else
git commit -m "Prepare crates release: common=$COMMON_VERSION, primitives=$PRIMITIVES_VERSION, pallet=$PALLET_VERSION, hop-promotion=$HOP_PROMOTION_VERSION"
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"
git push origin "$RELEASE_BRANCH"
fi

Expand Down Expand Up @@ -173,14 +184,36 @@ jobs:
cargo publish --locked -p "$NAME"
fi

# pallet-bulletin-transaction-storage depends on both bulletin-pallets-common and
# bulletin-transaction-storage-primitives, so both must be indexed on crates.io before
# it can resolve them. Common was published first (~10s+ ago by now) and primitives
# immediately before this sleep — 30s covers both.
# pallet-bulletin-transaction-storage-runtime-api depends on
# bulletin-transaction-storage-primitives, which was published immediately
# before this sleep — 30s covers its crates.io indexing.
- name: Wait for crates.io to index common and primitives
if: ${{ !inputs.dry_run }}
run: sleep 30

- name: Publish pallet-bulletin-transaction-storage-runtime-api
if: ${{ !inputs.dry_run }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
NAME: pallet-bulletin-transaction-storage-runtime-api
VERSION: ${{ inputs.runtime_api_version }}
run: |
status=$(curl -so /dev/null -w "%{http_code}" "https://crates.io/api/v1/crates/${NAME}/${VERSION}")
if [ "$status" = "200" ]; then
echo "$NAME $VERSION already on crates.io — skipping"
else
cargo publish --locked -p "$NAME"
fi

# pallet-bulletin-transaction-storage depends on bulletin-pallets-common,
# bulletin-transaction-storage-primitives, and
# pallet-bulletin-transaction-storage-runtime-api. The first two were indexed
# by the prior sleep; the runtime-api was just published and needs its own
# indexing window before the pallet can resolve it.
- name: Wait for crates.io to index runtime-api
if: ${{ !inputs.dry_run }}
run: sleep 30

- name: Publish pallet-bulletin-transaction-storage
if: ${{ !inputs.dry_run }}
env:
Expand Down Expand Up @@ -221,13 +254,15 @@ jobs:
env:
COMMON_VERSION: ${{ inputs.common_version }}
PRIMITIVES_VERSION: ${{ inputs.primitives_version }}
RUNTIME_API_VERSION: ${{ inputs.runtime_api_version }}
PALLET_VERSION: ${{ inputs.pallet_version }}
HOP_PROMOTION_VERSION: ${{ inputs.hop_promotion_version }}
run: |
set -e
for tag in \
"bulletin-pallets-common-v$COMMON_VERSION" \
"bulletin-transaction-storage-primitives-v$PRIMITIVES_VERSION" \
"pallet-bulletin-transaction-storage-runtime-api-v$RUNTIME_API_VERSION" \
"pallet-bulletin-transaction-storage-v$PALLET_VERSION" \
"pallet-bulletin-hop-promotion-v$HOP_PROMOTION_VERSION"; do
if git ls-remote --exit-code --tags origin "$tag" > /dev/null 2>&1; then
Expand All @@ -247,6 +282,7 @@ jobs:
# because the verification build resolves bulletin-* deps from crates.io at the
# new (not-yet-published) version. The real publish path handles this via
# sequential publish + index wait.
cargo package --locked --no-verify -p pallet-bulletin-transaction-storage-runtime-api --allow-dirty
cargo package --locked --no-verify -p pallet-bulletin-transaction-storage --allow-dirty
cargo package --locked --no-verify -p pallet-bulletin-hop-promotion --allow-dirty
echo "Dry run complete - all crates packaged successfully"
13 changes: 13 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ bulletin-transaction-storage-primitives = { version = "0.1.0", path = "pallets/t
bulletin-westend-runtime = { path = "runtimes/bulletin-westend" }
pallet-bulletin-hop-promotion = { version = "0.1.0", path = "pallets/hop-promotion", default-features = false }
pallet-bulletin-transaction-storage = { version = "0.1.0", path = "pallets/transaction-storage", default-features = false }
pallet-bulletin-transaction-storage-runtime-api = { version = "0.1.0", path = "pallets/transaction-storage/runtime-api", default-features = false }

# Polkadot SDK crates (shared git revision)
frame-benchmarking = { version = "47.0.0", default-features = false }
Expand Down Expand Up @@ -125,6 +126,7 @@ members = [
"pallets/hop-promotion",
"pallets/transaction-storage",
"pallets/transaction-storage/primitives",
"pallets/transaction-storage/runtime-api",
"runtimes/bulletin-paseo",
"runtimes/bulletin-westend",
"runtimes/bulletin-westend/integration-tests",
Expand Down
2 changes: 2 additions & 0 deletions pallets/transaction-storage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ codec = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
tracing = { workspace = true }
bulletin-transaction-storage-primitives = { workspace = true }
pallet-bulletin-transaction-storage-runtime-api = { workspace = true }

polkadot-sdk-frame = { workspace = true, default-features = false, features = [
"runtime",
Expand All @@ -38,6 +39,7 @@ std = [
"bulletin-pallets-common/std",
"bulletin-transaction-storage-primitives/std",
"codec/std",
"pallet-bulletin-transaction-storage-runtime-api/std",
"polkadot-sdk-frame/std",
"scale-info/std",
"sp-transaction-storage-proof/std",
Expand Down
20 changes: 20 additions & 0 deletions pallets/transaction-storage/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,27 @@

extern crate alloc;

use codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;

pub mod cids;

/// 32-byte hash of a stored blob of data.
pub type ContentHash = [u8; 32];

/// Identifies a previously-stored entry in the pallet's `Transactions` map.
#[derive(
Clone,
PartialEq,
Eq,
Debug,
Encode,
Decode,
codec::DecodeWithMemTracking,
TypeInfo,
MaxEncodedLen,
)]
pub enum TransactionRef<BlockNumber> {
Position { block: BlockNumber, index: u32 },
ContentHash(ContentHash),
}
27 changes: 27 additions & 0 deletions pallets/transaction-storage/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[package]
name = "pallet-bulletin-transaction-storage-runtime-api"
Comment thread
franciscoaguirre marked this conversation as resolved.
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "Runtime API for the Bulletin Chain transaction-storage pallet"

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]

[dependencies]
bulletin-transaction-storage-primitives = { workspace = true }
codec = { workspace = true }
scale-info = { features = ["derive"], workspace = true }
sp-api = { workspace = true }

[features]
default = ["std"]
std = [
"bulletin-transaction-storage-primitives/std",
"codec/std",
"scale-info/std",
"sp-api/std",
]
48 changes: 48 additions & 0 deletions pallets/transaction-storage/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
//! Runtime API for the Bulletin Chain transaction-storage pallet.
//!
//! Exposes one summary call and two boolean predicates that mirror the
//! validation logic of `store` and `renew`. Clients can use these to preview
//! whether a call will be accepted before signing it.

#![cfg_attr(not(feature = "std"), no_std)]

use bulletin_transaction_storage_primitives::TransactionRef;
use codec::{Codec, Decode, Encode};
use scale_info::TypeInfo;

/// Active-authorization summary for an account. Returned by
/// [`BulletinTransactionStorageApi::account_authorization`] when the account
/// has an unexpired authorization entry.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Encode, Decode, TypeInfo)]
pub struct AccountAuthorization<BlockNumber> {
/// Block at which this account's authorization expires.
pub expires_at: BlockNumber,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if client will be able to interpret this - relay block, Bulletin para block?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to use time? Relay chain block would be better for me, I'm vouching for that

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to use time? Relay chain block would be better for me, I'm vouching for that

Well, I don't know now, we don't use relay chain blocks, and everything is in Bulletin parachain blocks. I am not sure about the time. For now, with actual impl, I would just consider this Bulletin para block number and client could interpret this to the real clock time?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With authorization slots, this will be relay blocks

/// Total byte cap granted by the authorizer.
pub bytes_allowance: u64,
/// Bytes already consumed by `store` calls.
pub bytes_used: u64,
/// Bytes already consumed by `renew` calls (counts against the same
/// `bytes_allowance` cap).
pub bytes_permanent_used: u64,
}

sp_api::decl_runtime_apis! {
/// Runtime API for the Bulletin Chain transaction-storage pallet.
pub trait BulletinTransactionStorageApi<AccountId, BlockNumber>
where
AccountId: Codec,
BlockNumber: Codec,
{
/// Authorization summary for `account`, or `None` if the account has
/// no unexpired authorization.
fn account_authorization(account: AccountId) -> Option<AccountAuthorization<BlockNumber>>;

/// Returns `true` iff a `store(data)` call where `data.len() == data_len`
/// would currently pass transaction validation for `account`.
fn can_store(account: AccountId, data_len: u32) -> bool;

/// Returns `true` iff a `renew(entry)` call would currently pass transaction
/// validation for `account`.
fn can_renew(account: AccountId, entry: TransactionRef<BlockNumber>) -> bool;
}
}
Loading
Loading