Exemple #1
0
    def test_script(self) -> None:
        for t in load_test_vectors('script_tests.json'):
            (scriptSig, scriptPubKey, witness, nValue, flags, expected_result,
             comment, test_case) = t
            (txCredit, txSpend) = self.create_test_txs(scriptSig, scriptPubKey,
                                                       witness, nValue)

            try:
                VerifyScript(scriptSig,
                             scriptPubKey,
                             txSpend,
                             0,
                             flags,
                             amount=nValue,
                             witness=witness)
            except ValidationError as err:
                if expected_result == 'OK':
                    self.fail(
                        'Script FAILED: %r %r %r with exception %r\n\nTest data: %r'
                        % (scriptSig, scriptPubKey, comment, err, test_case))
                continue

            if expected_result != 'OK':
                self.fail('Expected %r to fail (%s)' %
                          (test_case, expected_result))
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, ))
    def check_sign(self, blinded_tx: CTransaction, signed_tx: CTransaction,
                   bundle: Dict[str, Any]) -> None:
        tx_to_sign = blinded_tx.to_mutable()
        for n, vin in enumerate(tx_to_sign.vin):
            utxo = bundle['vin_utxo'][n]
            amount = -1 if utxo['amount'] == -1 else coins_to_satoshi(
                utxo['amount'])

            scriptPubKey = CScript(x(utxo['scriptPubKey']))
            a = CCoinAddress(utxo['address'])
            if 'privkey' in utxo:
                privkey = CCoinKey(utxo['privkey'])
                assert isinstance(a, P2PKHCoinAddress),\
                    "only P2PKH is supported for single-sig"
                assert a == P2PKHElementsAddress.from_pubkey(privkey.pub)
                assert scriptPubKey == a.to_scriptPubKey()
                sighash = SignatureHash(scriptPubKey,
                                        tx_to_sign,
                                        n,
                                        SIGHASH_ALL,
                                        amount=amount,
                                        sigversion=SIGVERSION_BASE)
                sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
                tx_to_sign.vin[n].scriptSig = CScript(
                    [CScript(sig), CScript(privkey.pub)])
            else:
                pk_list = [CCoinKey(pk) for pk in utxo['privkey_list']]
                redeem_script_data = [utxo['num_p2sh_participants']]
                redeem_script_data.extend([pk.pub for pk in pk_list])
                redeem_script_data.extend([len(pk_list), OP_CHECKMULTISIG])
                redeem_script = CScript(redeem_script_data)
                assert isinstance(a, P2SHCoinAddress),\
                    "only P2SH is supported for multi-sig."
                assert scriptPubKey == redeem_script.to_p2sh_scriptPubKey()
                assert a == P2SHElementsAddress.from_scriptPubKey(
                    redeem_script.to_p2sh_scriptPubKey())
                sighash = SignatureHash(redeem_script,
                                        tx_to_sign,
                                        n,
                                        SIGHASH_ALL,
                                        amount=amount,
                                        sigversion=SIGVERSION_BASE)
                sigs = [
                    pk.sign(sighash) + bytes([SIGHASH_ALL]) for pk in pk_list
                ]
                tx_to_sign.vin[n].scriptSig = CScript([b''] + sigs +
                                                      [redeem_script])

            VerifyScript(tx_to_sign.vin[n].scriptSig,
                         scriptPubKey,
                         tx_to_sign,
                         n,
                         amount=amount)

        self.assertEqual(tx_to_sign.serialize(), signed_tx.serialize())
Exemple #4
0
def verify_tx_input(tx, i, scriptSig, scriptPubKey, amount=None, witness=None):
    flags = set([SCRIPT_VERIFY_STRICTENC])
    if witness:
        # https://github.com/Simplexum/python-bitcointx/blob/648ad8f45ff853bf9923c6498bfa0648b3d7bcbd/bitcointx/core/scripteval.py#L1250-L1252
        flags.add(SCRIPT_VERIFY_P2SH)
        flags.add(SCRIPT_VERIFY_WITNESS)
    try:
        VerifyScript(scriptSig, scriptPubKey, tx, i,
                 flags=flags, amount=amount, witness=witness)
    except ValidationError as e:
        return False
    return True
    def test_tx_invalid(self):
        for prevouts, tx, enforceP2SH in load_test_vectors('tx_invalid.json'):
            try:
                CheckTransaction(tx)
            except CheckTransactionError:
                continue

            with self.assertRaises(ValidationError):
                for i in range(len(tx.vin)):
                    flags = set()
                    if enforceP2SH:
                        flags.add(SCRIPT_VERIFY_P2SH)

                    VerifyScript(tx.vin[i].scriptSig,
                                 prevouts[tx.vin[i].prevout],
                                 tx,
                                 i,
                                 flags=flags)
    def test_tx_valid(self):
        for prevouts, tx, enforceP2SH in load_test_vectors('tx_valid.json'):
            try:
                CheckTransaction(tx)
            except CheckTransactionError:
                self.fail('tx failed CheckTransaction(): ' \
                        + str((prevouts, b2x(tx.serialize()), enforceP2SH)))
                continue

            for i in range(len(tx.vin)):
                flags = set()
                if enforceP2SH:
                    flags.add(SCRIPT_VERIFY_P2SH)

                VerifyScript(tx.vin[i].scriptSig,
                             prevouts[tx.vin[i].prevout],
                             tx,
                             i,
                             flags=flags)
Exemple #7
0
def verify_tx_input(tx,
                    i,
                    scriptSig,
                    scriptPubKey,
                    amount=None,
                    witness=None,
                    native=False):
    flags = set([SCRIPT_VERIFY_STRICTENC])
    if witness:
        flags.add(SCRIPT_VERIFY_P2SH)
    if native:
        flags.add(SCRIPT_VERIFY_WITNESS)
    try:
        VerifyScript(scriptSig,
                     scriptPubKey,
                     tx,
                     i,
                     flags=flags,
                     amount=amount,
                     witness=witness)
    except ValidationError as e:
        return False
    return True
Exemple #8
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)
Exemple #9
0
txin_scriptPubKey = \
    P2PKHBitcoinAddress.from_pubkey(seckey.pub).to_scriptPubKey()

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    0.001 * COIN,
    CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction.
sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, seckey.pub])

# Verify the signature worked. This calls EvalScript() and actually executes
# the opcodes in the scripts to see if everything worked out. If it doesn't an
# exception will be raised.
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0)

# Done! Print the transaction to standard output with the bytes-to-hex
# function.
print(b2x(tx.serialize()))
Exemple #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"
Exemple #11
0
    [OP_DUP, OP_HASH160,
     Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    0.001 * COIN,
    CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction.
sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, seckey.pub])

# Verify the signature worked. This calls EvalScript() and actually executes
# the opcodes in the scripts to see if everything worked out. If it doesn't an
# exception will be raised.
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH, ))

# Done! Print the transaction to standard output with the bytes-to-hex
# function.
print(b2x(tx.serialize()))
Exemple #12
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()))