-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8608b97
commit d67a5d6
Showing
3 changed files
with
114 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,44 @@ | ||
import sys | ||
from enum import IntEnum | ||
from pathlib import Path | ||
from ragger.utils import create_currency_config | ||
from ragger.bip import BtcDerivationPathFormat, bitcoin_pack_derivation_path | ||
from ragger.backend.interface import BackendInterface, RAPDU | ||
from ragger.backend import RaisePolicy | ||
|
||
sys.path.append(f"{Path(__file__).parent.resolve()}/bitcoin_client") | ||
from txmaker import createPsbt | ||
from ledger_bitcoin import Client, WalletPolicy, MultisigWallet, AddressType, PartialSignature, segwit_addr | ||
from ledger_bitcoin import Client, Chain, createClient | ||
from ledger_bitcoin.bip380.descriptors import Descriptor | ||
|
||
BTC_CONF = create_currency_config("BTC", "Bitcoin") | ||
|
||
BTC_PACKED_DERIVATION_PATH = bitcoin_pack_derivation_path(BtcDerivationPathFormat.BECH32, "m/44'/0'/0'/0/0") | ||
BTC_PACKED_DERIVATION_PATH = bitcoin_pack_derivation_path(BtcDerivationPathFormat.BECH32, "m/84'/0'/0'/0/0") | ||
|
||
CHAIN = Chain.MAIN | ||
|
||
class BitcoinErrors(IntEnum): | ||
SW_SWAP_CHECKING_FAIL = 0x6b00 | ||
|
||
class BitcoinClient: | ||
def __init__(self, backend: BackendInterface): | ||
if not isinstance(backend, BackendInterface): | ||
raise TypeError("backend must be an instance of BackendInterface") | ||
self._backend = backend | ||
self._backend.raise_policy = RaisePolicy.RAISE_CUSTOM | ||
self._backend.whitelisted_status = [0x9000, 0xE000] | ||
self.client = createClient(backend, chain=CHAIN, debug=True) | ||
|
||
def send_simple_sign_tx(self, in_wallet: WalletPolicy, fees: int, destination: WalletPolicy, send_amount: int) -> RAPDU: | ||
in_amounts = [send_amount + fees] | ||
out_amounts = [send_amount] | ||
psbt = createPsbt(in_wallet, in_amounts, out_amounts, [False], [destination]) | ||
self.client.sign_psbt(psbt, in_wallet, None) | ||
|
||
def get_address_from_wallet(wallet: WalletPolicy): | ||
desc = Descriptor.from_str(wallet.get_descriptor(False)) | ||
desc.derive(0) | ||
spk = desc.script_pubkey | ||
hrp = "bc" if CHAIN == Chain.MAIN else "tb" | ||
return segwit_addr.encode(hrp, 0, spk[2:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,5 @@ stellar_sdk | |
base58 | ||
xrpl-py | ||
scalecodec | ||
bip32 | ||
embit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import pytest | ||
|
||
from .apps.exchange_test_runner import ExchangeTestRunner, ALL_TESTS_EXCEPT_MEMO | ||
from .apps.bitcoin import BitcoinClient, BitcoinErrors | ||
from ledger_bitcoin import WalletPolicy | ||
|
||
in_wallet = WalletPolicy( | ||
"", | ||
"wpkh(@0/**)", | ||
[ | ||
"[f5acc2fd/84'/0'/0']xpub6DUYn4moKgHkK2d7bXX3mHTPb6XQwRVFRMdZ6ZwLS5u3nonGVpJiFeZiQkHutwdFqxKP75jex8gvVm7ed4euYeDtMnoiF1Cz1z4CeBJYWin" | ||
], | ||
) | ||
|
||
out_wallet = WalletPolicy( | ||
"", | ||
"wpkh(@0/**)", | ||
[ | ||
"xpub6CatWdiZiodmYVtWLtEQsAg1H9ooS1bmsJUBwQ83FE1Fyk386FWcyicJgEZv3quZSJKA5dh5Lo2PbubMGxCfZtRthV6ST2qquL9w3HSzcUn" | ||
], | ||
) | ||
|
||
out_wallet_2 = WalletPolicy( | ||
"", | ||
"wpkh(@0/**)", | ||
[ | ||
"xpub6D7atwj3ewAGT347tUzTNzfTGos1rCFVX4v8gViXiM2R1QHvox1LhEf6NtCeNsCwpppFUoQuS6mHUwfTveA5tEEwn2LqZHfVBEz5qvYmYhf" | ||
], | ||
) | ||
|
||
# ExchangeTestRunner implementation for Bitcoin | ||
class BitcoinTests(ExchangeTestRunner): | ||
|
||
currency_ticker = "BTC" | ||
valid_destination_1 = BitcoinClient.get_address_from_wallet(out_wallet) | ||
valid_destination_memo_1 = "" | ||
valid_destination_2 = BitcoinClient.get_address_from_wallet(out_wallet_2) | ||
valid_destination_memo_2 = "0" | ||
valid_refund = BitcoinClient.get_address_from_wallet(in_wallet) | ||
valid_refund_memo = "" | ||
valid_send_amount_1 = 20900000 | ||
valid_send_amount_2 = 446739662 | ||
valid_fees_1 = 100000 | ||
valid_fees_2 = 10078 | ||
fake_refund = "abcdabcd" | ||
fake_refund_memo = "" | ||
fake_payout = "abcdabcd" | ||
fake_payout_memo = "" | ||
signature_refusal_error_code = BitcoinErrors.SW_SWAP_CHECKING_FAIL | ||
|
||
def perform_final_tx(self, destination, send_amount, fees, memo): | ||
if destination == BitcoinClient.get_address_from_wallet(out_wallet): | ||
BitcoinClient(self.backend).send_simple_sign_tx(in_wallet=in_wallet, | ||
fees=fees, | ||
destination=out_wallet, | ||
send_amount=send_amount) | ||
|
||
elif destination == BitcoinClient.get_address_from_wallet(out_wallet_2): | ||
BitcoinClient(self.backend).send_simple_sign_tx(in_wallet=in_wallet, | ||
fees=fees, | ||
destination=out_wallet_2, | ||
send_amount=send_amount) | ||
|
||
# TODO : assert signature validity | ||
|
||
|
||
# Use a class to reuse the same Speculos instance | ||
class TestsBitcoin: | ||
|
||
@pytest.mark.parametrize('test_to_run', ALL_TESTS_EXCEPT_MEMO) | ||
def test_bitcoin(self, backend, exchange_navigation_helper, test_to_run): | ||
BitcoinTests(backend, exchange_navigation_helper).run_test(test_to_run) | ||
|