Exemplo n.º 1
0
    def sign(self, default_wallet: BitcoinWallet = None):
        """Signing transaction using the wallet object."""

        for tx_index, tx_in in enumerate(self.tx.vin):
            utxo = self.solvable_utxo[tx_index]
            wallet = utxo.wallet or default_wallet

            if wallet is None:
                raise RuntimeError('Cannot sign transaction without a wallet.')

            tx_script = utxo.parsed_script
            if utxo.contract:
                sig_hash = script.SignatureHash(
                    script.CScript.fromhex(utxo.contract), self.tx, tx_index,
                    script.SIGHASH_ALL)
            else:
                sig_hash = script.SignatureHash(tx_script, self.tx, tx_index,
                                                script.SIGHASH_ALL)
            sig = wallet.private_key.sign(sig_hash) + struct.pack(
                '<B', script.SIGHASH_ALL)
            script_sig = [sig, wallet.private_key.pub
                          ] + utxo.unsigned_script_sig
            tx_in.scriptSig = script.CScript(script_sig)

            VerifyScript(tx_in.scriptSig, tx_script, self.tx, tx_index,
                         (SCRIPT_VERIFY_P2SH, ))
        self.signed = True
Exemplo n.º 2
0
    def close_tx(self, fee: int, privkey_dest: str) -> str:
        """Create a (mutual) close tx"""
        txin = CTxIn(COutPoint(bytes.fromhex(self.txid), self.output_index))

        out_privkey = privkey_expand(privkey_dest)

        txout = CTxOut(self.amount - fee,
                       CScript([script.OP_0,
                                Hash160(coincurve.PublicKey.from_secret(out_privkey.secret).format())]))

        tx = CMutableTransaction(vin=[txin], vout=[txout])
        sighash = script.SignatureHash(self.redeemscript(), tx, inIdx=0,
                                       hashtype=script.SIGHASH_ALL,
                                       amount=self.amount,
                                       sigversion=script.SIGVERSION_WITNESS_V0)

        sigs = [key.sign(sighash, hasher=None) for key in self.funding_privkeys_for_tx()]
        # BOLT #3:
        # ## Closing Transaction
        # ...
        #    * `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>`
        witness = CScriptWitness([bytes(),
                                  sigs[0] + bytes([script.SIGHASH_ALL]),
                                  sigs[1] + bytes([script.SIGHASH_ALL]),
                                  self.redeemscript()])
        tx.wit = CTxWitness([CTxInWitness(witness)])
        return tx.serialize().hex()
Exemplo n.º 3
0
    def sign_our_inputs(self) -> None:
        assert self.tx is not None
        for idx, _in in enumerate(self.inputs):
            privkey = _in['privkey']

            if privkey and 'sig' not in _in:
                print('signing our input for tx', self.tx.serialize().hex())
                inkey = privkey_expand(privkey)
                inkey_pub = coincurve.PublicKey.from_secret(inkey.secret)

                # Really horrid hack to produce a signature for the
                # multisig utxo in tests/helpers.py
                if privkey == '38204720bc4f9647fd58c6d0a4bd3a6dd2be16d8e4273c4d1bdd5774e8c51eaf':
                    redeemscript = bytes.fromhex('51210253cdf835e328346a4f19de099cf3d42d4a7041e073cd4057a1c4fd7cdbb1228f2103ae903722f21f85e651b8f9b18fc854084fb90eeb76452bdcfd0cb43a16a382a221036c264d68a9727afdc75949f7d7fa71910ae9ae8001a1fbffa6f7ce000976597c21036429fa8a4ef0b2b1d5cb553e34eeb90a32ab19fae1f0024f332ab4f74283a7282103d4232f19ea85051e7b76bf5f01d03e17eea8751463dee36d71413a739de1a92755ae')
                else:
                    address = P2WPKHBitcoinAddress.from_scriptPubKey(CScript([script.OP_0, Hash160(inkey_pub.format())]))
                    redeemscript = address.to_redeemScript()

                sighash = script.SignatureHash(redeemscript,
                                               self.tx, idx, script.SIGHASH_ALL,
                                               amount=_in['sats'],
                                               sigversion=script.SIGVERSION_WITNESS_V0)
                sig = inkey.sign(sighash, hasher=None) + bytes([script.SIGHASH_ALL])

                if privkey == '38204720bc4f9647fd58c6d0a4bd3a6dd2be16d8e4273c4d1bdd5774e8c51eaf':
                    _in['sig'] = CTxInWitness(CScriptWitness([bytes([]), sig, redeemscript]))
                else:
                    _in['sig'] = CTxInWitness(CScriptWitness([sig, inkey_pub.format()]))
Exemplo n.º 4
0
    def add_witnesses(self,
                      witness_stack) -> str:
        wits = []
        for idx, _in in enumerate(self.inputs):
            privkey = _in['privkey']
            serial_id = _in['serial_id']

            if privkey:
                inkey = privkey_expand(privkey)
                inkey_pub = coincurve.PublicKey.from_secret(inkey.secret)

                address = P2WPKHBitcoinAddress.from_scriptPubKey(CScript([script.OP_0, Hash160(inkey_pub.format())]))

                sighash = script.SignatureHash(address.to_redeemScript(),
                                               self.tx, idx, script.SIGHASH_ALL,
                                               amount=_in['sats'],
                                               sigversion=script.SIGVERSION_WITNESS_V0)
                sig = inkey.sign(sighash, hasher=None) + bytes([script.SIGHASH_ALL])

                wits.append(CTxInWitness(CScriptWitness([sig, inkey_pub.format()])))
                continue

            # Every input from the witness stack will be the accepter's
            # which is always an odd serial
            assert(serial_id % 2 == 1)
            elems = witness_stack.pop(0)['witness_element']

            stack = []
            for elem in elems:
                stack.append(bytes.fromhex(elem['witness']))

            wits.append(CTxInWitness(CScriptWitness(stack)))

        self.tx.wit = CTxWitness(wits)
        return self.tx.serialize().hex()
Exemplo n.º 5
0
 def _sig(self, privkey: coincurve.PrivateKey,
          tx: CMutableTransaction) -> Sig:
     sighash = script.SignatureHash(self.funding.redeemscript(),
                                    tx,
                                    inIdx=0,
                                    hashtype=script.SIGHASH_ALL,
                                    amount=self.funding.amount,
                                    sigversion=script.SIGVERSION_WITNESS_V0)
     return Sig(privkey.secret.hex(), sighash.hex())
Exemplo n.º 6
0
    def from_utxo(txid_in: str,
                  tx_index_in: int,
                  sats: int,
                  privkey: str,
                  fee: int,
                  local_node_privkey: str,
                  local_funding_privkey: str,
                  remote_node_privkey: str,
                  remote_funding_privkey: str,
                  chain_hash: str = regtest_hash) -> Tuple['Funding', str]:
        """Make a funding transaction by spending this utxo using privkey: return Funding, tx."""

        # Create dummy one to start: we will fill in txid at the end.
        funding = Funding('', 0, sats - fee, local_node_privkey,
                          local_funding_privkey, remote_node_privkey,
                          remote_funding_privkey, chain_hash)

        # input private key.
        inkey = privkey_expand(privkey)
        inkey_pub = coincurve.PublicKey.from_secret(inkey.secret)

        # use RBF'able input (requirement for dual-funded things)
        txin = CTxIn(COutPoint(bytes.fromhex(txid_in), tx_index_in),
                     nSequence=0xFFFFFFFD)
        txout = CTxOut(
            sats - fee,
            CScript([script.OP_0,
                     sha256(funding.redeemscript()).digest()]))
        tx = CMutableTransaction([txin], [txout],
                                 nVersion=2,
                                 nLockTime=funding.locktime)

        # now fill in funding txid.
        funding.txid = tx.GetTxid().hex()
        funding.tx = tx

        # while we're here, sign the transaction.
        address = P2WPKHBitcoinAddress.from_scriptPubKey(
            CScript([script.OP_0, Hash160(inkey_pub.format())]))

        sighash = script.SignatureHash(address.to_redeemScript(),
                                       tx,
                                       0,
                                       script.SIGHASH_ALL,
                                       amount=sats,
                                       sigversion=script.SIGVERSION_WITNESS_V0)
        sig = inkey.sign(sighash, hasher=None) + bytes([script.SIGHASH_ALL])

        tx.wit = CTxWitness(
            [CTxInWitness(CScriptWitness([sig, inkey_pub.format()]))])
        return funding, tx.serialize().hex()
Exemplo n.º 7
0
def create_tx(n, addressFrom, addressTo, mixer_list, fee=None):
	pre_tx = transaction(n, addressFrom, addressTo, mixer_list, fee=None)
	own_n = len(pre_tx.own_inputs)

	# Get inputs signed by each of the miners
	for x in pre_tx.mixer_inputs:
		sig_mixer, pubKey_mixer = send_tx(pre_tx.tx, x, pre_tx.pruned_mixer_inputs)
		x.scriptSig = bcs.CScript([sig_mixer, pubKey_mixer])

	# Sign inputs owned by sender's address
	txin_scriptPubKey = bcs.CScript([bcs.OP_DUP, bcs.OP_HASH160, bc.Hash160(addressFrom.pubKey), bcs.OP_EQUALVERIFY, bcs.OP_CHECKSIG])
	for i in range(own_n):
		sighash = bcs.SignatureHash(txin_scriptPubKey, pre_tx.tx, i, bcs.SIGHASH_ALL)
		sig = addressFrom.priv.sign(sighash) + bytes([bcs.SIGHASH_ALL])
		pre_tx.inputs[i].scriptSig = bcs.CScript([sig, addressFrom.pubKey])
		bcseval.VerifyScript(pre_tx.inputs[i].scriptSig, txin_scriptPubKey, pre_tx.tx, i, (bcseval.SCRIPT_VERIFY_P2SH,))

	return pre_tx
Exemplo n.º 8
0
    def htlc_sigs(self, signer: Side, side: Side) -> List[Sig]:
        """Produce the signer's signatures for the dest's HTLC transactions"""
        # BOLT #2:
        # - MUST include one `htlc_signature` for every HTLC transaction
        #   corresponding to the ordering of the commitment transaction (see
        #   [BOLT
        #   #3](03-transactions.md#transaction-input-and-output-ordering)).

        # So we need the HTLCs in output order, which is why we had _unsigned_tx
        # return them.
        commit_tx, htlcs = self._unsigned_tx(side)

        sigs: List[Sig] = []
        for outnum, htlc in enumerate(htlcs):
            # to_local or to_remote output?
            if htlc is None:
                continue
            if htlc.owner == side:
                redeemscript, sats = self._offered_htlc_output(htlc, side)
                fee = htlc.htlc_timeout_fee(self.feerate)
                # BOLT #3:
                # * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout
                locktime = htlc.cltv_expiry
            else:
                redeemscript, sats = self._received_htlc_output(htlc, side)
                fee = htlc.htlc_success_fee(self.feerate)
                locktime = 0

            htlc_tx = self.htlc_tx(commit_tx, outnum, side,
                                   (htlc.amount_msat - msat(fee)) // 1000,
                                   locktime)
            print("htlc_tx = {}".format(htlc_tx.serialize().hex()))
            sighash = script.SignatureHash(
                redeemscript,
                htlc_tx,
                inIdx=0,
                hashtype=script.SIGHASH_ALL,
                amount=htlc.amount_msat // 1000,
                sigversion=script.SIGVERSION_WITNESS_V0)
            privkey = self._basepoint_tweak(
                self.keyset[signer].htlc_base_secret, side)
            sigs.append(Sig(privkey.secret.hex(), sighash.hex()))

        return sigs
Exemplo n.º 9
0
 def signed_tx(self,
               unsigned_tx: CMutableTransaction) -> CMutableTransaction:
     # BOLT #3:
     # * `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>`
     tx = unsigned_tx.copy()
     sighash = script.SignatureHash(self.funding.redeemscript(),
                                    tx,
                                    inIdx=0,
                                    hashtype=script.SIGHASH_ALL,
                                    amount=self.funding.amount,
                                    sigversion=script.SIGVERSION_WITNESS_V0)
     sigs = [
         key.sign(sighash, hasher=None)
         for key in self.funding.funding_privkeys_for_tx()
     ]
     tx.wit = CTxWitness([
         CScriptWitness([
             bytes(), sigs[0] + bytes([script.SIGHASH_ALL]),
             sigs[1] + bytes([script.SIGHASH_ALL]),
             self.funding.redeemscript()
         ])
     ])
     return tx