예제 #1
0
 def test_get_output_size(self) -> None:
     pub = CPubKey(x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71'))
     a0 = P2PKHCoinAddress.from_pubkey(pub)
     self.assertEqual(P2PKHCoinAddress.get_output_size(), 34)
     self.assertEqual(a0.get_output_size(), 34)
     a1 = P2WPKHCoinAddress.from_pubkey(pub)
     self.assertEqual(P2WPKHCoinAddress.get_output_size(), 31)
     self.assertEqual(a1.get_output_size(), 31)
     a2 = P2SHCoinAddress.from_redeemScript(
         CScript(b'\xa9' + Hash160(pub) + b'\x87'))
     self.assertEqual(P2SHCoinAddress.get_output_size(), 32)
     self.assertEqual(a2.get_output_size(), 32)
     a3 = P2WSHCoinAddress.from_redeemScript(
         CScript(b'\xa9' + Hash160(pub) + b'\x87'))
     self.assertEqual(P2WSHCoinAddress.get_output_size(), 43)
     self.assertEqual(a3.get_output_size(), 43)
예제 #2
0
def pubkey_to_p2wpkh_script(pub):
    """
    Given a pubkey in bytes (compressed), return a CScript
    representing the corresponding pay-to-witness-pubkey-hash
    scriptPubKey.
    """
    return P2WPKHCoinAddress.from_pubkey(pub).to_scriptPubKey()
예제 #3
0
def get_unconfidential_address_samples(pub1, pub2):
    return AddressSamples(
        p2pkh=P2PKHCoinAddress.from_pubkey(pub1),
        p2wpkh=P2WPKHCoinAddress.from_pubkey(pub1),
        p2sh=P2SHCoinAddress.from_redeemScript(
            CScript(b'\xa9' + Hash160(pub1) + b'\x87')),
        p2wsh=P2WSHCoinAddress.from_redeemScript(
            CScript(b'\xa9' + Hash160(pub1) + b'\x87')),
        conf_p2pkh=P2PKHCoinConfidentialAddress.from_unconfidential(
            P2PKHCoinAddress.from_pubkey(pub1), pub2),
        conf_p2wpkh=P2WPKHCoinConfidentialAddress.from_unconfidential(
            P2WPKHCoinAddress.from_pubkey(pub1), pub2),
        conf_p2sh=P2SHCoinConfidentialAddress.from_unconfidential(
            P2SHCoinAddress.from_redeemScript(
                CScript(b'\xa9' + Hash160(pub1) + b'\x87')), pub2),
        conf_p2wsh=P2WSHCoinConfidentialAddress.from_unconfidential(
            P2WSHCoinAddress.from_redeemScript(
                CScript(b'\xa9' + Hash160(pub1) + b'\x87')), pub2))
예제 #4
0
 def derive_address(self):
     bip_keypath = HDKeyPath(self.key_path[:BIP_KEYPATH_INDEX])
     if bip_keypath == bip_44_keypath():
         self._address = P2PKHAddress.from_pubkey(self.pub_key)
     elif bip_keypath == bip_84_keypath():
         self._address = P2WPKHAddress.from_pubkey(self.pub_key)
     elif bip_keypath == bip_49_keypath():
         self._address = WalletAddress.make_wrapped_segwit_address(
             self.pub_key)
     else:
         raise Exception
예제 #5
0
    def test_sighash(self) -> None:
        spent_amount = 1100
        pub = CKey.from_secret_bytes(os.urandom(32)).pub
        spk_legacy = P2PKHCoinAddress.from_pubkey(pub).to_scriptPubKey()
        spk_segwit = P2WPKHCoinAddress.from_pubkey(pub).to_scriptPubKey()

        tx = CTransaction([
            CTxIn(
                COutPoint(b'\x00' * 32, 0), CScript([]), nSequence=0xFFFFFFFF)
        ], [CTxOut(1000, spk_legacy)],
                          nLockTime=0,
                          nVersion=1)

        # no exceptions should be raised with these two calls
        spk_legacy.sighash(tx,
                           0,
                           SIGHASH_ALL,
                           amount=spent_amount,
                           sigversion=SIGVERSION_WITNESS_V0)
        spk_segwit.sighash(tx,
                           0,
                           SIGHASH_ALL,
                           amount=spent_amount,
                           sigversion=SIGVERSION_WITNESS_V0)

        with self.assertRaises(ValueError):
            # unknown sigversion
            spk_segwit.sighash(tx,
                               0,
                               SIGHASH_ALL,
                               amount=spent_amount,
                               sigversion=SIGVERSION_WITNESS_V0 +
                               1)  # type: ignore

        assert spk_segwit.is_witness_scriptpubkey()
        with self.assertRaises(ValueError):
            # incorect sigversion for segwit
            spk_segwit.sighash(tx,
                               0,
                               SIGHASH_ALL,
                               amount=spent_amount,
                               sigversion=SIGVERSION_BASE)

        with self.assertRaises(ValueError):
            # inIdx > len(tx.vin) - non-raw sighash function should raise
            # ValueError (raw_sighash can return HASH_ONE)
            spk_legacy.sighash(tx,
                               10,
                               SIGHASH_ALL,
                               amount=spent_amount,
                               sigversion=SIGVERSION_BASE)
예제 #6
0
 async def async_regtest() -> None:
     select_chain_params('bitcoin/regtest')
     a = P2WPKHCoinAddress.from_pubkey(pub)
     witver, data = bitcointx.segwit_addr.decode(
         P2WPKHBitcoinRegtestAddress.bech32_hrp, str(a))
     assert witver == 0
     assert data == Hash160(pub)
     check_core_modules()
     ready('regtest')
     await wait_async('testnet')
     await wait_async('mainnet')
     self.assertEqual(get_current_chain_params().NAME,
                      'bitcoin/regtest')
     finish('regtest')
예제 #7
0
def sign(tx, i, priv, hashcode=SIGHASH_ALL, amount=None, native=False):
    """
    Given a transaction tx of type CMutableTransaction, an input index i,
    and a raw privkey in bytes, updates the CMutableTransaction to contain
    the newly appended signature.
    Only four scriptPubKey types supported: p2pkh, p2wpkh, p2sh-p2wpkh, p2wsh.
    Note that signing multisig must be done outside this function, using
    the wrapped library.
    If native is not the default (False), and if native != "p2wpkh",
    then native must be a CScript object containing the redeemscript needed to sign.
    Returns: (signature, "signing succeeded")
    or: (None, errormsg) in case of failure
    """
    # script verification flags
    flags = set([SCRIPT_VERIFY_STRICTENC])

    def return_err(e):
        return None, "Error in signing: " + repr(e)

    assert isinstance(tx, CMutableTransaction)

    pub = privkey_to_pubkey(priv)

    if not amount:
        # p2pkh only supported here:
        input_scriptPubKey = pubkey_to_p2pkh_script(pub)
        sighash = SignatureHash(input_scriptPubKey, tx, i, hashcode)
        try:
            sig = ecdsa_raw_sign(sighash, priv, rawmsg=True) + bytes(
                [hashcode])
        except Exception as e:
            return return_err(e)
        tx.vin[i].scriptSig = CScript([sig, pub])
        # Verify the signature worked.
        try:
            VerifyScript(tx.vin[i].scriptSig,
                         input_scriptPubKey,
                         tx,
                         i,
                         flags=flags)
        except Exception as e:
            return return_err(e)
        return sig, "signing succeeded"

    else:
        # segwit case; we currently support p2wpkh native or under p2sh.

        # https://github.com/Simplexum/python-bitcointx/blob/648ad8f45ff853bf9923c6498bfa0648b3d7bcbd/bitcointx/core/scripteval.py#L1250-L1252
        flags.add(SCRIPT_VERIFY_P2SH)

        if native and native != "p2wpkh":
            scriptCode = native
            input_scriptPubKey = redeem_script_to_p2wsh_script(native)
        else:
            # this covers both p2wpkh and p2sh-p2wpkh case:
            input_scriptPubKey = pubkey_to_p2wpkh_script(pub)
            # only created for convenience access to scriptCode:
            input_address = P2WPKHCoinAddress.from_scriptPubKey(
                input_scriptPubKey)
            # function name is misleading here; redeemScript only applies to p2sh.
            scriptCode = input_address.to_redeemScript()

        sighash = SignatureHash(scriptCode,
                                tx,
                                i,
                                hashcode,
                                amount=amount,
                                sigversion=SIGVERSION_WITNESS_V0)
        try:
            sig = ecdsa_raw_sign(sighash, priv, rawmsg=True) + bytes(
                [hashcode])
        except Exception as e:
            return return_err(e)
        if native:
            flags.add(SCRIPT_VERIFY_WITNESS)
        else:
            tx.vin[i].scriptSig = CScript([input_scriptPubKey])

        if native and native != "p2wpkh":
            witness = [sig, scriptCode]
        else:
            witness = [sig, pub]
        ctxwitness = CTxInWitness(CScriptWitness(witness))
        tx.wit.vtxinwit[i] = ctxwitness
        # Verify the signature worked.
        try:
            VerifyScript(tx.vin[i].scriptSig,
                         input_scriptPubKey,
                         tx,
                         i,
                         flags=flags,
                         amount=amount,
                         witness=tx.wit.vtxinwit[i].scriptWitness)
        except ValidationError as e:
            return return_err(e)

        return sig, "signing succeeded"
예제 #8
0
 def make_wrapped_segwit_redeem_script(address_pubkey):
     return P2WPKHAddress.from_pubkey(address_pubkey).to_scriptPubKey()