Skip to content

Commit

Permalink
contract checking tx inclusion in block
Browse files Browse the repository at this point in the history
  • Loading branch information
lana-shanghai committed Dec 11, 2024
1 parent 1542a05 commit d25ede2
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 1 deletion.
52 changes: 52 additions & 0 deletions packages/onchain/Scarb.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,27 @@ name = "alexandria_math"
version = "0.2.1"
source = "git+https://github.com/keep-starknet-strange/alexandria#95d98a5182001d07673b856a356eff0e6bd05354"

[[package]]
name = "consensus"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/raito.git?rev=02a13045b7074ae2b3247431cd91f1ad76263fb2#02a13045b7074ae2b3247431cd91f1ad76263fb2"
dependencies = [
"shinigami_engine",
"utils",
]

[[package]]
name = "onchain"
version = "0.1.0"
dependencies = [
"alexandria_math",
"consensus",
"openzeppelin",
"openzeppelin_token",
"openzeppelin_utils",
"snforge_std",
"utils",
"utu_relay",
]

[[package]]
Expand Down Expand Up @@ -123,6 +135,31 @@ name = "openzeppelin_utils"
version = "0.19.0"
source = "git+https://github.com/openzeppelin/cairo-contracts?tag=v0.19.0#8d49e8c445efd9bdc99b050c8b7d11ae5ad19628"

[[package]]
name = "ripemd160"
version = "0.1.0"
source = "git+https://github.com/j1mbo64/ripemd160_cairo.git#833e07d7d074d4ee51ceb40a5bcb4af2fe6898f3"

[[package]]
name = "sha1"
version = "0.1.0"
source = "git+https://github.com/j1mbo64/sha1_cairo.git#2b65bc00a829bdcc244c140d0f31feda32f8d2c4"

[[package]]
name = "shinigami_engine"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/shinigami.git?rev=3415ed6#3415ed6331d3ea2dc2de6f9ab8e0be6562585f2d"
dependencies = [
"ripemd160",
"sha1",
"shinigami_utils",
]

[[package]]
name = "shinigami_utils"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/shinigami.git?rev=3415ed6#3415ed6331d3ea2dc2de6f9ab8e0be6562585f2d"

[[package]]
name = "snforge_scarb_plugin"
version = "0.33.0"
Expand All @@ -135,3 +172,18 @@ source = "git+https://github.com/foundry-rs/starknet-foundry?tag=v0.33.0#221b1db
dependencies = [
"snforge_scarb_plugin",
]

[[package]]
name = "utils"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/raito.git?rev=02a13045b7074ae2b3247431cd91f1ad76263fb2#02a13045b7074ae2b3247431cd91f1ad76263fb2"

[[package]]
name = "utu_relay"
version = "0.1.0"
source = "git+https://github.com/lana-shanghai/utu_relay.git#25f8d9799df04465c716155e9ece61d9145b0f8c"
dependencies = [
"openzeppelin",
"openzeppelin_upgrades",
"utils",
]
13 changes: 12 additions & 1 deletion packages/onchain/Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,29 @@ edition = "2024_07"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[patch.crates-io]
openzeppelin = "0.19.0"

[dependencies]
snforge_std = { git = "https://github.com/foundry-rs/starknet-foundry", tag = "v0.33.0" }
openzeppelin = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.19.0" }
starknet = "2.9.1"
alexandria_math = { git = "https://github.com/keep-starknet-strange/alexandria" }
openzeppelin_token = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.19.0" }
openzeppelin_utils = { git = "https://github.com/openzeppelin/cairo-contracts", tag = "v0.19.0" }
utils = { git = "https://github.com/keep-starknet-strange/raito.git", rev = "02a13045b7074ae2b3247431cd91f1ad76263fb2" }
consensus = { git = "https://github.com/keep-starknet-strange/raito.git", rev = "02a13045b7074ae2b3247431cd91f1ad76263fb2" }
utu_relay = { git = "https://github.com/lana-shanghai/utu_relay.git" }

[[target.starknet-contract]]
casm = true
sierra = true
build-external-contracts = ["openzeppelin_presets::erc20::ERC20Upgradeable"]
build-external-contracts = [
"openzeppelin_presets::erc20::ERC20Upgradeable",
"utu_relay::utu_relay::UtuRelay"
]
allowed-libfuncs-list.name = "experimental"
casm-add-pythonic-hints = true

[dev-dependencies]
assert_macros = "2.9.1"
Expand Down
1 change: 1 addition & 0 deletions packages/onchain/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod escrow;
mod orderbook;
mod utils;
mod relay;
1 change: 1 addition & 0 deletions packages/onchain/src/relay.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod relay;
61 changes: 61 additions & 0 deletions packages/onchain/src/relay/relay.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
use utils::hash::Digest;
use utu_relay::bitcoin::block::BlockHeader;

#[starknet::interface]
pub trait IBitcoinDepositor<TContractState> {
fn prove_inclusion(
ref self: TContractState,
tx_id: Digest,
block_height: u64,
block_header: BlockHeader,
tx_inclusion: Array<(Digest, bool)>
);
}

#[starknet::contract]
mod BitcoinDepositor {
use onchain::utils::utils::compute_merkle_root;
use utu_relay::bitcoin::block::BlockHashTrait;
use starknet::{ContractAddress, get_block_timestamp};
use starknet::storage::{StoragePointerReadAccess, StoragePointerWriteAccess};
use utils::{hash::Digest, numeric::u32_byte_reverse};
use utu_relay::{
interfaces::{IUtuRelayDispatcher, IUtuRelayDispatcherTrait}, bitcoin::block::BlockHeader
};

#[storage]
struct Storage {
depositor: ContractAddress,
utu_address: ContractAddress,
}

#[constructor]
fn constructor(ref self: ContractState, utu_address: ContractAddress) {
self.utu_address.write(utu_address);
}

#[abi(embed_v0)]
impl BitcoinDepositorImpl of super::IBitcoinDepositor<ContractState> {
fn prove_inclusion(
ref self: ContractState,
tx_id: Digest,
block_height: u64,
block_header: BlockHeader,
tx_inclusion: Array<(Digest, bool)>
) {
// we verify this tx is included in the provided block
let merkle_root = compute_merkle_root(tx_id, tx_inclusion);
assert(
block_header.merkle_root_hash.value == merkle_root.value, 'Invalid inclusion proof.'
);

// we verify this block is safe to use (part of the canonical chain & sufficient pow)
// sufficient pow for our usecase: 100 sextillion expected hashes
let utu = IUtuRelayDispatcher { contract_address: self.utu_address.read() };
utu.assert_safe(block_height, block_header.hash(), 100_000_000_000_000_000_000_000, 0);
// we ensure this block was not premined
let block_time = u32_byte_reverse(block_header.time).into();
assert(block_time <= get_block_timestamp(), 'Block comes from the future.');
}
}
}
36 changes: 36 additions & 0 deletions packages/onchain/src/utils/utils.cairo
Original file line number Diff line number Diff line change
@@ -1 +1,37 @@
use utils::hash::Digest;
use utils::double_sha256::double_sha256_parent;

/// Computes the Merkle root from a transaction hash and its siblings.
///
/// Arguments:
/// - `tx_hash: Digest`: The transaction hash as a Digest
/// - `siblings: Array<(Digest, bool)>`: An array of tuples (Digest, bool), where the bool indicates if the sibling is on
/// the right
///
/// Returns:
/// - `Digest`: The computed Merkle root as a Digest
pub fn compute_merkle_root(tx_hash: Digest, siblings: Array<(Digest, bool)>) -> Digest {
let mut current_hash = tx_hash;

// Iterate through all siblings
let mut i = 0;
loop {
if i == siblings.len() {
break;
}

let (sibling, is_left) = *siblings.at(i);

// Concatenate current_hash and sibling based on the order
current_hash =
if is_left {
double_sha256_parent(@sibling, @current_hash)
} else {
double_sha256_parent(@current_hash, @sibling)
};

i += 1;
};

current_hash
}

0 comments on commit d25ede2

Please sign in to comment.