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
45 changes: 44 additions & 1 deletion .github/workflows/functional.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,38 @@ env:
CARGO_TERM_COLOR: always

jobs:
run-functional-tests:
lint:
name: Lint test files
runs-on: ubuntu-latest
timeout-minutes: 30

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "^3.10" # Keep in sync with `pyproject.toml`

- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python -
echo "${HOME}/.local/bin" >> $GITHUB_PATH

- name: Configure Poetry to create the virtual environment inside the project
run: poetry config virtualenvs.in-project true

- name: Install python dependencies
run: cd functional-tests && poetry install --no-root && cd -

- name: Check formatting
run: cd functional-tests && poetry run ruff format --check && cd -

- name: Lint
run: cd functional-tests && poetry run ruff check && cd -

run:
name: Run functional tests
runs-on: ubuntu-latest
timeout-minutes: 30
Expand Down Expand Up @@ -68,3 +99,15 @@ jobs:
which alpen-express-sequencer
cd functional-tests && \
poetry run python entry.py

functional-tests-success:
name: Check that all checks pass
runs-on: ubuntu-latest
if: always()
needs: [lint, run]
timeout-minutes: 60
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
62 changes: 10 additions & 52 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,41 @@ on:

env:
CARGO_TERM_COLOR: always
CACHE_KEY: lint

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build:
name: Build workspace before tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: dtolnay/rust-toolchain@nightly
with:
components: llvm-tools-preview
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: ${{ env.CACHE_KEY }}
- name: Build project
run: |
cargo build --workspace --locked

clippy-binaries:
name: Run clippy on binaries
runs-on: ubuntu-latest
needs: build
timeout-minutes: 30
strategy:
matrix:
include:
- binary: alpen-express-sequencer
- binary: alpen-express-reth
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@clippy
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: ${{ env.CACHE_KEY }}
- run: cargo clippy --bin "${{ matrix.binary }}" --workspace --locked
env:
RUSTFLAGS: -D warnings

clippy:
name: Run clippy on library crates
name: Run clippy on crates
runs-on: ubuntu-latest
needs: build
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@clippy
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: ${{ env.CACHE_KEY }}
- run: cargo clippy --workspace --lib --examples --tests --benches --all-features --locked
- run: cargo clippy --workspace --lib --examples --tests --benches --all-features --all-targets --locked
env:
RUSTFLAGS: -D warnings

crate-checks:
name: Check that crates compile on their own
runs-on: ubuntu-latest
timeout-minutes: 40
needs: build
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
- uses: taiki-e/install-action@cargo-hack
- uses: Swatinem/rust-cache@v2
with:
cache-on-failure: true
shared-key: ${{ env.CACHE_KEY }}
- name: Configure sccache
run: |
echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV
echo "SCCACHE_GHA_ENABLED=true" >> $GITHUB_ENV
- name: Run sccache-cache
uses: mozilla-actions/[email protected]
with:
version: "v0.8.1" # sccache version
- run: cargo hack check --locked

fmt:
Expand Down Expand Up @@ -127,7 +86,6 @@ jobs:
runs-on: ubuntu-latest
if: always()
needs:
- clippy-binaries
- clippy
- crate-checks
- fmt
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ jobs:
test:
name: Run unit tests and generate report
runs-on: ubuntu-latest
env:
RUSTFLAGS: -D warnings
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@nightly
Expand Down
4 changes: 2 additions & 2 deletions Cargo.lock

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

39 changes: 13 additions & 26 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,19 +104,13 @@ fmt-check-toml: ensure-taplo ## Runs `taplo` to check that TOML files are proper
fmt-toml: ensure-taplo ## Runs `taplo` to format TOML files
taplo fmt

ensure-ruff:
@if ! command -v ruff &> /dev/null; then \
echo "ruff not found. Please install it by running the command 'pip install ruff' or refer to the following link for more information: https://docs.astral.sh/ruff/installation/" \
exit 1; \
fi

.PHONY: fmt-check-func-tests
fmt-check-func-tests: ensure-ruff ## Check formatting of python files inside `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && ruff format --check
fmt-check-func-tests: ensure-poetry ## Check formatting of python files inside `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && poetry run ruff format --check

.PHONY: fmt-func-tests
fmt-func-tests: ensure-ruff ## Apply formatting of python files inside `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && ruff format
fmt-func-tests: ensure-poetry ## Apply formatting of python files inside `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && poetry run ruff format

.PHONY: lint-check-ws
lint-check-ws: ## Checks for lint issues in the workspace.
Expand Down Expand Up @@ -162,27 +156,20 @@ lint-check-toml: ensure-taplo ## Lints TOML files
taplo lint

.PHONY: lint-check-func-tests
lint-check-func-tests: ensure-ruff ## Lints python files inside the `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && ruff check
lint-check-func-tests: ensure-poetry ## Lints the functional tests
cd $(FUNCTIONAL_TESTS_DIR) && poetry run ruff check

.PHONY: lint-fix-func-tests
lint-fix-func-tests: ensure-ruff ## Runs lint fixes for python files inside `test` directory.
cd $(FUNCTIONAL_TESTS_DIR) && ruff check --fix
.PHONY: lint-fix-functional-tests
lint-fix-func-tests: ensure-poetry ## Lints the functional tests and applies fixes where possible
cd $(FUNCTIONAL_TESTS_DIR) && poetry run ruff check --fix

.PHONY: lint
lint: ## Runs all lints and checks for issues without trying to fix them.
make lint-check-ws && \
make lint-check-codespell && \
make lint-check-toml && \
make fmt-check-toml && \
make fmt-check-ws
lint: fmt-check-ws fmt-check-func-tests fmt-check-toml lint-check-ws lint-check-func-tests lint-check-codespell ## Runs all lints and checks for issues without trying to fix them.
@echo "\n\033[36m======== OK: Lints and Formatting ========\033[0m\n"

.PHONY: lint-fix
lint-fix: ## Runs all lints and applies fixes where possible.
make lint-fix-ws && \
make lint-fix-codespell && \
make fmt-toml && \
make fmt-ws
lint-fix: fmt-toml fmt-ws lint-fix-ws lint-fix-codespell ## Runs all lints and applies fixes where possible.
@echo "\n\033[36m======== OK: Lints and Formatting Fixes ========\033[0m\n"

.PHONY: rustdocs
rustdocs: ## Runs `cargo docs` to generate the Rust documents in the `target/doc` directory.
Expand Down
52 changes: 52 additions & 0 deletions crates/bridge-exec/src/duties/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//! This module defines the duties and relevant traits that the bridge client cares about.

use std::{collections::BTreeMap, str::FromStr};

use alpen_express_state::bridge_state::OperatorIdx;
use bitcoin::{
address::{NetworkChecked, NetworkUnchecked},
amount::serde::as_sat::deserialize,
secp256k1::schnorr::Signature,
Address, Amount, NetworkKind,
};
use express_bridge_txm::{DepositInfo, DepositSignatureInfo, WithdrawalInfo};
use serde::{Deserialize, Deserializer, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "payload")]
pub enum Duty {
SignDeposit {
deposit_info: DepositInfo,
signature_info: Option<DepositSignatureInfo>,
},

FulfillWithdrawal {
withdrawal_table: WithdrawalTable,
assigned_operator_id: OperatorIdx,
expiry: BitcoinBlockHeight,
},

SignWithdrawal {
withdrawal_info: WithdrawalInfo,
signature: Option<Signature>,
},
}

/// The `bitcoin block height`
type BitcoinBlockHeight = usize;

/// The table of withdrawal requests where `Amount` is the requested withdrawal amount and
/// `BitcoinAddress` is the address to deposit the withdrawn amount. We use a `BTreeMap` to preserve
/// the order of withdrawals as that will be used to generate the withdrawal fulfillment transaction
/// chain deterministically.
pub type WithdrawalTable = BTreeMap<Amount, Address>;

// impl FromStr for BitcoinAddress {
// type Err = String;
//
// fn from_str(value: &str) -> Result<Self, Self::Err> {
// Address::from_str(value).map_err(|e| format!("invalid bitcoin address: {e}"))?;
//
// Ok::<Self, String>(Self(value.to_string()))
// }
// }
46 changes: 46 additions & 0 deletions crates/bridge-tx-manager/src/script_builder/withdrawal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//! Provides types/traits associated with the withdrawal process.

use alpen_express_state::bridge_state::OperatorIdx;
use bitcoin::{secp256k1::schnorr::Signature, OutPoint};
use serde::{Deserialize, Serialize};

/// A marker type indicating that a withdrawal request has come in and needs to be validated.
#[derive(Debug, Clone)]
pub struct Requested;

/// A marker type indicating that a withdrawal has been validated and can be signed.
#[derive(Debug, Clone)]
pub struct Validated;

/// The withdrawal information required in the cooperative path to gather signatures.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WithdrawalInfo<State = Requested> {
/// The UTXO in the operator's reserved address that they want to use to fulfill a withdrawal
/// request.
operator_reserved_utxo: OutPoint,

/// The Deposit UTXO in the Bridge Address that is to be used to reimburse the operator.
deposit_utxo: OutPoint,

/// The ID of the operator requesting the signature.
operator_id: OperatorIdx,

state: std::marker::PhantomData<State>,
// Rollup data required to verify withdrawal assignment.
// TODO: This possibly requires SSZ impl for efficient verification
// rollup_block_info: ??
}

impl WithdrawalInfo<Requested> {
/// Validate that the operator requesting
pub fn validate(&self) -> WithdrawalInfo<Validated> {
unimplemented!();
}
}

impl WithdrawalInfo<Validated> {
/// Sign off on the validated withdrawal transaction
pub fn sign_reimbursement(&self) -> Signature {
unimplemented!();
}
}
4 changes: 2 additions & 2 deletions crates/btcio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ anyhow = { workspace = true }
async-trait = { workspace = true }
base64 = { workspace = true }
bitcoin = { workspace = true }
bytes = { workspace = true }
hex = { workspace = true }
bytes = { workspace = true }
hex = { workspace = true }
rand = { workspace = true }
reqwest = { workspace = true }
serde = { workspace = true }
Expand Down
2 changes: 1 addition & 1 deletion crates/db/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ anyhow = { workspace = true }
arbitrary = { workspace = true }
bitcoin = { workspace = true }
borsh = { workspace = true }
mockall = { workspace = true, optional = true }
parking_lot = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }
mockall = { workspace = true, optional = true }

[features]
default = []
Expand Down
2 changes: 1 addition & 1 deletion crates/state/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ borsh = { workspace = true }
digest = { workspace = true }
num_enum = { workspace = true }
sha2 = { workspace = true }
tracing = { workspace = true } # ideally this shouldn't be in this trait
tracing = { workspace = true }
Loading