Skip to content
Open
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
2 changes: 1 addition & 1 deletion functional-tests/envs/testenv.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def __init__(self, datadir_root: str, name: str, env: flexitest.LiveEnv):
)
.with_pubkey(agg_pubkey)
.with_magic_bytes("".join(chr(b) for b in rollup_cfg.magic_bytes))
.with_datadir(self.datadir_root)
.with_datadir(os.path.join(self.datadir_root, name))
)

self.alpen_cli = builder.build(self)
Expand Down
4 changes: 3 additions & 1 deletion functional-tests/factory/alpen_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,14 @@ def l1_address(self):
# fmt: on
return self._run_and_extract_with_re(cmd, r"\b(?:bc1|tb1|bcrt1)[0-9a-z]{25,59}\b")

def deposit(self) -> str | None:
def deposit(self, alpen_address=None) -> str | None:
# fmt: off
cmd = [
"alpen",
"deposit",
]
if alpen_address:
cmd.append(alpen_address)
# fmt: on
return self._run_and_extract_with_re(cmd, r"Transaction ID:\s*([0-9a-f]{64})")

Expand Down
1 change: 1 addition & 0 deletions functional-tests/mixins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def premain(self, ctx: flexitest.RunContext):
w3 = self._new_w3()
funded_acc = FundedAccount(w3)
funded_acc.fund_me(genesis_account)
self.funded_acc = funded_acc
# Setting transactions api with default DEBUG level.
self._txs = EthTransactions(funded_acc, self.debug)
self._w3 = w3
Expand Down
6 changes: 3 additions & 3 deletions functional-tests/mixins/bridge_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def deposit(
self.info(f"Initial EL balance: {initial_balance}")

# Make DRT (deposit request transaction)
drt_tx_id, raw_drt_bytes = self.make_drt()
drt_tx_id, raw_drt_bytes = self.make_drt(el_address)
self.info(f"Deposit Request Transaction ID: {drt_tx_id}")

# Create managed DT (deposit transaction) with auto-incremented ID
Expand Down Expand Up @@ -178,7 +178,7 @@ def check_checkpoint_covers_withdrawal():

return l2_tx_hash, tx_receipt, total_gas_used

def make_drt(self) -> tuple[str, str]:
def make_drt(self, el_address=None) -> tuple[str, str]:
"""
Creates and matures a Deposit Request Transaction (DRT).

Expand All @@ -193,7 +193,7 @@ def make_drt(self) -> tuple[str, str]:
self.btcrpc.proxy.sendtoaddress(addr, 10.01)
self.btcrpc.proxy.generatetoaddress(1, seq_addr)
# Create and send deposit request transaction
drt_tx_id = self.alpen_cli.deposit()
drt_tx_id = self.alpen_cli.deposit(el_address)
current_height = self.btcrpc.proxy.getblockcount()
# time to mature DRT
self.btcrpc.proxy.generatetoaddress(6, seq_addr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from mixins import bridge_mixin
from utils import get_bridge_pubkey
from utils.transaction import SmartContracts


class BridgePrecompileMixin(bridge_mixin.BridgeMixin):
Expand All @@ -15,14 +16,27 @@ def premain(self, ctx: flexitest.InitContext):

self.withdraw_address = ctx.env.gen_ext_btc_address()
self.bridge_pk = get_bridge_pubkey(self.seqrpc)
self.w3.eth.default_account = self.w3.address

xonlypk = extract_p2tr_pubkey(self.withdraw_address)
bosd = xonlypk_to_descriptor(xonlypk)

self.bosd = bytes.fromhex(bosd)

# Extract ABI for compatibility with existing tests
self.abi, _ = SmartContracts.compile_contract(
"IndirectWithdrawalProxy.sol", "WithdrawCaller"
)

# Deploy contract.
self.withdraw_contract_id = "withdraw_contract"
self.txs.deploy_contract(
contract_address, _ = self.txs.deploy_contract(
"IndirectWithdrawalProxy.sol", "WithdrawCaller", self.withdraw_contract_id
)

# Create a simple object to hold the contract address for compatibility
class DeploymentReceipt:
def __init__(self, contract_address):
self.contractAddress = contract_address

self.deployed_contract_receipt = DeploymentReceipt(contract_address)
22 changes: 1 addition & 21 deletions functional-tests/tests/bridge/bridge_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
import os

import base58
import flexitest
from strata_utils import (
extract_p2tr_pubkey,
Expand Down Expand Up @@ -30,24 +27,7 @@ def __init__(self, ctx: flexitest.InitContext):
)

def main(self, ctx: flexitest.RunContext):
path = os.path.join(ctx.datadir_root, "_bridge_test", "_init")
print(path)
priv_keys = []
opkeys = sorted(
filter(lambda file: file.startswith("opkey"), os.listdir(path)),
key=lambda x: int("".join(filter(str.isdigit, x))),
)
print(opkeys)
for filename in opkeys:
if not filename.startswith("op"):
continue

full_path = os.path.join(path, filename)
with open(full_path) as f:
content = f.read().strip()
decoded = base58.b58decode(content)[:-4] # remove checksum
priv_keys.append(decoded)

priv_keys = get_priv_keys(ctx)
el_address = self.alpen_cli.l2_address()
print("-----------------------")
print(el_address)
Expand Down
71 changes: 41 additions & 30 deletions functional-tests/tests/el_bridge_precompile.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,44 @@
import os
import time

import flexitest
from web3 import Web3
from web3._utils.events import get_event_data

from envs import testenv
from envs import net_settings, testenv
from mixins.bridge_out_precompile_contract_mixin import BridgePrecompileMixin
from utils import *
from utils.constants import PRECOMPILE_BRIDGEOUT_ADDRESS

withdrawal_intent_event_abi = {
"anonymous": False,
"inputs": [
{"indexed": False, "internalType": "uint64", "name": "amount", "type": "uint64"},
{"indexed": False, "internalType": "bytes", "name": "dest_pk", "type": "bytes32"},
{"indexed": False, "internalType": "bytes", "name": "destination", "type": "bytes"},
],
"name": "WithdrawalIntentEvent",
"type": "event",
}
event_signature_text = "WithdrawalIntentEvent(uint64,bytes32)"
event_signature_text = "WithdrawalIntentEvent(uint64,bytes)"


@flexitest.register
class ElBridgePrecompileTest(testenv.StrataTestBase):
class ElBridgePrecompileTest(BridgePrecompileMixin):
def __init__(self, ctx: flexitest.InitContext):
ctx.set_env("basic")
ctx.set_env(
testenv.BasicEnvConfig(
101,
prover_client_settings=ProverClientSettings.new_with_proving(),
rollup_settings=net_settings.get_fast_batch_settings(),
auto_generate_blocks=True,
)
)

def main(self, ctx: flexitest.RunContext):
self.warning("SKIPPING TEST fn_el_bridge_precompile")
return True

reth = ctx.get_service("reth")
web3: Web3 = reth.create_web3()
web3: Web3 = self.reth.create_web3()

source = web3.address
dest = web3.to_checksum_address(PRECOMPILE_BRIDGEOUT_ADDRESS)
# 64 bytes
dest_pk = os.urandom(32).hex()
self.debug(dest_pk)

priv_keys = get_priv_keys(ctx)
self.deposit(ctx, self.deployed_contract_receipt.contractAddress, priv_keys)

assert web3.is_connected(), "cannot connect to reth"

Expand All @@ -46,24 +48,36 @@ def main(self, ctx: flexitest.RunContext):

assert original_bridge_balance == 0

# 10 rollup btc as wei
to_transfer_wei = 10_000_000_000_000_000_000
cfg = ctx.env.rollup_cfg()
deposit_amount = cfg.deposit_amount
to_transfer_sats = deposit_amount * 10_000_000_000
to_transfer_wei = to_transfer_sats # Same value in wei
dest_pk = "0x04db4c79cc3ffca26f51e21241b9332d646b0772dd7e98de9c1de6b10990cab80b"

txid = web3.eth.send_transaction(
{
"to": dest,
"value": hex(to_transfer_wei),
"gas": hex(100000),
"value": hex(to_transfer_sats),
"from": source,
"gas": hex(200000),
"data": dest_pk,
}
)
self.debug(txid.to_0x_hex())

# build block
time.sleep(2)

receipt = web3.eth.get_transaction_receipt(txid)
def check_transaction_and_blocks():
try:
receipt = web3.eth.get_transaction_receipt(txid)
return receipt
except Exception as e:
return e

receipt = wait_until_with_value(
check_transaction_and_blocks,
lambda result: not isinstance(result, Exception),
error_with="Transaction receipt for txid not available",
timeout=60,
step=2,
)
Comment on lines +74 to +80
Copy link
Contributor

Choose a reason for hiding this comment

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

This is basically doing a "wait until EVM tx included in block" operation. If there isn't already waiter for this then can we add it to one so it's available everywhere?


assert receipt.status == 1, "precompile transaction failed"
assert len(receipt.logs) == 1, "no logs or invalid logs"
Expand All @@ -74,11 +88,8 @@ def main(self, ctx: flexitest.RunContext):
assert log.topics[0].hex() == event_signature_hash
event_data = get_event_data(web3.codec, withdrawal_intent_event_abi, log)

# 1 rollup btc = 10**18 wei
to_transfer_sats = to_transfer_wei // 10_000_000_000

assert event_data.args.amount == to_transfer_sats
assert event_data.args.dest_pk.hex() == dest_pk
assert event_data.args.amount == deposit_amount
assert event_data.args.destination.hex() == dest_pk[2:] # Remove 0x prefix for comparison

final_block_no = web3.eth.block_number
final_bridge_balance = web3.eth.get_balance(dest)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
import logging

import flexitest

from envs import net_settings, testenv
from mixins.bridge_out_precompile_contract_mixin import BridgePrecompileMixin
from utils import ProverClientSettings, get_priv_keys


@flexitest.register
class ContractBridgeOutWithContractBalanceTest(BridgePrecompileMixin):
def __init__(self, ctx: flexitest.InitContext):
fast_batch_settings = net_settings.get_fast_batch_settings()
ctx.set_env(
testenv.BasicEnvConfig(pre_generate_blocks=101, rollup_settings=fast_batch_settings)
testenv.BasicEnvConfig(
101,
prover_client_settings=ProverClientSettings.new_with_proving(),
rollup_settings=net_settings.get_fast_batch_settings(),
auto_generate_blocks=True,
)
)

def main(self, ctx: flexitest.RunContext):
logging.warn("test temporarily disabled")
return

# Deposit to contract Address
self.deposit(ctx, self.deployed_contract_receipt.contractAddress, self.bridge_pk)
priv_keys = get_priv_keys(ctx)
self.deposit(ctx, self.deployed_contract_receipt.contractAddress, priv_keys)
self.deposit(ctx, self.web3.address, priv_keys)

# withdraw
# TODO: use self.txs.deploy and self.txs.call
Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
import logging

import flexitest

from envs import net_settings, testenv
from envs.rollup_params_cfg import RollupConfig
from mixins.bridge_out_precompile_contract_mixin import BridgePrecompileMixin
from utils import ProverClientSettings, get_priv_keys
from utils.constants import SATS_TO_WEI


@flexitest.register
class ContractBridgeOutWithSenderValueTest(BridgePrecompileMixin):
def __init__(self, ctx: flexitest.InitContext):
fast_batch_settings = net_settings.get_fast_batch_settings()
ctx.set_env(
testenv.BasicEnvConfig(pre_generate_blocks=101, rollup_settings=fast_batch_settings)
testenv.BasicEnvConfig(
101,
prover_client_settings=ProverClientSettings.new_with_proving(),
rollup_settings=net_settings.get_fast_batch_settings(),
auto_generate_blocks=True,
)
)

def main(self, ctx: flexitest.RunContext):
logging.warn("test temporarily disabled")
return
priv_keys = get_priv_keys(ctx)

# deposit once
self.deposit(ctx, self.bridge_eth_account.address, self.bridge_pk)
# deposit twice
self.deposit(ctx, self.web3.address, priv_keys)
self.deposit(ctx, self.web3.address, priv_keys)
print(self.web3.address)

cfg: RollupConfig = ctx.env.rollup_cfg()
deposit_amount = cfg.deposit_amount

# Call the contract function
# TODO: use self.txs.deploy and self.txs.call
contract_instance = self.w3.eth.contract(
# check balance
contract_instance = self.web3.eth.contract(
abi=self.abi, address=self.deployed_contract_receipt.contractAddress
)
tx_hash = contract_instance.functions.withdraw(self.bosd).transact(
{"gas": 5_000_000, "value": deposit_amount * SATS_TO_WEI}
)

tx_receipt = self.w3.eth.wait_for_transaction_receipt(tx_hash, timeout=30)
tx_receipt = self.web3.eth.wait_for_transaction_receipt(tx_hash, timeout=30)
assert tx_receipt.status == 1
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def main(self, ctx: flexitest.RunContext):
self.warning("SKIPPING TEST prover_el_deposit_withdraw")
return True

evm_addr = self.bridge_eth_account.address
evm_addr = self.eth_account.address
bridge_pk = get_bridge_pubkey(self.seqrpc)

# Init RPCs.
Expand Down
26 changes: 26 additions & 0 deletions functional-tests/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from threading import Thread
from typing import Any, TypeVar

import base58
from bitcoinlib.services.bitcoind import BitcoindClient
from strata_utils import convert_to_xonly_pk, musig_aggregate_pks

Expand Down Expand Up @@ -652,3 +653,28 @@ def check_initial_eth_balance(rethrpc, address, debug_fn=print):
balance = int(rethrpc.eth_getBalance(address), 16)
debug_fn(f"Strata Balance before deposits: {balance}")
assert balance == 0, "Strata balance is not expected (should be zero initially)"


def get_priv_keys(ctx, env=None):
if env is None:
path = os.path.join(ctx.datadir_root, f"_{ctx.name}", "_init")
else:
path = os.path.join(ctx.datadir_root, env, "_init")

print(path)
priv_keys = []
opkeys = sorted(
filter(lambda file: file.startswith("opkey"), os.listdir(path)),
key=lambda x: int("".join(filter(str.isdigit, x))),
)
print(opkeys)
Comment on lines +664 to +670
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these prints needed? If so then use logging so they get picked up properly.

Edit: oh I see these were from before this PR, it'd be good to convert over the prints in these updated tests

for filename in opkeys:
if not filename.startswith("op"):
continue

full_path = os.path.join(path, filename)
with open(full_path) as f:
content = f.read().strip()
decoded = base58.b58decode(content)[:-4] # remove checksum
priv_keys.append(decoded)
return priv_keys
Loading