예제 #1
0
 def __get_multisig_script_sig__(self,  script_sig,
                                 keys, signatures,
                                 script_code,
                                 redeem_script,
                                 n, amount=None):
     sig_map = {keys[i]:signatures[i] for i in range(len(keys))}
     pub_keys = get_multisig_public_keys(redeem_script)
     p2wsh = True if isinstance(script_sig, list) else False
     if not p2wsh:
         s = get_stream(script_sig)
         o, d = read_opcode(s)
         while o:
             o, d = read_opcode(s)
             if d and is_valid_signature_encoding(d):
                 for i in range(4):
                     sighash = self.sig_hash(n, script_pub_key=script_code, sighash_type=d[-1])
                     sighash = s2rh(sighash) if isinstance(sighash, str) else sighash
                     pk = public_key_recovery(d[:-1], sighash, i, hex=0)
                     if pk in pub_keys:
                         sig_map[pk] = d
                         break
         # recreate script sig
         r = [OP_0]
         for k in pub_keys:
             try:
                 r.append(op_push_data(sig_map[k]))
             except:
                 pass
         r += [op_push_data(redeem_script)]
     else:
         for w in script_sig:
             if isinstance(w, str):
                 w = bytes.fromhex(w)
             if w and is_valid_signature_encoding(w):
                 d = w[:-1]
                 for i in range(4):
                     sighash = self.sig_hash_segwit(n, amount,
                                                    script_pub_key=script_code,
                                                    sighash_type=w[-1])
                     pk = public_key_recovery(d, sighash, i, hex=0)
                     if pk in pub_keys:
                         sig_map[pk] = w
                         break
         r = [b""]
         for k in pub_keys:
             try:
                 r.append(sig_map[k])
             except:
                 pass
         r += [redeem_script]
     return r
예제 #2
0
    def __init__(self,
                 key=None,
                 address_type="P2WPKH",
                 testnet=False,
                 compressed=True):
        if key is None:
            #: instance of ``PrivateKey`` class
            self.private_key = PrivateKey(testnet=testnet,
                                          compressed=compressed)
            #: instance of ``PublicKey`` class
            self.public_key = PublicKey(self.private_key)
            #: flag for testnet network address  (boolean)
            self.testnet = testnet
        if isinstance(key, str) or isinstance(key, bytes):
            key = PrivateKey(key, testnet=testnet, compressed=compressed)
        if isinstance(key, PrivateKey):
            self.private_key = key
            self.testnet = key.testnet
            compressed = key.compressed
            self.public_key = PublicKey(self.private_key)
        elif isinstance(key, PublicKey):
            self.public_key = key
            self.testnet = testnet
            compressed = key.compressed
        if address_type not in ("P2PKH", "PUBKEY", "P2WPKH", "P2SH_P2WPKH"):
            raise TypeError("address type invalid")
        if not compressed:
            if address_type not in ("P2PKH", "PUBKEY", "P2SH"):
                raise TypeError("compressed public key invalid")
        #: flag for testnet network address  (boolean)
        self.type = address_type

        if address_type == "PUBKEY":
            self.pubkey_script = b"%s%s" % (op_push_data(
                self.public_key.key), OP_CHECKSIG)
            self.pubkey_script_hex = self.pubkey_script.hex()
            #: version of witness program for SEGWIT address (string)
        self.witness_version = 0 if address_type == "P2WPKH" else None
        self.compressed = compressed
        if address_type == "P2SH_P2WPKH":
            #: flag for script hash address (boolean)
            self.script_hash = True
            #: redeeem script, only for P2SH_P2WPKH (bytes)
            self.redeem_script = public_key_to_p2sh_p2wpkh_script(
                self.public_key.key)
            #: redeeem script HEX, only for P2SH_P2WPKH (string)
            self.redeem_script_hex = self.redeem_script.hex()
            #: address hash
            self.hash = hash160(self.redeem_script)
            self.witness_version = None
        else:
            self.script_hash = False
            self.hash = hash160(self.public_key.key)
        #: address hash HEX (string)
        self.hash_hex = self.hash.hex()
        #: address in base58 or bech32 encoding (string)
        self.address = hash_to_address(self.hash,
                                       script_hash=self.script_hash,
                                       witness_version=self.witness_version,
                                       testnet=self.testnet)
예제 #3
0
    def __sign_p2sh_p2wpkh(self, n, private_key, public_key, redeem_script, sighash_type, amount):
        s = [b'\x19', OP_DUP, OP_HASH160,
             op_push_data(hash160(public_key[0], 0)),
             OP_EQUALVERIFY, OP_CHECKSIG]
        if amount is None:
            try:
                amount = self["vIn"][n]["value"]
            except:
                raise RuntimeError("no input amount")
        sighash = self.sig_hash_segwit(n, amount, script_pub_key=b"".join(s), sighash_type=sighash_type)
        sighash = bytes.fromhex(sighash) if isinstance(sighash, str) else sighash
        signature = sign_message(sighash, private_key[0], 0) + bytes([sighash_type])

        self["segwit"] = True
        if self["format"] == "raw":
            self["vIn"][n]['txInWitness'] = [signature, public_key[0]]
        else:
            self["vIn"][n]['txInWitness'] = [signature.hex(), public_key[0].hex()]

        self["vIn"][n]['signatures'] = [signature,] if self["format"] == "raw" else [signature.hex(),]

        return op_push_data(redeem_script)
예제 #4
0
def test_op_push_data():
    assert op_push_data("") == b"\x00"
    assert op_push_data(b"1234567890") == b'\n1234567890'
    assert op_push_data(b"1" * 75) == b'K' + b"1" * 75
    assert op_push_data(b"1" * 76) != b'\x4c' + b"1" * 76
    assert op_push_data(b"1" * 76) == get_bytes(
        [OP_PUSHDATA1, b"\x4c", b"1" * 76])
    assert op_push_data(b"1" * 256) == get_bytes(
        [OP_PUSHDATA2, pack('<H', 256), b"1" * 256])
    p = b"1" * 65537
    l = op_push_data(p) == OP_PUSHDATA4 + pack('<L', 65537) + p
    assert l
예제 #5
0
 def __sign_p2sh_p2wsh_multisig(self, n, private_key, public_key,
                                redeem_script, sighash_type, amount):
     self["segwit"] = True
     script_code = int_to_var_int(len(redeem_script)) + redeem_script
     sighash = self.sig_hash_segwit(n, amount, script_pub_key=script_code, sighash_type=sighash_type)
     sighash = bytes.fromhex(sighash) if isinstance(sighash, str) else sighash
     sig = [sign_message(sighash, p, 0) + bytes([sighash_type]) for p in private_key]
     self["vIn"][n]['signatures'] = [s if self["format"] == "raw" else s.hex() for s in sig]
     if "txInWitness" not in self["vIn"][n]:
         self["vIn"][n]["txInWitness"] = []
     witness = self.__get_multisig_script_sig__(self["vIn"][n]["txInWitness"],
                                                public_key,
                                                sig,
                                                script_code,
                                                redeem_script,
                                                n,
                                                amount)
     if self["format"] == "raw":
         self["vIn"][n]['txInWitness'] = list(witness)
     else:
         self["vIn"][n]["txInWitness"] = list([w.hex() for w in witness])
     # calculate P2SH redeem script from P2WSH redeem script
     return op_push_data(b"\x00" + op_push_data(sha256(redeem_script)))
예제 #6
0
 def __get_bare_multisig_script_sig__(self,  script_sig, script_pub_key,
                                      keys, signatures, n):
     sig_map = {keys[i]:signatures[i] for i in range(len(keys))}
     pub_keys = get_multisig_public_keys(script_pub_key)
     s = get_stream(script_sig)
     o, d = read_opcode(s)
     while o:
         o, d = read_opcode(s)
         if d and is_valid_signature_encoding(d):
             for i in range(4):
                 sighash = self.sig_hash(n, script_pub_key=script_pub_key, sighash_type=d[-1])
                 sighash = s2rh(sighash) if isinstance(sighash, str) else sighash
                 pk = public_key_recovery(d[:-1], sighash, i, hex=0)
                 if pk in pub_keys:
                     sig_map[pk] = d
                     break
     # recreate script sig
     r = [OP_0]
     for k in pub_keys:
         try:
             r.append(op_push_data(sig_map[k]))
         except:
             pass
     return r
예제 #7
0
def op_push_data(data):
    return __parent__.op_push_data(data)