Exemple #1
0
    def _do_multisig_script(self, sigs, message, current_script_sig, redeem_script, hash_type):
        # If the current script is empty or None, create it
        sig_script = None
        if current_script_sig is None or not str(current_script_sig):
            sig_bytes = [s["signature"].to_der() + pack_compact_int(hash_type) for s in sigs]

            sig_script = Script.build_multisig_sig(sigs=sig_bytes, redeem_script=redeem_script)
        else:
            # Need to extract all the sigs already present
            multisig_params = redeem_script.extract_multisig_redeem_info()
            sig_info = current_script_sig.extract_multisig_sig_info()

            # Do a few quick sanity checks
            if str(sig_info["redeem_script"]) != str(redeem_script):
                raise ValueError("Redeem script in signature script does not match redeem_script!")

            if len(sig_info["signatures"]) == multisig_params["n"]:
                # Already max number of signatures
                return current_script_sig

            # Go through the signatures and match them up to the public keys
            # in the redeem script
            pub_keys = []
            for pk in multisig_params["public_keys"]:
                pub_keys.append(crypto.PublicKey.from_bytes(pk))

            existing_sigs = []
            for s in sig_info["signatures"]:
                s1, h = s[:-1], s[-1]  # Last byte is hash_type
                existing_sigs.append(crypto.Signature.from_der(s1))
                if h != hash_type:
                    raise ValueError("hash_type does not match that of the existing signatures.")

            # Match them up
            existing_sig_indices = self._match_sigs_to_pub_keys(existing_sigs, pub_keys, message)
            sig_indices = {s["index"]: s["signature"] for s in sigs}

            # Make sure there are no dups
            all_indices = set(list(existing_sig_indices.keys()) + list(sig_indices.keys()))
            if len(all_indices) < len(existing_sig_indices) + len(sig_indices):
                raise ValueError("At least one signature matches an existing signature.")

            if len(all_indices) > multisig_params["n"]:
                raise ValueError("There are too many signatures.")

            all_sigs = []
            for i in sorted(all_indices):
                if i in existing_sig_indices:
                    all_sigs.append(existing_sig_indices[i])
                elif i in sig_indices:
                    all_sigs.append(sig_indices[i])

            all_sigs_bytes = [s.to_der() + pack_compact_int(hash_type) for s in all_sigs]
            sig_script = Script.build_multisig_sig(all_sigs_bytes, redeem_script)

        return sig_script
Exemple #2
0
    def set_txn_side_effect_for_hd_discovery(self):
        # For each used account, there are at least 2 calls required:
        # 1 for the first DISCOVERY_INCREMENT payout addresses and 1
        # for the first DISCOVERY_INCREMENT change
        # addresses. Depending on the number of used addresses for the
        # account, this will change.

        effects = []

        n = self._num_used_accounts
        if n == 0:
            n = 1

        for acct_num in range(n):
            for change in [0, 1]:
                num_used = self._num_used_addresses[acct_num][change]
                r = math.ceil(
                    (num_used + HDAccount.GAP_LIMIT) / self.address_increment)
                k = 'change_addresses' if change else 'payout_addresses'
                addr_list = self._acct_keys[acct_num][k]

                if change:
                    metadata = dict(
                        block=234790 + r,
                        block_hash=Hash(
                            "000000000000000007d57f03ebe36dbe4f87ab2f340e93b45999ab249b6dc0df"
                        ),
                        confirmations=23890 - r)
                else:
                    metadata = dict(block=None,
                                    block_hash=None,
                                    confirmations=0)

                if r == 0:
                    r = 1
                for i in range(r):
                    start = i * self.address_increment
                    end = (i + 1) * self.address_increment
                    addr_range = range(start, end)

                    out = TransactionOutput(value=10000,
                                            script=Script.build_p2pkh(
                                                address_to_key_hash(
                                                    addr_list[i])[1]))
                    dummy_txn = Transaction(1, [], [out], 0)

                    m = MockTxnDict(num_used=num_used,
                                    addr_range=addr_range,
                                    addr_list=addr_list,
                                    used_value=[
                                        dict(metadata=metadata,
                                             transaction=dummy_txn)
                                    ],
                                    unused_value=[])
                    effects.append(m)

        self.get_transactions.side_effect = effects

        return len(effects)
Exemple #3
0
    def set_txn_side_effect_for_hd_discovery(self):
        # For each used account, there are at least 2 calls required:
        # 1 for the first DISCOVERY_INCREMENT payout addresses and 1
        # for the first DISCOVERY_INCREMENT change
        # addresses. Depending on the number of used addresses for the
        # account, this will change.

        effects = []

        n = self._num_used_accounts
        if n == 0:
            n = 1

        for acct_num in range(n):
            for change in [0, 1]:
                num_used = self._num_used_addresses[acct_num][change]
                r = math.ceil((num_used + HDAccount.GAP_LIMIT) /
                              self.address_increment)
                k = 'change_addresses' if change else 'payout_addresses'
                addr_list = self._acct_keys[acct_num][k]

                if change:
                    metadata = dict(block=234790 + r,
                                    block_hash=Hash("000000000000000007d57f03ebe36dbe4f87ab2f340e93b45999ab249b6dc0df"),
                                    confirmations=23890 - r)
                else:
                    metadata = dict(block=None,
                                    block_hash=None,
                                    confirmations=0)

                if r == 0:
                    r = 1
                for i in range(r):
                    start = i * self.address_increment
                    end = (i + 1) * self.address_increment
                    addr_range = range(start, end)

                    out = TransactionOutput(value=10000,
                                            script=Script.build_p2pkh(
                                                address_to_key_hash(
                                                    addr_list[i])[1]))
                    dummy_txn = Transaction(1,
                                            [],
                                            [out],
                                            0)

                    m = MockTxnDict(num_used=num_used,
                                    addr_range=addr_range,
                                    addr_list=addr_list,
                                    used_value=[dict(metadata=metadata,
                                                     transaction=dummy_txn)],
                                    unused_value=[])
                    effects.append(m)

        self.get_transactions.side_effect = effects

        return len(effects)
Exemple #4
0
    def __init__(self, height, raw_script, sequence=MAX_INT, block_version=3):
        self.height = height
        if block_version == 1:
            scr = raw_script
        else:
            scr = Script.build_push_int(self.height) + raw_script

        # Coinbase scripts are basically whatever, so we don't
        # try to create a script object from them.

        super().__init__(self.NULL_OUTPOINT, self.MAX_INT, scr, sequence)
Exemple #5
0
    def __init__(self, height, raw_script, sequence=MAX_INT, block_version=3):
        self.height = height
        if block_version == 1:
            scr = raw_script
        else:
            scr = Script.build_push_int(self.height) + raw_script

        # Coinbase scripts are basically whatever, so we don't
        # try to create a script object from them.

        super().__init__(self.NULL_OUTPOINT, self.MAX_INT, scr, sequence)
Exemple #6
0
    def sign_input(self, input_index, hash_type, private_key, sub_script):
        """ Signs an input.

        Args:
            input_index (int): The index of the input to sign.
            hash_type (int): What kind of signature hash to do.
            private_key (crypto.PrivateKey): private key with which
                to sign the transaction.
            sub_script (Script): the scriptPubKey of the corresponding
                utxo being spent if the outpoint is P2PKH or the redeem
                script if the outpoint is P2SH.
        """
        if input_index < 0 or input_index >= len(self.inputs):
            raise ValueError("Invalid input index.")

        inp = self.inputs[input_index]

        multisig = False
        if sub_script.is_multisig_redeem():
            multisig = True
        elif not sub_script.is_p2pkh():
            raise TypeError(
                "Signing arbitrary redeem scripts is not currently supported.")

        tmp_script = sub_script.remove_op("OP_CODESEPARATOR")

        # Before signing we should verify that the address in the
        # sub_script corresponds to that of the private key
        m = self._match_public_key(private_key, tmp_script)
        if not m['match']:
            if multisig:
                msg = "Public key derived from private key does not match any of the public keys in redeem script."
            else:
                msg = "Address derived from private key does not match sub_script!"
            raise ValueError(msg)

        sig, signed_message = self.get_signature_for_input(
            input_index, hash_type, private_key, sub_script)

        if multisig:
            # For multisig, we need to determine if there are already
            # signatures and if so, where we insert this signature
            inp.script = self._do_multisig_script(
                [dict(index=m['info']['multisig_key_index'], signature=sig)],
                signed_message, inp.script, tmp_script, hash_type)
        else:
            pub_key_bytes = self._get_public_key_bytes(private_key,
                                                       m['info']['compressed'])
            inp.script = Script(
                [sig.to_der() + pack_compact_int(hash_type), pub_key_bytes])

        return True
Exemple #7
0
    def _copy_for_sig(self, input_index, hash_type, sub_script):
        """ Returns a copy of this txn appropriate for signing, based
            on hash_type.
        """
        new_txn = copy.deepcopy(self)

        # First deal w/the inputs

        # For the SIG_HASH_ANY case, we only care about
        # self.inputs[input_index]
        if hash_type == self.SIG_HASH_ANY:
            ti = new_txn.inputs[input_index]
            new_txn.inputs = [ti]
        else:
            for i, inp in enumerate(new_txn.inputs):
                inp.script = sub_script if i == input_index else Script("")

                if hash_type & 0x1f in [
                        self.SIG_HASH_NONE, self.SIG_HASH_SINGLE
                ] and input_index != i:
                    # Sequence numbers (nSequence) must be set to 0 for all but
                    # the input we care about.
                    inp.sequence_num = 0

        # Now deal with outputs

        if hash_type & 0x1f == self.SIG_HASH_NONE:
            new_txn.outputs = []
        elif hash_type & 0x1f == self.SIG_HASH_SINGLE:
            # Resize output vector to input_index + 1
            new_txn.outputs = new_txn.outputs[:input_index + 1]
            # All outputs except outputs[i] have a value of -1 (0xffffffff)
            # and a blank script
            for i, out in enumerate(new_txn.outputs):
                if i != input_index:
                    out.script = Script("")
                    out.value = 0xffffffff

        return new_txn
Exemple #8
0
    def txn_from_json(txn_json):
        inputs = []
        outputs = []
        addr_keys = set()

        for i in sorted(txn_json["vin"], key=lambda i: i["n"]):
            if 'coinbase' in i:
                inputs.append(CoinbaseInput(height=0,
                                            raw_script=bytes.fromhex(i['coinbase']),
                                            sequence=i['sequence'],
                                            block_version=1))
            else:
                script = Script.from_hex(i["scriptSig"]["hex"])
                inputs.append(TransactionInput(Hash(i["txid"]),
                                               i["vout"],
                                               script,
                                               i["sequence"]))
            if "addr" in i:
                addr_keys.add(i["addr"])

        for o in sorted(txn_json["vout"], key=lambda o: o["n"]):
            script = Script.from_hex(o["scriptPubKey"]["hex"])
            value = int(decimal.Decimal(str(o["value"])) * decimal.Decimal('1e8'))
            outputs.append(TransactionOutput(value, script))

            if "addresses" in o["scriptPubKey"]:
                for a in o["scriptPubKey"]["addresses"]:
                    addr_keys.add(a)

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION,
                          inputs,
                          outputs,
                          txn_json["locktime"])

        assert txn.hash == Hash(txn_json['txid'])

        return txn, addr_keys
Exemple #9
0
    def from_bytes(b):
        """ Deserializes a byte stream into a TransactionOutput object.

        Args:
            b (bytes): byte-stream beginning with the value.

        Returns:
            tuple: First element of the tuple is a TransactionOutput,
                   the second is the remainder of the byte stream.
        """
        value, b0 = unpack_u64(b)
        script_len, b0 = unpack_compact_int(b0)

        return (TransactionOutput(value,
                                  Script(b0[:script_len])), b0[script_len:])
Exemple #10
0
    def from_bytes(b):
        """ Deserializes a byte stream into a TransactionInput.

        Args:
            b (bytes): byte stream starting with the outpoint.

        Returns:
            tuple: First element of the tuple is the TransactionInput
                   object and the second is the remaining byte stream.
        """
        outpoint = b[0:32]
        outpoint_index, b1 = unpack_u32(b[32:])
        script, b1 = Script.from_bytes(b1)
        sequence_num, b1 = unpack_u32(b1)

        return (TransactionInput(Hash(outpoint), outpoint_index, script, sequence_num), b1)
Exemple #11
0
    def _verify_input(self, input_index, sub_script, partial_multisig=False):
        p2sh = sub_script.is_p2sh()

        sig_script = self.inputs[input_index].script

        si = ScriptInterpreter(txn=self,
                               input_index=input_index,
                               sub_script=sub_script)
        try:
            si.run_script(sig_script)
        except ScriptInterpreterError:
            return False

        # This copy_stack and the restore_stack emulate the behavior
        # found in bitcoin core for evaluating P2SH scripts. See:
        # https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1170
        if p2sh:
            si.copy_stack()

        try:
            si.run_script(sub_script)
        except ScriptInterpreterError:
            return False
        rv = si.valid

        if p2sh:
            si.restore_stack()
            redeem_script = Script(si.stack.pop())
            si._sub_script = redeem_script

            try:
                if sig_script.is_multisig_sig() and partial_multisig:
                    # This is a hack for partial verification
                    partial_script = copy.deepcopy(redeem_script)
                    partial_script.ast[-1] = 'OP_CHECKPARTIALMULTISIG'

                    sig_info = sig_script.extract_multisig_sig_info()
                    si.run_script(partial_script)
                    rv &= si.match_count > 0 and si.match_count <= len(
                        sig_info['signatures'])
                else:
                    si.run_script(redeem_script)
                    rv &= si.valid
            except:
                rv = False

        return rv
Exemple #12
0
    def from_bytes(b):
        """ Deserializes a byte stream into a TransactionInput.

        Args:
            b (bytes): byte stream starting with the outpoint.

        Returns:
            tuple: First element of the tuple is the TransactionInput
                   object and the second is the remaining byte stream.
        """
        outpoint = b[0:32]
        outpoint_index, b1 = unpack_u32(b[32:])
        script, b1 = Script.from_bytes(b1)
        sequence_num, b1 = unpack_u32(b1)

        return (TransactionInput(Hash(outpoint), outpoint_index, script,
                                 sequence_num), b1)
Exemple #13
0
    def get_utxos(self, address_list):
        """ Provides all unspent transactions associated with each address in
            the address_list.

        Args:
            address_list (list(str)): List of Base58Check encoded Bitcoin
            addresses.

        Returns:
            dict: A dict keyed by address with each value being a list of
               UnspentTransactionOutput objects.
        """
        ret = defaultdict(list)
        for addresses in self._list_chunks(address_list, 199):
            r = self._request("GET", "addresses/" + ",".join(addresses)
                              + "/unspents")
            data = r.json()

            # for each address
            # {
            #     "transaction_hash": "0bf0de38c261...",
            #     "output_index": 0,
            #     "value": 290000,
            #     "addresses": [
            #         "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb"
            #     ],
            #     "script": "OP_DUP OP_HASH160 c6296...",
            #     "script_hex": "76a914c629680b8d1...",
            #     "script_type": "pubkeyhash",
            #     "required_signatures": 1,
            #     "spent": false,
            #     "confirmations": 8758
            # },

            for d in data:
                address = d["addresses"][0]
                txn_hash = Hash(d["transaction_hash"])
                script, _ = Script.from_bytes(
                    pack_var_str(bytes.fromhex(d["script_hex"])))
                ret[address].append(UnspentTransactionOutput(txn_hash,
                                                             d["output_index"],
                                                             d["value"],
                                                             script,
                                                             d["confirmations"]))
        return ret
Exemple #14
0
from two1.lib.bitcoin.txn import TransactionOutput
from two1.lib.bitcoin.script import Script
from two1.lib.bitcoin.utils import address_to_key_hash
from two1.lib.bitcoin.utils import bytes_to_str

address = '137KzxStaf6vw5yGujViK3Tkigoix9N3v7'
_, hash160 = address_to_key_hash(address)
out_script = Script.build_p2pkh(hash160)
out1 = TransactionOutput(value=100000, script=out_script)

# Print the script
print("%s" % (out_script))

# Print the address
print("Addresses = %r" % (out1.get_addresses()))

# Print the value
print("Value: %d" % (out1.value))

# Serialize
out1_bytes = bytes(out1)
print(bytes_to_str(out1_bytes))
Exemple #15
0
    def txn_from_json(txn_json):
        """
        Args:
            txn_json: Json with the following format:
        {
        "block_hash": "0000000000000000af64802c79...",
        "block_height": 292586,
        "hash": "b4735a0690dab16b8789fceaf81c511f...",
        "addresses": [
            "18KXZzuC3xvz6upUMQpsZzXrBwNPWZjdSa",
            "1AAuRETEcHDqL4VM3R97aZHP8DSUHxpkFV",
            "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD",
            "1VxsEDjo6ZLMT99dpcLu4RQonMDVEQQTG"
        ],
        "total": 3537488,
        "fees": 20000,
        "size": 438,
        "preference": "medium",
        "relayed_by": "",
        "confirmed": "2014-03-26T17:08:04Z",
        "received": "2014-03-26T17:08:04Z",
        "ver": 1,
        "lock_time": 0,
        "double_spend": false,
        "vin_sz": 2,
        "vout_sz": 2,
        "confirmations": 64492,
        "confidence": 1,
        "inputs": [
        {
            "prev_hash": "729f6469b59fea5da7...",
            "output_index": 0,
            "script": "483045022100d06cdad1a...",
            "output_value": 3500000,
            "sequence": 4294967295,
            "addresses": [
                "1VxsEDjo6ZLMT99dpcLu4RQonMDVEQQTG"
            ],
            "script_type": "pay-to-pubkey-hash"
        },
        ...
        ],
        "outputs": [
        {
             "value": 3500000,
             "script": "76a9148629647bd642a237...",
             "addresses": [
                 "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD"
             ],
             "script_type": "pay-to-pubkey-hash"
        }
        ]...

        Returns: An Object of type Transaction

        """

        inputs = []
        outputs = []
        addr_keys = set()
        for i in txn_json["inputs"]:
            # Chain doesn't return the stuff about script length etc, so
            # we need to prepend that.
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script"])))
            inputs.append(
                TransactionInput(Hash(i["prev_hash"]), i["output_index"],
                                 script, i["sequence"]))
            if "addresses" in i and i["addresses"]:
                addr_keys.add(i["addresses"][0])

        for i in txn_json["outputs"]:
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script"])))
            outputs.append(TransactionOutput(i["value"], script))
            if "addresses" in i and i["addresses"]:
                addr_keys.add(i["addresses"][0])

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, inputs,
                          outputs, txn_json["lock_time"])

        return txn, addr_keys
    def txn_from_json(txn_json):
        """ Returns a new Transaction from a JSON-serialized transaction

        Args:
            txn_json: JSON with the following format:

        {
        "hash": "0bf0de38c26195919179f...",
        "block_hash": "000000000000000...",
        "block_height": 303404,
        "block_time": "2014-05-30T23:54:55Z",
        "chain_received_at": "2015-08-13T10:52:21.718Z",
        "confirmations": 69389,
        "lock_time": 0,
        "inputs": [
          {
            "transaction_hash": "0bf0de38c2619...",
            "output_hash": "b84a66c46e24fe71f9...",
            "output_index": 0,
            "value": 300000,
            "addresses": [
              "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr"
            ],
            "script_signature": "03046022100de7b67b9...",
            "script_signature_hex": "00493046022100de7b...",
            "sequence": 4294967295
          }
        ],
        "outputs": [
          {
            "transaction_hash": "0bf0de38c261959...",
            "output_index": 0,
            "value": 290000,
            "addresses": [
              "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb"
            ],
            "script": "OP_DUP OP_HASH160 c629680b8d...",
            "script_hex": "76a914c629680b8d13...",
            "script_type": "pubkeyhash",
            "required_signatures": 1,
            "spent": false,
            "spending_transaction": null
          }
        ],
        "fees": 10000,
        "amount": 290000
        },
        Transaction.DEFAULT_TRANSACTION_VERSION

        Returns:
            two1.lib.bitcoin.Transaction: a deserialized transaction derived
                from the provided json.

        """
        inputs = []
        outputs = []
        addr_keys = set()
        for i in txn_json["inputs"]:
            if 'coinbase' in i:
                inputs.append(
                    CoinbaseInput(
                        height=txn_json["block_height"] or 0,
                        raw_script=bytes.fromhex(i['coinbase']),
                        sequence=i['sequence'],
                        block_version=1))
            else:
                # Script length etc. are not returned so we need to
                # prepend that.
                script, _ = Script.from_bytes(
                    pack_var_str(bytes.fromhex(i["script_signature_hex"])))
                inputs.append(TransactionInput(Hash(i["output_hash"]),
                                               i["output_index"],
                                               script,
                                               i["sequence"]))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        for i in txn_json["outputs"]:
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script_hex"])))
            outputs.append(TransactionOutput(i["value"],
                                             script))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION,
                          inputs,
                          outputs,
                          txn_json["lock_time"])

        return txn, addr_keys
    def txn_from_json(txn_json):
        """
        Args:
            txn_json: Json with the following format:
        {
        "block_hash": "0000000000000000af64802c79...",
        "block_height": 292586,
        "hash": "b4735a0690dab16b8789fceaf81c511f...",
        "addresses": [
            "18KXZzuC3xvz6upUMQpsZzXrBwNPWZjdSa",
            "1AAuRETEcHDqL4VM3R97aZHP8DSUHxpkFV",
            "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD",
            "1VxsEDjo6ZLMT99dpcLu4RQonMDVEQQTG"
        ],
        "total": 3537488,
        "fees": 20000,
        "size": 438,
        "preference": "medium",
        "relayed_by": "",
        "confirmed": "2014-03-26T17:08:04Z",
        "received": "2014-03-26T17:08:04Z",
        "ver": 1,
        "lock_time": 0,
        "double_spend": false,
        "vin_sz": 2,
        "vout_sz": 2,
        "confirmations": 64492,
        "confidence": 1,
        "inputs": [
        {
            "prev_hash": "729f6469b59fea5da7...",
            "output_index": 0,
            "script": "483045022100d06cdad1a...",
            "output_value": 3500000,
            "sequence": 4294967295,
            "addresses": [
                "1VxsEDjo6ZLMT99dpcLu4RQonMDVEQQTG"
            ],
            "script_type": "pay-to-pubkey-hash"
        },
        ...
        ],
        "outputs": [
        {
             "value": 3500000,
             "script": "76a9148629647bd642a237...",
             "addresses": [
                 "1DEP8i3QJCsomS4BSMY2RpU1upv62aGvhD"
             ],
             "script_type": "pay-to-pubkey-hash"
        }
        ]...

        Returns: An Object of type Transaction

        """

        inputs = []
        outputs = []
        addr_keys = set()
        for i in txn_json["inputs"]:
            # Chain doesn't return the stuff about script length etc, so
            # we need to prepend that.
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script"])))
            inputs.append(TransactionInput(Hash(i["prev_hash"]),
                                           i["output_index"],
                                           script,
                                           i["sequence"]))
            if "addresses" in i and i["addresses"]:
                addr_keys.add(i["addresses"][0])

        for i in txn_json["outputs"]:
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script"])))
            outputs.append(TransactionOutput(i["value"],
                                             script))
            if "addresses" in i and i["addresses"]:
                addr_keys.add(i["addresses"][0])

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION,
                          inputs,
                          outputs,
                          txn_json["lock_time"])

        return txn, addr_keys
Exemple #18
0
    def txn_from_json(txn_json):
        """ Returns a new Transaction from a JSON-serialized transaction

        Args:
            txn_json: JSON with the following format:

        {
        "hash": "0bf0de38c26195919179f...",
        "block_hash": "000000000000000...",
        "block_height": 303404,
        "block_time": "2014-05-30T23:54:55Z",
        "chain_received_at": "2015-08-13T10:52:21.718Z",
        "confirmations": 69389,
        "lock_time": 0,
        "inputs": [
          {
            "transaction_hash": "0bf0de38c2619...",
            "output_hash": "b84a66c46e24fe71f9...",
            "output_index": 0,
            "value": 300000,
            "addresses": [
              "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr"
            ],
            "script_signature": "03046022100de7b67b9...",
            "script_signature_hex": "00493046022100de7b...",
            "sequence": 4294967295
          }
        ],
        "outputs": [
          {
            "transaction_hash": "0bf0de38c261959...",
            "output_index": 0,
            "value": 290000,
            "addresses": [
              "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb"
            ],
            "script": "OP_DUP OP_HASH160 c629680b8d...",
            "script_hex": "76a914c629680b8d13...",
            "script_type": "pubkeyhash",
            "required_signatures": 1,
            "spent": false,
            "spending_transaction": null
          }
        ],
        "fees": 10000,
        "amount": 290000
        },
        Transaction.DEFAULT_TRANSACTION_VERSION

        Returns:
            two1.lib.bitcoin.Transaction: a deserialized transaction derived
                from the provided json.

        """
        inputs = []
        outputs = []
        addr_keys = set()

        for i in sorted(txn_json["vin"], key=lambda i: i["n"]):
            if 'coinbase' in i:
                inputs.append(CoinbaseInput(height=0,
                                            raw_script=bytes.fromhex(i['coinbase']),
                                            sequence=i['sequence'],
                                            block_version=1))
            else:
                script = Script.from_hex(i["scriptSig"]["hex"])
                inputs.append(TransactionInput(Hash(i["txid"]),
                                               i["vout"],
                                               script,
                                               i["sequence"]))
            if "addr" in i:
                addr_keys.add(i["addr"])

        for o in sorted(txn_json["vout"], key=lambda o: o["n"]):
            script = Script.from_hex(o["scriptPubKey"]["hex"])
            value = int(decimal.Decimal(str(o["value"])) * decimal.Decimal('1e8'))
            outputs.append(TransactionOutput(value, script))

            if "addresses" in o["scriptPubKey"]:
                for a in o["scriptPubKey"]["addresses"]:
                    addr_keys.add(a)

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION,
                          inputs,
                          outputs,
                          txn_json["locktime"])

        assert txn.hash == Hash(txn_json['txid'])

        return txn, addr_keys
Exemple #19
0
    def txn_from_json(txn_json):
        """ Returns a new Transaction from a JSON-serialized transaction

        Args:
            txn_json: JSON with the following format:

        {
        "hash": "0bf0de38c26195919179f...",
        "block_hash": "000000000000000...",
        "block_height": 303404,
        "block_time": "2014-05-30T23:54:55Z",
        "chain_received_at": "2015-08-13T10:52:21.718Z",
        "confirmations": 69389,
        "lock_time": 0,
        "inputs": [
          {
            "transaction_hash": "0bf0de38c2619...",
            "output_hash": "b84a66c46e24fe71f9...",
            "output_index": 0,
            "value": 300000,
            "addresses": [
              "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr"
            ],
            "script_signature": "03046022100de7b67b9...",
            "script_signature_hex": "00493046022100de7b...",
            "sequence": 4294967295
          }
        ],
        "outputs": [
          {
            "transaction_hash": "0bf0de38c261959...",
            "output_index": 0,
            "value": 290000,
            "addresses": [
              "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb"
            ],
            "script": "OP_DUP OP_HASH160 c629680b8d...",
            "script_hex": "76a914c629680b8d13...",
            "script_type": "pubkeyhash",
            "required_signatures": 1,
            "spent": false,
            "spending_transaction": null
          }
        ],
        "fees": 10000,
        "amount": 290000
        },
        Transaction.DEFAULT_TRANSACTION_VERSION

        Returns:
            two1.lib.bitcoin.Transaction: a deserialized transaction derived
                from the provided json.

        """
        inputs = []
        outputs = []
        addr_keys = set()
        for i in txn_json["inputs"]:
            if 'coinbase' in i:
                inputs.append(
                    CoinbaseInput(height=txn_json["block_height"] or 0,
                                  raw_script=bytes.fromhex(i['coinbase']),
                                  sequence=i['sequence'],
                                  block_version=1))
            else:
                # Script length etc. are not returned so we need to
                # prepend that.
                script, _ = Script.from_bytes(
                    pack_var_str(bytes.fromhex(i["script_signature_hex"])))
                inputs.append(
                    TransactionInput(Hash(i["output_hash"]), i["output_index"],
                                     script, i["sequence"]))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        for i in txn_json["outputs"]:
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script_hex"])))
            outputs.append(TransactionOutput(i["value"], script))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, inputs,
                          outputs, txn_json["lock_time"])

        return txn, addr_keys
Exemple #20
0
    def _do_multisig_script(self, sigs, message, current_script_sig,
                            redeem_script, hash_type):
        # If the current script is empty or None, create it
        sig_script = None
        if current_script_sig is None or not str(current_script_sig):
            sig_bytes = [
                s['signature'].to_der() + pack_compact_int(hash_type)
                for s in sigs
            ]

            sig_script = Script.build_multisig_sig(sigs=sig_bytes,
                                                   redeem_script=redeem_script)
        else:
            # Need to extract all the sigs already present
            multisig_params = redeem_script.extract_multisig_redeem_info()
            sig_info = current_script_sig.extract_multisig_sig_info()

            # Do a few quick sanity checks
            if str(sig_info['redeem_script']) != str(redeem_script):
                raise ValueError(
                    "Redeem script in signature script does not match redeem_script!"
                )

            if len(sig_info['signatures']) == multisig_params['n']:
                # Already max number of signatures
                return current_script_sig

            # Go through the signatures and match them up to the public keys
            # in the redeem script
            pub_keys = []
            for pk in multisig_params['public_keys']:
                pub_keys.append(crypto.PublicKey.from_bytes(pk))

            existing_sigs = []
            for s in sig_info['signatures']:
                s1, h = s[:-1], s[-1]  # Last byte is hash_type
                existing_sigs.append(crypto.Signature.from_der(s1))
                if h != hash_type:
                    raise ValueError(
                        "hash_type does not match that of the existing signatures."
                    )

            # Match them up
            existing_sig_indices = self._match_sigs_to_pub_keys(
                existing_sigs, pub_keys, message)
            sig_indices = {s['index']: s['signature'] for s in sigs}

            # Make sure there are no dups
            all_indices = set(list(existing_sig_indices.keys()) + \
                              list(sig_indices.keys()))
            if len(all_indices) < len(existing_sig_indices) + len(sig_indices):
                raise ValueError(
                    "At least one signature matches an existing signature.")

            if len(all_indices) > multisig_params['n']:
                raise ValueError("There are too many signatures.")

            all_sigs = []
            for i in sorted(all_indices):
                if i in existing_sig_indices:
                    all_sigs.append(existing_sig_indices[i])
                elif i in sig_indices:
                    all_sigs.append(sig_indices[i])

            all_sigs_bytes = [
                s.to_der() + pack_compact_int(hash_type) for s in all_sigs
            ]
            sig_script = Script.build_multisig_sig(all_sigs_bytes,
                                                   redeem_script)

        return sig_script
Exemple #21
0
    def txn_from_json(txn_json):
        # {
        # "hash": "0bf0de38c26195919179f...",
        # "block_hash": "000000000000000...",
        # "block_height": 303404,
        # "block_time": "2014-05-30T23:54:55Z",
        # "chain_received_at": "2015-08-13T10:52:21.718Z",
        # "confirmations": 69389,
        # "lock_time": 0,
        # "inputs": [
        #   {
        #     "transaction_hash": "0bf0de38c2619...",
        #     "output_hash": "b84a66c46e24fe71f9...",
        #     "output_index": 0,
        #     "value": 300000,
        #     "addresses": [
        #       "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr"
        #     ],
        #     "script_signature": "03046022100de7b67b9...",
        #     "script_signature_hex": "00493046022100de7b...",
        #     "sequence": 4294967295
        #   }
        # ],
        # "outputs": [
        #   {
        #     "transaction_hash": "0bf0de38c261959...",
        #     "output_index": 0,
        #     "value": 290000,
        #     "addresses": [
        #       "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb"
        #     ],
        #     "script": "OP_DUP OP_HASH160 c629680b8d...",
        #     "script_hex": "76a914c629680b8d13...",
        #     "script_type": "pubkeyhash",
        #     "required_signatures": 1,
        #     "spent": false,
        #     "spending_transaction": null
        #   }
        # ],
        # "fees": 10000,
        # "amount": 290000
        # },
        # Transaction.DEFAULT_TRANSACTION_VERSION
        inputs = []
        outputs = []
        addr_keys = set()
        for i in txn_json["inputs"]:
            # Chain doesn't return the stuff about script length etc, so
            # we need to prepend that.
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script_signature_hex"])))
            inputs.append(TransactionInput(Hash(i["output_hash"]),
                                           i["output_index"],
                                           script,
                                           i["sequence"]))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        for i in txn_json["outputs"]:
            script, _ = Script.from_bytes(
                pack_var_str(bytes.fromhex(i["script_hex"])))
            outputs.append(TransactionOutput(i["value"],
                                             script))
            if "addresses" in i:
                addr_keys.add(i["addresses"][0])

        txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION,
                          inputs,
                          outputs,
                          txn_json["lock_time"])

        return txn, addr_keys
Exemple #22
0
from two1.lib.bitcoin.txn import Transaction
from two1.lib.wallet import Wallet
from two1.lib.bitcoin.script import Script
from two1.lib.blockchain.twentyone_provider import TwentyOneProvider
import two1.lib.bitcoin as bitcoin

provider = TwentyOneProvider()
wallet = Wallet()

pubkey = input("Please enter the public key that was used to create the script")
tx_hex = input("Please enter the transaction hex")
server_pubkey = input("Please enter server pub key")
white_pubkey = input("Please enter white pub key")
black_pubkey = input("Please enter black pub key")


their_pubkey = PublicKey.from_bytes(pubkey)
tx = Transaction.from_hex(tx_hex)

private_key = wallet.get_private_for_public(their_pubkey)
public_keys = [PublicKey.from_bytes(server_pubkey).compressed_bytes, PublicKey.from_bytes(white_pubkey).compressed_bytes, PublicKey.from_bytes(black_pubkey).compressed_bytes]
redeem_script = Script.build_multisig_redeem(2, public_keys)

for i, inp in enumerate(tx.inputs):
   tx.sign_input(i, bitcoin.Transaction.SIG_HASH_ALL, private_key, redeem_script)

txid = provider.broadcast_transaction(tx.to_hex())

print("Transaction ID: {}".format(txid))