예제 #1
0
def b58decode(v: String, out_size: Optional[int] = None) -> bytes:
    """Decode a Base58Check encoded bytes-like object or ASCII string.

    Optionally, it also ensures required output size.
    """

    if isinstance(v, str):
        # do not trim spaces
        v = v.encode("ascii")

    result = _b58decode(v)
    if len(result) < 4:
        err_msg = "not enough bytes for checksum, "
        err_msg += f"invalid base58 decoded size: {len(result)}"
        raise BTClibValueError(err_msg)

    result, checksum = result[:-4], result[-4:]
    h256 = hash256(result)
    if checksum != h256[:4]:
        err_msg = f"invalid checksum: 0x{checksum.hex()} instead of 0x{h256[:4].hex()}"
        raise BTClibValueError(err_msg)

    if out_size is None or len(result) == out_size:
        return result

    err_msg = "valid checksum, invalid decoded size: "
    err_msg += f"{len(result)} bytes instead of {out_size}"
    raise BTClibValueError(err_msg)
예제 #2
0
def legacy(script_: Octets, tx: Tx, vin_i: int, hash_type: int) -> bytes:
    script_ = bytes_from_octets(script_)

    new_tx = deepcopy(tx)
    for txin in new_tx.vin:
        txin.script_sig = b""
    # TODO: delete sig from script_ (even if non standard)
    new_tx.vin[vin_i].script_sig = script_
    if hash_type & 0x1F == NONE:
        new_tx.vout = []
        for i, txin in enumerate(new_tx.vin):
            if i != vin_i:
                txin.sequence = 0

    if hash_type & 0x1F == SINGLE:
        # sig_hash single bug
        if vin_i >= len(new_tx.vout):
            return (256**31).to_bytes(32, byteorder="big", signed=False)
        new_tx.vout = new_tx.vout[:vin_i + 1]
        for txout in new_tx.vout[:-1]:
            txout.script_pub_key = ScriptPubKey(b"")
            txout.value = 0xFFFFFFFFFFFFFFFF
        for i, txin in enumerate(new_tx.vin):
            if i != vin_i:
                txin.sequence = 0

    if hash_type & 0x80:
        new_tx.vin = [new_tx.vin[vin_i]]

    preimage = new_tx.serialize(include_witness=False, check_validity=False)
    preimage += hash_type.to_bytes(4, byteorder="little", signed=False)

    return hash256(preimage)
예제 #3
0
파일: tx.py 프로젝트: btclib-org/btclib
    def hash(self) -> bytes:
        """Return the transaction hash.

        It differs from tx_id for witness transactions.
        """
        serialized_ = self.serialize(include_witness=True, check_validity=False)
        hash256_ = hash256(serialized_)
        return hash256_[::-1]
예제 #4
0
def segwit_v0(script_: Octets, tx: Tx, vin_i: int, hash_type: int,
              amount: int) -> bytes:
    script_ = bytes_from_octets(script_)

    hash_prev_outs = b"\x00" * 32
    if not hash_type & ANYONECANPAY:
        hash_prev_outs = b"".join([vin.prev_out.serialize() for vin in tx.vin])
        hash_prev_outs = hash256(hash_prev_outs)

    hash_seqs = b"\x00" * 32
    if (not (hash_type & ANYONECANPAY) and (hash_type & 0x1F) != SINGLE
            and (hash_type & 0x1F) != NONE):
        hash_seqs = b"".join([
            vin.sequence.to_bytes(4, byteorder="little", signed=False)
            for vin in tx.vin
        ])
        hash_seqs = hash256(hash_seqs)

    hash_outputs = b"\x00" * 32
    if hash_type & 0x1F not in (SINGLE, NONE):
        hash_outputs = b"".join([vout.serialize() for vout in tx.vout])
        hash_outputs = hash256(hash_outputs)
    elif (hash_type & 0x1F) == SINGLE and vin_i < len(tx.vout):
        hash_outputs = hash256(tx.vout[vin_i].serialize())

    preimage = b"".join([
        tx.version.to_bytes(4, byteorder="little", signed=False),
        hash_prev_outs,
        hash_seqs,
        tx.vin[vin_i].prev_out.serialize(),
        var_bytes.serialize(script_),
        amount.to_bytes(8, byteorder="little", signed=False),  # value
        tx.vin[vin_i].sequence.to_bytes(4, byteorder="little", signed=False),
        hash_outputs,
        tx.lock_time.to_bytes(4, byteorder="little", signed=False),
        hash_type.to_bytes(4, byteorder="little", signed=False),
    ])
    return hash256(preimage)
예제 #5
0
def _assert_valid_hash256_preimages(
        hash256_preimages: Mapping[bytes, bytes]) -> None:

    for h, preimage in hash256_preimages.items():
        if hash256(preimage) != h:
            raise BTClibValueError("Invalid HASH256 preimage")
예제 #6
0
def b58encode(v: Octets, in_size: Optional[int] = None) -> bytes:
    """Encode a bytes-like object using Base58Check."""

    v = bytes_from_octets(v, in_size)
    h256 = hash256(v)
    return _b58encode(v + h256[:4])
예제 #7
0
 def id(self) -> bytes:
     "Return the transaction id."
     serialized_ = self.serialize(include_witness=False,
                                  check_validity=False)
     hash256_ = hash256(serialized_)
     return hash256_[::-1]
예제 #8
0
def test_hash160_hash256() -> None:
    test_vectors = (plain_prv_keys + net_unaware_compressed_pub_keys +
                    net_unaware_uncompressed_pub_keys)
    for hexstring in test_vectors:
        hash160(hexstring)
        hash256(hexstring)