コード例 #1
0
    def test_mutable_tx_creation_with_immutable_parts_specified(self):
        tx = CMutableTransaction(
            vin=[CTxIn(prevout=COutPoint(hash=b'a' * 32, n=0))],
            vout=[CTxOut(nValue=1)],
            witness=CTxWitness([CTxInWitness()]))

        def check_mutable_parts(tx):
            self.assertTrue(tx.vin[0].is_mutable())
            self.assertTrue(tx.vin[0].prevout.is_mutable())
            self.assertTrue(tx.vout[0].is_mutable())
            self.assertTrue(tx.wit.is_mutable())
            self.assertTrue(tx.wit.vtxinwit[0].is_mutable())

        check_mutable_parts(tx)

        # Test that if we deserialize with CMutableTransaction,
        # all the parts are mutable
        tx = CMutableTransaction.deserialize(tx.serialize())
        check_mutable_parts(tx)

        # Test some parts separately, because when created via
        # CMutableTransaction instantiation, they are created with from_*
        # methods, and not directly

        txin = CMutableTxIn(prevout=COutPoint(hash=b'a' * 32, n=0))
        self.assertTrue(txin.prevout.is_mutable())

        wit = CMutableTxWitness((CTxInWitness(), ))
        self.assertTrue(wit.vtxinwit[0].is_mutable())
コード例 #2
0
def sign_input(tx, input_index, utxo):
    """Sign an input of transaction.
    Single-signature signing with SIGHASH_ALL"""

    key = utxo['key']
    src_addr = CCoinAddress(utxo['address'])

    script_for_sighash = CScript(
        [OP_DUP, OP_HASH160,
         Hash160(key.pub), OP_EQUALVERIFY, OP_CHECKSIG])

    assert isinstance(src_addr, (P2PKHCoinAddress, P2SHCoinAddress,
                                 P2WPKHCoinAddress)),\
        'only p2pkh, p2wpkh and p2sh_p2wpkh addresses are supported'

    if isinstance(src_addr, P2PKHCoinAddress):
        sigversion = SIGVERSION_BASE
    else:
        sigversion = SIGVERSION_WITNESS_V0

    if 'amountcommitment' in utxo:
        amountcommitment = CConfidentialValue(x(utxo['amountcommitment']))
    else:
        amountcommitment = CConfidentialValue(coins_to_satoshi(utxo['amount']))

    sighash = script_for_sighash.sighash(tx,
                                         input_index,
                                         SIGHASH_ALL,
                                         amount=amountcommitment,
                                         sigversion=sigversion)

    sig = key.sign(sighash) + bytes([SIGHASH_ALL])

    if isinstance(src_addr, P2PKHCoinAddress):
        tx.vin[input_index].scriptSig = CScript(
            [CScript(sig), CScript(key.pub)])
        scriptpubkey = src_addr.to_scriptPubKey()
    elif isinstance(src_addr, P2WPKHCoinAddress):
        tx.vin[input_index].scriptSig = CScript()
        tx.wit.vtxinwit[input_index] = CTxInWitness(
            CScriptWitness([CScript(sig), CScript(key.pub)]))
        scriptpubkey = src_addr.to_scriptPubKey()
    else:
        # Assume that this is p2sh-wrapped p2wpkh address
        inner_scriptPubKey = CScript([0, Hash160(key.pub)])
        tx.vin[input_index].scriptSig = CScript([inner_scriptPubKey])
        tx.wit.vtxinwit[input_index] = CTxInWitness(
            CScriptWitness([CScript(sig), CScript(key.pub)]))
        scriptpubkey = inner_scriptPubKey.to_p2sh_scriptPubKey()

    VerifyScript(tx.vin[input_index].scriptSig,
                 scriptpubkey,
                 tx,
                 input_index,
                 amount=amountcommitment,
                 flags=(SCRIPT_VERIFY_P2SH, ))
コード例 #3
0
    def test_repr(self):
        def T(txout, expected):
            actual = repr(txout)
            self.assertEqual(actual, expected)

        T(CTxInWitness(CScriptWitness([1])),
          "CBitcoinTxInWitness(CScriptWitness([x('01')]))")
コード例 #4
0
    def test_repr(self) -> None:
        def T(txinwitness: CTxInWitness, expected: str) -> None:
            actual = repr(txinwitness)
            self.assertEqual(actual, expected)

        T(CTxInWitness(CScriptWitness([1])),
          "CBitcoinTxInWitness(CScriptWitness([x('01')]))")
コード例 #5
0
def generate_transaction(amount, txin_txid, txin_vout, txout_addr,
                         redeem_list):
    txin = CMutableTxIn(COutPoint(txin_txid, txin_vout))
    txout = CMutableTxOut(amount * COIN, txout_addr.addr.to_scriptPubKey())
    witness_script = CScriptWitness(tuple(redeem_list))
    witness = CTxWitness(tuple([CTxInWitness(witness_script)]))
    tx = CMutableTransaction(vin=[txin], vout=[txout], witness=witness)
    return tx
コード例 #6
0
 def create_test_txs(self, scriptSig, scriptPubKey, witness, nValue):
     txCredit = CTransaction([CTxIn(COutPoint(), CScript([OP_0, OP_0]), nSequence=0xFFFFFFFF)],
                             [CTxOut(nValue, scriptPubKey)],
                             witness=CTxWitness(),
                             nLockTime=0, nVersion=1)
     txSpend = CTransaction([CTxIn(COutPoint(txCredit.GetTxid(), 0), scriptSig, nSequence=0xFFFFFFFF)],
                            [CTxOut(nValue, CScript())],
                            nLockTime=0, nVersion=1,
                            witness=CTxWitness([CTxInWitness(witness)]))
     return (txCredit, txSpend)
コード例 #7
0
def create_btc_spend_tx(dst_addr,
                        txid,
                        vout_n,
                        btc_contract,
                        spend_key=None,
                        branch_condition=True):

    # In real application, the fees should not be static, of course
    out_amount = (coins_to_satoshi(pre_agreed_amount) -
                  coins_to_satoshi(fixed_fee_amount))

    tx = CMutableTransaction(
        vin=[CTxIn(prevout=COutPoint(hash=lx(txid), n=vout_n))],
        vout=[
            CTxOut(nValue=out_amount, scriptPubKey=dst_addr.to_scriptPubKey())
        ])

    if branch_condition is True:
        cond = b'\x01'
    else:
        tx.vin[0].nSequence = bitcoin_contract_timeout
        cond = b''

    in_amount = coins_to_satoshi(pre_agreed_amount)
    # We used P2WSHCoinAddress to create the address that we sent bitcoin to,
    # so we know that we need to use SIGVERSION_WITNESS_V0
    sighash = btc_contract.sighash(tx,
                                   0,
                                   SIGHASH_ALL,
                                   amount=in_amount,
                                   sigversion=SIGVERSION_WITNESS_V0)

    spend_sig = spend_key.sign(sighash) + bytes([SIGHASH_ALL])

    # This is script witness, not script. The condition for OP_IF
    # in our script is directly encoded as data in the witness.
    # We cannot use OP_TRUE/OP_FALSE here. We use DATA guard is to ensure that.
    witness = CScriptWitness([spend_sig, DATA(cond), btc_contract])

    # empty scriptSig, because segwit
    tx.vin[0].scriptSig = CBitcoinScript([])
    # all data to check the spend conditions is in the witness
    tx.wit.vtxinwit[0] = CTxInWitness(witness)

    # Cannot use VerifyScript for now,
    # because it does not support CHECKSEQUENCEVERIFY yet
    #
    # from_addr = P2WSHBitcoinAddress.from_redeemScript(btc_contract)
    # VerifyScript(tx.vin[0].scriptSig, from_addr.to_scriptPubKey(),
    #              tx, 0, amount=in_amount)

    return tx
コード例 #8
0
def sign_transaction(tx, privkeys):
    witness_list = list(tx.witness.vtxinwit[0].scriptWitness.stack)
    sighash = SignatureHash(tx.witness, tx, 0, SIGHASH_ALL)
    signatures = []
    for privkey in privkeys:
        privkey = CBitcoinSecret.from_bytes(privkey)
    for privkey in privkeys:
        signatures.append(privkey.sign(sighash) + bytes([SIGHASH_ALL]))
    counter = 0
    for signature in signatures:
        witness_list.insert(counter, signature)
        counter = counter + 1
    witness_script = CScriptWitness(tuple(witness_list))
    tx.witness = CTxWitness(tuple([CTxInWitness(witness_script)]))
    return tx.serialize()
コード例 #9
0
        def T(required: int,
              total: int,
              alt_total: Optional[int] = None) -> None:
            amount = 10000
            keys = [
                CKey.from_secret_bytes(os.urandom(32)) for _ in range(total)
            ]
            pubkeys = [k.pub for k in keys]

            if alt_total is not None:
                total = alt_total  # for assertRaises checks

            redeem_script = standard_multisig_redeem_script(total=total,
                                                            required=required,
                                                            pubkeys=pubkeys)

            # Test with P2SH

            scriptPubKey = redeem_script.to_p2sh_scriptPubKey()

            (_, tx) = self.create_test_txs(CScript(), scriptPubKey,
                                           CScriptWitness([]), amount)

            tx = tx.to_mutable()

            sighash = redeem_script.sighash(tx,
                                            0,
                                            SIGHASH_ALL,
                                            amount=amount,
                                            sigversion=SIGVERSION_BASE)

            sigs = [
                k.sign(sighash) + bytes([SIGHASH_ALL]) for k in keys[:required]
            ]

            tx.vin[0].scriptSig = CScript(
                standard_multisig_witness_stack(sigs, redeem_script))

            VerifyScript(tx.vin[0].scriptSig, scriptPubKey, tx, 0,
                         (SCRIPT_VERIFY_P2SH, ))

            # Test with P2WSH

            scriptPubKey = redeem_script.to_p2wsh_scriptPubKey()

            (_, tx) = self.create_test_txs(CScript(), scriptPubKey,
                                           CScriptWitness([]), amount)

            tx = tx.to_mutable()

            sighash = redeem_script.sighash(tx,
                                            0,
                                            SIGHASH_ALL,
                                            amount=amount,
                                            sigversion=SIGVERSION_WITNESS_V0)

            sigs = [
                k.sign(sighash) + bytes([SIGHASH_ALL]) for k in keys[:required]
            ]

            witness_stack = standard_multisig_witness_stack(
                sigs, redeem_script)
            tx.vin[0].scriptSig = CScript([])
            tx.wit.vtxinwit[0] = CTxInWitness(
                CScriptWitness(witness_stack)).to_mutable()

            VerifyScript(tx.vin[0].scriptSig,
                         scriptPubKey,
                         tx,
                         0,
                         flags=(SCRIPT_VERIFY_WITNESS, SCRIPT_VERIFY_P2SH),
                         amount=amount,
                         witness=tx.wit.vtxinwit[0].scriptWitness)

            # Test with P2SH_P2WSH

            scriptPubKey = redeem_script.to_p2wsh_scriptPubKey()

            (_, tx) = self.create_test_txs(CScript(), scriptPubKey,
                                           CScriptWitness([]), amount)

            tx = tx.to_mutable()

            sighash = redeem_script.sighash(tx,
                                            0,
                                            SIGHASH_ALL,
                                            amount=amount,
                                            sigversion=SIGVERSION_WITNESS_V0)

            sigs = [
                k.sign(sighash) + bytes([SIGHASH_ALL]) for k in keys[:required]
            ]

            witness_stack = standard_multisig_witness_stack(
                sigs, redeem_script)
            tx.vin[0].scriptSig = CScript([scriptPubKey])
            tx.wit.vtxinwit[0] = CTxInWitness(
                CScriptWitness(witness_stack)).to_mutable()

            VerifyScript(tx.vin[0].scriptSig,
                         scriptPubKey.to_p2sh_scriptPubKey(),
                         tx,
                         0,
                         flags=(SCRIPT_VERIFY_WITNESS, SCRIPT_VERIFY_P2SH),
                         amount=amount,
                         witness=tx.wit.vtxinwit[0].scriptWitness)
コード例 #10
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"
コード例 #11
0
    script_for_sighash = CScript(
        [OP_DUP, OP_HASH160,
         Hash160(key.pub), OP_EQUALVERIFY, OP_CHECKSIG])

    sighash = script_for_sighash.sighash(tx,
                                         input_index,
                                         SIGHASH_ALL,
                                         amount=utxo.nValue,
                                         sigversion=SIGVERSION_WITNESS_V0)

    sig = key.sign(sighash) + bytes([SIGHASH_ALL])

    inner_scriptPubKey = CScript([0, Hash160(key.pub)])
    tx.vin[input_index].scriptSig = CScript([inner_scriptPubKey])
    tx.wit.vtxinwit[input_index] = CTxInWitness(
        CScriptWitness([CScript(sig), CScript(key.pub)]))
    scriptpubkey = inner_scriptPubKey.to_p2sh_scriptPubKey()

    VerifyScript(tx.vin[input_index].scriptSig,
                 scriptpubkey,
                 tx,
                 input_index,
                 amount=utxo.nValue,
                 flags=(SCRIPT_VERIFY_P2SH, ))

    sys.stderr.write("Successfully signed\n")

    # Print out blinded and signed transaction, hex-encoded.
    print(b2x(tx.serialize()))
コード例 #12
0
 def test_clone(self):
     txinwit = CTxInWitness(CScriptWitness([1]))
     self.assertEqual(txinwit.serialize(), txinwit.clone().serialize())
コード例 #13
0
 def test_immutable(self):
     wit = CTxInWitness(CScriptWitness([1]))
     with self.assertRaises(AttributeError):
         wit.scriptWitness = CScriptWitness()
コード例 #14
0
 def test_clone(self):
     wit = CMutableTxWitness([CTxInWitness(CScriptWitness([1]))])
     self.assertEqual(wit.serialize(), wit.clone().serialize())
コード例 #15
0
 def test_immutable(self):
     wit = CTxWitness([CTxInWitness(CScriptWitness([1]))])
     with self.assertRaises(AttributeError):
         wit.vtxinwit = []
コード例 #16
0
    def _create_transaction(self, sources: List[Address],
                            recipients: List[Address], values, n_locktime,
                            n_sequence):
        # save cospends
        self.cospends.union_all([str(x.address) for x in sources])

        if not values:
            values = [recipient.value for recipient in recipients]
        tx_ins = [
            CMutableTxIn(COutPoint(source.txid, source.vout),
                         nSequence=n_sequence) for source in sources
        ]
        tx_outs = []

        cnt = 0
        for recipient, value in zip(recipients, values):
            if value == 0:
                self.log.warning("Creating output with 0 BTC")
            recipient.vout = cnt

            tx_outs.append(
                CMutableTxOut(
                    Coin(value).satoshi(),
                    recipient.address.to_scriptPubKey()))
            cnt += 1

        tx = CMutableTransaction(tx_ins, tx_outs, nLockTime=n_locktime)

        in_idx = 0
        witnesses = []
        for txin, source in zip(tx_ins, sources):
            key = source.key

            if source.type == 'p2pkh':
                script = source.address.to_redeemScript()
            elif source.type == 'p2sh':
                script = CScript([key.pub, OP_CHECKSIG])
            elif source.type == 'p2wpkh':
                script = source.address.to_redeemScript()
            elif source.type == 'p2wsh':
                script = source.witness_program
            else:
                raise UnsupportedAddressTypeError()

            # Create signature
            amount = Coin(source.value).satoshi()
            sig = self._sign(script, tx, in_idx, amount, key, source.type)

            # Add signature to input or witness
            if source.type == 'p2pkh':
                txin.scriptSig = CScript([sig, key.pub])
                witnesses.append(CTxInWitness())
            elif source.type == 'p2sh':
                txin.scriptSig = CScript([sig, script])
                witnesses.append(CTxInWitness())
            elif source.type == 'p2wpkh':
                txin.scriptSig = CScript()
                witnesses.append(CTxInWitness(CScriptWitness([sig, key.pub])))
            elif source.type == 'p2wsh':
                txin.scriptSig = CScript()
                witnesses.append(CTxInWitness(CScriptWitness([sig, script])))
            in_idx += 1

        tx.wit = CTxWitness(witnesses)
        return tx