Ejemplo n.º 1
0
    def sighash(self, i, script=b'', hashcode=SIGHASH.ALL):
        inp = self.inputs[i]
        tx_type = inp.ref().type()

        if tx_type in (TX.P2PK, TX.P2PKH) or (tx_type == TX.P2SH and not inp.is_nested()):
            preimage = self.signature_form_legacy(i=i, script=script, hashcode=hashcode)
        else:
            preimage = self.signature_form_segwit(i=i, hashcode=hashcode)

        return sha256(sha256(preimage))
Ejemplo n.º 2
0
def legacy_address(pub_or_script: Union[bytes, PublicKey],
                   version_byte: bytes) -> str:
    """https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses"""
    bts = pub_or_script.encode(compressed=False) if isinstance(
        pub_or_script, PublicKey) else pub_or_script
    hashed = hash160(bts)
    payload = version_byte + hashed
    checksum = sha256(sha256(payload))[:4]
    address = payload + checksum
    return base58.encode(address)
Ejemplo n.º 3
0
    def signature_form_segwit(self, i, hashcode=SIGHASH.ALL):
        """Segwit version of signature_form"""
        # https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#specification
        tx = deepcopy(self)

        ref = tx.inputs[i].ref()

        nversion = tx._version[::-1]
        hashprevouts = sha256(sha256(concat((inp.outpoint() for inp in tx.inputs)))) if not hashcode.is_anyonecanpay() else pad(0, 32)
        hashsequence = sha256(sha256(concat(inp._sequence[::-1] for inp in tx.inputs))) if hashcode == SIGHASH.ALL else pad(0, 32)
        outpoint = tx.inputs[i].outpoint()
        scriptcode = serialize(tx.inputs[i].scriptcode())
        value = ref._value[::-1]
        nsequence = tx.inputs[i]._sequence[::-1]

        if not (hashcode.is_single() or hashcode.is_none()):
            hashoutputs = sha256(sha256(concat(out._value[::-1] + push(out.script) for out in tx.outputs)))
        elif hashcode.is_single() and i < len(tx.outputs):
            hashoutputs = sha256(sha256(tx.outputs[i]._value[::-1] + push(tx.outputs[i].script)))
        else:
            hashoutputs = pad(0, 32)

        nlocktime = tx._lock_time[::-1]
        sighash = pad(hashcode.value, 4)[::-1]

        return concat([nversion, hashprevouts, hashsequence, outpoint, scriptcode, value, nsequence, hashoutputs, nlocktime, sighash])
Ejemplo n.º 4
0
def address_type(addr):
    if addr.startswith(('1', '2', '3', 'm', 'n')):
        try:
            address = base58.decode(addr).rjust(25, b'\x00')
        except Base58DecodeError as e:
            raise InvalidAddress(f"{addr} : {e}") from None
        payload, checksum = address[:-4], address[-4:]
        version_byte, digest = payload[0:1], payload[1:].rjust(20, b'\x00')
        if len(digest) != 20:
            raise InvalidAddress(f"{addr} : Bad Payload") from None
        if sha256(sha256(payload))[:4] != checksum:
            raise InvalidAddress(f"{addr} : Invalid checksum") from None
        try:
            return {
                network('keyhash'): ADDRESS.P2PKH,
                network('scripthash'): ADDRESS.P2SH
            }[version_byte]
        except KeyError:
            raise InvalidAddress(f"{addr} : Invalid version byte") from None
    elif addr.startswith(network('hrp')):
        try:
            witness_version, witness_program = bech32.decode(
                network('hrp'), addr)
        except Bech32DecodeError as e:
            raise InvalidAddress(f"{addr} : {e}") from None

        if not witness_version == 0x00:
            raise InvalidAddress(f"{addr} : Invalid witness version") from None
        if len(witness_program) == 20:
            return ADDRESS.P2WPKH
        elif len(witness_program) == 32:
            return ADDRESS.P2WSH
        else:
            raise InvalidAddress(f"{addr} : Invalid witness program") from None
    else:
        raise InvalidAddress(f"{addr} : Invalid leading character") from None
Ejemplo n.º 5
0
def check(mnemonic):
    mnemonic = mnemonic.lower().split()

    if len(mnemonic) not in {12, 15, 18, 21, 24}:
        return False

    try:
        indexes = [binary_search(word) for word in mnemonic]
    except LookupError:
        return False

    bits = ''.join(int_to_bin(idx).zfill(11) for idx in indexes)
    checksum_length = len(mnemonic) // 3
    data, checksum = bin_to_bytes(
        bits[:-checksum_length]), bits[-checksum_length:]
    return bytes_to_bin(sha256(data)).zfill(256)[:checksum_length] == checksum
Ejemplo n.º 6
0
    def verify_p2wsh(self):
        if not version_byte(self.scriptPubKey) == 0x00:
            raise InvalidTransaction('Unknown witness version')

        witness = deepcopy(self.input.witness)
        self.stack = list(witness)
        witness_script = self.pop()

        if not len(witness_script) <= 10000:
            raise InvalidTransaction('Witness script too long')

        if not witness_program(self.scriptPubKey) == sha256(witness_script):
            raise InvalidTransaction(
                'Redeem script hash does not match scriptPubKey')

        self.script = witness_script
        if any((len(item) > 520 for item in witness)):
            raise InvalidTransaction(
                f'Invalid witness for a {TX.P2WSH} transaction')

        return self.verify_legacy() and len(self.stack) == 0
Ejemplo n.º 7
0
def script_to_bech32(script: bytes, witver: int) -> str:
    """https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#witness-program"""
    witprog = sha256(script)
    return bech32.encode(network('hrp'), witver, witprog)
Ejemplo n.º 8
0
    lambda pub: legacy_address(pub, version_byte=network('keyhash')),
    # 'P2WPKH': partial(pubkey_to_p2wpkh, version_byte=0x06, witver=0x00),  # WAS REPLACED BY BIP 173
    ADDRESS.P2WPKH_P2SH:
    lambda pub: legacy_address(witness_byte(witver=0) + push(
        hash160(pub.encode(compressed=True))),
                               version_byte=network('scripthash')),
    ADDRESS.P2WPKH:
    partial(pubkey_to_bech32, witver=0x00),
}

script_to_addr_versions = {
    ADDRESS.P2SH:
    lambda script: legacy_address(script, version_byte=network('scripthash')),
    # 'P2WSH': partial(script_to_p2wsh, version_byte=0x0A, witver=0x00),  # WAS REPLACED BY BIP 173
    ADDRESS.P2WSH_P2SH:
    lambda script: legacy_address(witness_byte(witver=0) + push(sha256(script)
                                                                ),
                                  version_byte=network('scripthash')),
    ADDRESS.P2WSH:
    partial(script_to_bech32, witver=0x00),
}


def pubkey_to_address(pub: PublicKey, version='P2PKH') -> str:
    converter = key_to_addr_versions[ADDRESS(version.upper())]
    return converter(pub)


def script_to_address(script: bytes, version='P2SH') -> str:
    """Redeem script to address"""
    converter = script_to_addr_versions[ADDRESS(version.upper())]
Ejemplo n.º 9
0
 def encode(self):
     data = self.serialize()
     assert len(data) == 78
     checksum = sha256(sha256(data))[:4]
     return base58.encode(data + checksum)
Ejemplo n.º 10
0
 def decode(cls, string: str) -> 'ExtendedKey':
     bts = base58.decode(string)
     assert len(bts) == 82, f'Invalid length {len(bts)})'
     data, checksum = bts[:78], bts[78:]
     assert sha256(sha256(data)).startswith(checksum), 'Invalid checksum'
     return cls.deserialize(data)
Ejemplo n.º 11
0
 def wtxid(self):
     if not self.segwit:
         return self.txid()
     return sha256(sha256(self.serialize(segwit=True)))
Ejemplo n.º 12
0
 def txid(self):
     return sha256(sha256(self.serialize(segwit=False)))
Ejemplo n.º 13
0
def hashed_payload_to_address(payload):
    checksum = sha256(sha256(payload))[:4]
    address = payload + checksum
    return base58.encode(address)