Multisig – Earlybirds Invest https://earlybirdsinvest.com Latest Crypto News Mon, 01 Sep 2025 22:40:23 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.8 https://i0.wp.com/earlybirdsinvest.com/wp-content/uploads/2024/12/cropped-New-Project-2024-12-17T235703.455.png?fit=32%2C32&ssl=1 Multisig – Earlybirds Invest https://earlybirdsinvest.com 32 32 240146708 OpenSats Grant Fuels Bitcoin-Safe Safe Multi-Sig Wallet Fire Hardware Focus https://earlybirdsinvest.com/opensats-grant-fuels-bitcoin-safe-safe-multi-sig-wallet-fire-hardware-focus/ https://earlybirdsinvest.com/opensats-grant-fuels-bitcoin-safe-safe-multi-sig-wallet-fire-hardware-focus/#respond Mon, 01 Sep 2025 22:40:22 +0000 https://earlybirdsinvest.com/opensats-grant-fuels-bitcoin-safe-safe-multi-sig-wallet-fire-hardware-focus/

Bitcoin-Safe, an open source Bitcoin savings wallet, is now available for families, individuals and businesses looking for safe, long-term Bitcoin storage. It focuses on multi-sig security and distinguishes itself from other desktop wallets such as Electrum and Sparrow, as it requires a hardware wallet for mainnet operations. Supported by the one-year OpenSats Grant awarded in March 2025, Bitcoin-Safe is the latest version 1.5.0 released on September 1, 2025, combining robust security with a redesigned user interface.

Development and OpenSat Support

Developed by Andreas Griffin for over two and a half years, Bitcoin-Safe aims to simplify multi-sig setups and reduce reliance on Electrum servers. “I started with this wallet two and a half years ago, and I had two goals to make multisig easier and not have to resort to Electrum servers,” Griffin told Bitcoin Magazine. OpenSats Grant, which will be held from March 2025 to March 2026, supports these efforts. The open source code for wallets built into the Bitcoin Dev Kit (BDK) is auditable on GitHub, and installable clients are available for free at Bitcoin-safe.org/download.

Multisig, hardware wallet security, coin control

Bitcoin-Safe enforces hardware wallets for the mainnet and prohibits software seeds from mitigating security risks. “There’s no way around hardware wallets to save money,” Griffin said, highlighting compatibility with major hardware devices via QR, USB or SD cards. This allows Bitcoin Safe to allow software seeds, prioritize security for significant savings, and minimize “footguns.” This is a feature that users can easily hurt.

The Wallet Multisig Setup Wizard generates PDFs with wallet descriptors, such as send and receive tests for validation. “After this wizard is finished, you can make sure it’s set up correctly,” Griffin said. This ensures reliable configuration and allows for multisig access without compromising security.

Using the NOSTR protocol, Bitcoin-Safe synchronizes transactions and addresses the entire end-to-end encrypted device label. “We create protocols on top of Nostr to link these computers and synchronize labels seamlessly,” Griffin said. Multisig participants can share partially signed Bitcoin Transactions (PSBTs) with a single click, and the relay stores encrypted messages for asynchronous access.

The Coin category separates funds such as KYC exchange withdrawals and private coins to prevent unintended transaction connections. “You should not link it by mistake as you need to select the source of the fund,” Griffin supported the privacy of users.

User Interface and Experience

Version 1.5.0 introduces a new interface developed with @Design-R. “The designers who participated in the project are really very helpful,” Griffin said. Features include a sidebar for managing multiple wallets, an updated transaction view for sending and signing PSBTs, and a Mempool visualization showing block and fee data.

The wallet will add keyboard shortcuts, tooltips and clear error messages. Bug fixes improve functionality and ensure accessibility for beginners and advanced users.

Bitcoin-Safe supports real-time conversion of 123 Fiat currencies integrated into the interface. It also converts Bitcoin to gold or silver values ​​in ounces and grams. Real-time Mempool alerts notify users of transaction propagation. “This is an opt-in feature for existing users and opt-out of new installations,” Griffin said, noting in a customizable network setting.

Users can unlock multiple wallets with a single encryption password. “If multiple wallets share the same encryption password, users must enter it only once,” explained Griffin. Nostr’s Chat & Sync feature enables remote PSBT adjustments for multi-sig participants.

Community and Accessibility

Bitcoin-Safe supports languages ​​such as English, Chinese, and Spanish, as well as translation via Weblate. Users can test with TBTC, report bugs, or donate via Lightning or Onchain. Engagement is done through chorus.community and x accounts (@bitcoinsafe, @bitcoinsafecn) and documentation is available at bitcoin-safe.org.

Future Development: Compact Block Filter

Bitcoin-Safe plans to replace the Electrum server in 2025 with integrated compact block filters. “My plan is to replace (Electrum Servers) with a compact block filter and retrieve blockchain data directly from the Bitcoin core node,” Griffin said, aiming to enhance privacy and server independence.

]]>
https://earlybirdsinvest.com/opensats-grant-fuels-bitcoin-safe-safe-multi-sig-wallet-fire-hardware-focus/feed/ 0 56285
Multisig Fund Protection Strategy Review https://earlybirdsinvest.com/multisig-fund-protection-strategy-review/ https://earlybirdsinvest.com/multisig-fund-protection-strategy-review/#respond Sat, 14 Jun 2025 23:01:48 +0000 https://earlybirdsinvest.com/multisig-fund-protection-strategy-review/ I want to protect my bitcoin and mine Threat model It’s about accessing one of two paper copies of the seed, collecting your wallet and stealing your funds. To mitigate this risk, we are considering the 2-OUT-3 multi-sig wallet option. My first strategy is:
Enter the image description here

Therefore, I have four geographically separated secret locations (except for myself). As for hardware wallets, if your main device is stolen, you need another key, which means Bitcoin is safe. The same can be said when location 1 or 2 is discovered and the hardware wallet device is stolen (as there is only one hardware wallet). butTaking the perspective of seeds, two seeds are compromised.

My first question is whether an attacker can discover two seeds and steal funds, or three seeds Must do To replicate the wallet and steal the funds? (I assume that an attacker can access two seeds to reproduce the private key and (It’s not possible to use a multi-sig wallet set up on my personal computer). Because collecting multi-sig wallets with Electrum requires three seeds (or co-signers of one seed and two public keys), but I really want to reaffirm with the community. Bitcoin cannot find two seeds and move. Note that in this setup, you need mobile Bitcoin to co-sign with hardware wallet 3, in this case either hardware wallet 1 or 2, so you need cold cold storage effectively.

Another option is to create a Hidden wallet Comes with a passphrase using one wallet. In that case, two copies of the seed and two copies of the passphrase can be stored in four geographically different locations. If seeds are found, you cannot access the hidden wallet, and if you access the passphrase, you cannot replicate the hidden wallet either. The only vulnerability in the latter case is when a hardware device is stolen and used to transport money (though physically tampering or using it may limit use of device pins).

My second question is whether the first option gives a significantly higher entropy for protection. Note that in storage costs, the cost is the same as having to use four locations in both cases.

]]>
https://earlybirdsinvest.com/multisig-fund-protection-strategy-review/feed/ 0 42047
Can’t get the signature of P2SH-P2WSH nested 2 correctly in two Multisig scripts https://earlybirdsinvest.com/cant-get-the-signature-of-p2sh-p2wsh-nested-2-correctly-in-two-multisig-scripts/ https://earlybirdsinvest.com/cant-get-the-signature-of-p2sh-p2wsh-nested-2-correctly-in-two-multisig-scripts/#respond Fri, 21 Feb 2025 12:11:56 +0000 https://earlybirdsinvest.com/cant-get-the-signature-of-p2sh-p2wsh-nested-2-correctly-in-two-multisig-scripts/
def BIP_143_raw_transaction(prev_tx_id: str, amount_to_be_sent: int | float, signatureScript: str | None, pubKeyScript: str | None):
    # Version
    version = bytes.fromhex("02000000")
    # HashPrevOuts = prev_tx + vout
    HashPrev_out = bytes.fromhex(double_sha256(
        "0"*72))
    # HashSequence
    HashSequence = bytes.fromhex(double_sha256("f"*8))
    # HashOutputs for ALL signHash
    HashOutputs = bytes.fromhex(double_sha256(
        "a08601000000000017a914043f512301b66ffa8d73e71907e2b0b80989521587"))
    # Hash preimage for all
    raw_hash_pre_images = bytearray()
    raw_hash_pre_images.extend(version)
    raw_hash_pre_images.extend(HashPrev_out)
    raw_hash_pre_images.extend(HashSequence)
    raw_hash_pre_images.extend(bytes.fromhex(
        "000000000000000000000000000000000000000000000000000000000000000000000000"))
    # CORRECTION 2 scriptcode
    #ONLY ERROR IF THIS
    raw_hash_pre_images.extend(bytes.fromhex(
        "475221032ff8c5df0bc00fe1ac2319c3b8070d6d1e04cfbf4fedda499ae7b775185ad53b21039bbc8d24f89e5bc44c5b0d1980d6658316a6b2440023117c3c03a4975b04dd5652ae"))
    raw_hash_pre_images.extend(bytes.fromhex("a086010000000000"))
    raw_hash_pre_images.extend(bytes.fromhex("ffffffff"))
    raw_hash_pre_images.extend(HashOutputs)
    raw_hash_pre_images.extend(bytes.fromhex("00000000"))
    raw_hash_pre_images.extend(bytes.fromhex("01000000"))

    return raw_hash_pre_images.hex()

def double_sha256(hex_string):
    binary_data = binascii.unhexlify(hex_string)
    # return hashlib.sha256(hashlib.sha256(binary_data).digest()).digest()(::-1).hex()
    return hashlib.sha256(hashlib.sha256(binary_data).digest()).hexdigest()

def finalize_signed_transaction(raw_tx, signatures, redeem_script, signatureScript: str, prev_tx_id: str, amount_to_be_sent: int, pubKeyScript: str):
    try:
        witness_stack = bytearray()
        # WITNESS STACK SIZE
        witness_stack.extend(bytes.fromhex("04"))
        witness_stack.extend(bytes.fromhex("00"))
        for sig in signatures:
            witness_stack.extend(struct.pack("<256HashofRedeemScript/witnessScript>
        sigScriptlen = struct.pack('


def P2SH_P2WSH_PubKeyScript(redeem_script_hash: str):
    try:
        pubKeyScript = CScript((
            OP_HASH160,
            bytes.fromhex(redeem_script_hash),
            OP_EQUAL
        ))
        return pubKeyScript.hex()

    except Exception as error:
        print("An error ocurred while generating the PubKey Script for P2SH-P2WSH Multi-sig transaction - :", error)

def util_main():
    # IT WORKS
    private_key_arr = ("39dc0a9f0b185a2ee56349691f34716e6e0cda06a7f9707742ac113c4e2317bf",
                       "5077ccd9c558b7d04a81920d38aa11b4a9f9de3b23fab45c3ef28039920fdd6d")
    # SHA 256 on redeem Script
    hash_redeem_P2WSH = hashlib.sha256(bytes.fromhex(
        "5221032ff8c5df0bc00fe1ac2319c3b8070d6d1e04cfbf4fedda499ae7b775185ad53b21039bbc8d24f89e5bc44c5b0d1980d6658316a6b2440023117c3c03a4975b04dd5652ae")).hexdigest()
    print(hash_redeem_P2WSH, " HASHING THE REDEEM SCRIPT")
    # Witness Program
    scr = CScript((
        OP_0,
        bytes.fromhex(hash_redeem_P2WSH)
    ))
    # Hashing the Witness program
    scr_hash = hash_redeem_script(bytes.fromhex(scr.hex()))
    print(scr_hash, " HASHING THE WITNESS PROGRAM")
    # Recepient Address from the Script Hash
    scr_add = generate_token_address(scr_hash)
    print(scr_add, " Address after checksum and base58 decode")
    # Generating the output lock script or the pubKeyScript
    pub_key_P2SH_P2WSH = P2SH_P2WSH_PubKeyScript(scr_hash)
    print(pub_key_P2SH_P2WSH, " PubKeyScript Hex for P2SH P2WSH transaction")
    # Generating raw unsigned transaction for P2SH_P2WSH as The signScript will remain empty in case of witness program
    raw_tx_P2SH_P2WSH = createRawTransaction(
        "0000000000000000000000000000000000000000000000000000000000000000", 100000, "", pub_key_P2SH_P2WSH)
    print(raw_tx_P2SH_P2WSH, " Raw unsigned transaction for P2SH P2WSH")
    # breakpoint()
    bip_143_raw = BIP_143_raw_transaction("", 1, "", P2SH_P2WSH_PubKeyScript)
    print(bip_143_raw, " Raw BIP 143 raw transaction for ALL SigHash")
    # CORRECTION 3
    # s256 = hashlib.sha256(hashlib.sha256(
    #     bytes.fromhex(bip_143_raw)).digest()).digest()
    # s256 = hashlib.sha256(bytes.fromhex(bip_143_raw)).hexdigest()
    s256 = double_sha256(bip_143_raw)
    print(s256, " Hex for BIP - 143")
    signatures = signRawtransaction_P2SH_P2WSH(s256, private_key_arr)
    print(signatures(0), " Signatures from raw BIP-143")
    sigScript = signScript_P2SH_P2WSH(hash_redeem_P2WSH)
    print(sigScript, " Signature Script for P2SH_P2WSH")
    signed_transaction = finalize_signed_transaction(
        raw_tx_P2SH_P2WSH, signatures(0), "5221032ff8c5df0bc00fe1ac2319c3b8070d6d1e04cfbf4fedda499ae7b775185ad53b21039bbc8d24f89e5bc44c5b0d1980d6658316a6b2440023117c3c03a4975b04dd5652ae", sigScript, "0000000000000000000000000000000000000000000000000000000000000000", 100000, pub_key_P2SH_P2WSH)
    print(signed_transaction)
    # signature script is 256sha hash of witness script
    return signed_transaction


I don’t understand, but do signatures come out the same way in any way every time? I checked multiple times with different sources, but that doesn’t answer anything

I’m trying to build a P2SH-P2WSH transaction from scratch. Could someone help me debug the above implementation?

]]>
https://earlybirdsinvest.com/cant-get-the-signature-of-p2sh-p2wsh-nested-2-correctly-in-two-multisig-scripts/feed/ 0 20923
Unable to generate address after importing Taproot Multisig descriptor https://earlybirdsinvest.com/unable-to-generate-address-after-importing-taproot-multisig-descriptor/ https://earlybirdsinvest.com/unable-to-generate-address-after-importing-taproot-multisig-descriptor/#respond Mon, 10 Feb 2025 22:58:00 +0000 https://earlybirdsinvest.com/unable-to-generate-address-after-importing-taproot-multisig-descriptor/

There are three wallets to use to create a Taproot Multisig wallet. All of my work is based on this https://github.com/bitcoin/bitcoin/blob/master/doc/multisig-tutorial.md. The external and internal Xpubs for each are as follows:

Wallet 1 (External + Internal Xpubs)

(11776e3b/86h/1h/0h)tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/0/*
(11776e3b/86h/1h/0h)tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/1/*

Wallet 2 (External + Internal Xpubs)

(fe5187e5/86h/1h/0h)tpubDCqr5GVKeptzMG5QKLu1aQKXFXgF6kMy9dYDQ6Nap6emZ3iziMCeVX1pPjEzA7nTmyZS9NP2KjUsGtEs8jNqFcUTpKxAwXPB3yfbee4RthM/0/*
(fe5187e5/86h/1h/0h)tpubDCqr5GVKeptzMG5QKLu1aQKXFXgF6kMy9dYDQ6Nap6emZ3iziMCeVX1pPjEzA7nTmyZS9NP2KjUsGtEs8jNqFcUTpKxAwXPB3yfbee4RthM/1/*

Wallet 3 (External + Internal Xpubs)

(9f5cbc68/86h/1h/0h)tpubDDQbi15GQjXYxhAysxdEC6VsSFacJ6hgDAJ7oQy4wUs9sfwMQWtcLqLx7GUbBfWyVwUYMEEJtWmxFXmpmjQL8X4cRdgAJ7BcaazuCYq4iCp/0/*
(9f5cbc68/86h/1h/0h)tpubDDQbi15GQjXYxhAysxdEC6VsSFacJ6hgDAJ7oQy4wUs9sfwMQWtcLqLx7GUbBfWyVwUYMEEJtWmxFXmpmjQL8X4cRdgAJ7BcaazuCYq4iCp/1/*

Here is my descriptor:

external_desc="tr(tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/1/*,sortedmulti_a(2,tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/0/*,tpubDCqr5GVKeptzMG5QKLu1aQKXFXgF6kMy9dYDQ6Nap6emZ3iziMCeVX1pPjEzA7nTmyZS9NP2KjUsGtEs8jNqFcUTpKxAwXPB3yfbee4RthM/0/*,tpubDDQbi15GQjXYxhAysxdEC6VsSFacJ6hgDAJ7oQy4wUs9sfwMQWtcLqLx7GUbBfWyVwUYMEEJtWmxFXmpmjQL8X4cRdgAJ7BcaazuCYq4iCp/0/*))#546p4cqh"

For the first discussion of tr Uses and uses the internal Xpub of wallet 1 sortedmulti_a To configure 2-3 using an external one. I’ll call getdescriptorinfo Instructions:

 ./build/src/bitcoin-cli -signet getdescriptorinfo $external_desc
{
  "descriptor": "tr(tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/1/*,sortedmulti_a(2,tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/0/*,tpubDCqr5GVKeptzMG5QKLu1aQKXFXgF6kMy9dYDQ6Nap6emZ3iziMCeVX1pPjEzA7nTmyZS9NP2KjUsGtEs8jNqFcUTpKxAwXPB3yfbee4RthM/0/*,tpubDDQbi15GQjXYxhAysxdEC6VsSFacJ6hgDAJ7oQy4wUs9sfwMQWtcLqLx7GUbBfWyVwUYMEEJtWmxFXmpmjQL8X4cRdgAJ7BcaazuCYq4iCp/0/*))#546p4cqh",
  "checksum": "546p4cqh",
  "isrange": true,
  "issolvable": true,
  "hasprivatekeys": false
}

It then uses that descriptor to construct the descriptor that is used to import JSON into your wallet. This is what I used to create the JSON:

external_desc_sum=$(./build/src/bitcoin-cli -signet getdescriptorinfo $external_desc | jq '.descriptor')
multisig_ext_desc="({\"desc\": $external_desc_sum, \"timestamp\": \"now\"})"

After that I call it importdescriptors New blank wallet way:

./build/src/bitcoin-cli -signet -named createwallet wallet_name="multi_tr" disable_private_keys=true blank=true
./build/src/bitcoin-cli -signet -rpcwallet="multi_tr" importdescriptors "$multisig_ext_desc"
./build/src/bitcoin-cli -signet -rpcwallet="multi_tr" getwalletinfo

The following is the response for the import descriptor:

{
  "name": "multi_tr"
}
(
  {
    "success": true,
    "warnings": (
      "Range not given, using default keypool range"
    )
  }
)

The output from Get Wallet Info is as follows:

{
  "walletname": "multi_tr",
  "walletversion": 169900,
  "format": "sqlite",
  "balance": 0.00000000,
  "unconfirmed_balance": 0.00000000,
  "immature_balance": 0.00000000,
  "txcount": 0,
  "keypoolsize": 0,
  "keypoolsize_hd_internal": 0,
  "paytxfee": 0.00000000,
  "private_keys_enabled": false,
  "avoid_reuse": false,
  "scanning": false,
  "descriptors": true,
  "external_signer": false,
  "blank": true,
  "birthtime": 1739107662,
  "lastprocessedblock": {
    "hash": "0000005ba71046c3e13011955cf5a65c09fc7e945030a3d623dbfef8e7b3dce6",
    "height": 234655
  }
}

After seeing this output I was excited and wanted to generate a new address to fund a multi-sig wallet, but I got an error.

./build/src/bitcoin-cli  -signet -rpcwallet="multi_tr" getnewaddress
error code: -4
error message:
Error: This wallet has no available keys

After searching for a replacement I found it deriveaddresses The method worked in my use case and was able to get some addresses.

./build/src/bitcoin-cli  -signet deriveaddresses "tr(tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/1/*,sortedmulti_a(2,tpubDCTp9moNmiVHK9KS6j6HEyU9duvomZrE87wTNQMkcZktDu89f3yJFATEQovpsT8KwUDWhut5YYd3zNsUYuv6sGHLozsub1AHPoyL7uGW2LT/0/*,tpubDCqr5GVKeptzMG5QKLu1aQKXFXgF6kMy9dYDQ6Nap6emZ3iziMCeVX1pPjEzA7nTmyZS9NP2KjUsGtEs8jNqFcUTpKxAwXPB3yfbee4RthM/0/*,tpubDDQbi15GQjXYxhAysxdEC6VsSFacJ6hgDAJ7oQy4wUs9sfwMQWtcLqLx7GUbBfWyVwUYMEEJtWmxFXmpmjQL8X4cRdgAJ7BcaazuCYq4iCp/0/*))#546p4cqh" "(0,2)"
(
  "tb1pg0p5p2vfqn3stjrrz0ga33m4wudcxmsl4qsuv4csnq5lxfnws3zss5xcvh",
  "tb1p4z6n9hlt2rs9arlaxwkcgpp79803rmle6wty946zwce74u4wnmas4r8etx",
  "tb1pk3nj9xt2aempeys63etmw3zfkj8pya0sr2lcl2spf6xqtjev8zfqkfzg5p"
)

My question is:

  • Why the first way generatenewaddress Is it not working?
  • is deriveaddresses What is the recommended method for general use? If so, I think you need to save the range of use to generate a new address each time (as using the same range will generate the same address). So if you use the range (0,0), you must use the next time (1,1).

thank you

]]>
https://earlybirdsinvest.com/unable-to-generate-address-after-importing-taproot-multisig-descriptor/feed/ 0 18699