예제 #1
0
 def hash_prevouts(self):
     if self._hash_prevouts is None:
         all_prevouts = b""
         all_sequence = b""
         for tx_in in self.tx_ins:
             all_prevouts += tx_in.prev_tx[::-1] + int_to_little_endian(
                 tx_in.prev_index, 4)
             all_sequence += tx_in.sequence.serialize()
         self._hash_prevouts = hash256(all_prevouts)
         self._hash_sequence = hash256(all_sequence)
     return self._hash_prevouts
예제 #2
0
 def hash_outputs(self):
     if self._hash_outputs is None:
         all_outputs = b""
         for tx_out in self.tx_outs:
             all_outputs += tx_out.serialize()
         self._hash_outputs = hash256(all_outputs)
     return self._hash_outputs
예제 #3
0
 def check_pow(self):
     """Returns whether this block satisfies proof of work"""
     # get the hash256 of the serialization of this block
     h256 = hash256(self.serialize())
     # interpret this hash as a little-endian number
     proof = little_endian_to_int(h256)
     # return whether this integer is less than the target
     return proof < self.target()
예제 #4
0
 def hash(self):
     """Returns the hash256 interpreted little endian of the block"""
     # serialize
     s = self.serialize()
     # hash256
     h256 = hash256(s)
     # reverse
     return h256[::-1]
예제 #5
0
 def sig_hash_bip143(
     self,
     input_index,
     redeem_script=None,
     witness_script=None,
     hash_type=SIGHASH_ALL,
 ):
     """Returns the integer representation of the hash that needs to get
     signed for index input_index"""
     # grab the input being signed by looking up the input_index
     tx_in = self.tx_ins[input_index]
     # start with the version in 4 bytes, little endian
     s = int_to_little_endian(self.version, 4)
     # add the HashPrevouts and HashSequence
     if hash_type & SIGHASH_ANYONECANPAY != SIGHASH_ANYONECANPAY:
         s += self.hash_prevouts()
     if hash_type & SIGHASH_ANYONECANPAY != SIGHASH_ANYONECANPAY and (
             hash_type & 3) not in (SIGHASH_SINGLE, SIGHASH_NONE):
         s += self.hash_sequence()
     # add the previous transaction hash in little endian
     s += tx_in.prev_tx[::-1]
     # add the previous transaction index in 4 bytes, little endian
     s += int_to_little_endian(tx_in.prev_index, 4)
     # for p2wpkh, we need to compute the ScriptCode
     # Exercise 1: account for p2wsh. Check first for the existence of a WitnessScript
     if witness_script:
         # for p2wsh and p2sh-p2wsh the ScriptCode is the WitnessScript
         script_code = witness_script
     elif redeem_script:
         # for p2sh-p2wpkh, get the hash160 which is the 2nd command of the RedeemScript
         h160 = redeem_script.commands[1]
         # the ScriptCode is the P2PKHScriptPubKey created using the hash160
         script_code = P2PKHScriptPubKey(h160)
     else:
         # get the script pubkey associated with the previous output (remember network)
         script_pubkey = tx_in.script_pubkey(self.network)
         # next get the hash160 in the script_pubkey. for p2wpkh, it's the second command
         h160 = script_pubkey.commands[1]
         # finally the ScriptCode is the P2PKHScriptPubKey created using the hash160
         script_code = P2PKHScriptPubKey(h160)
     # add the serialized ScriptCode
     s += script_code.serialize()
     # add the value of the input in 8 bytes, little endian
     s += int_to_little_endian(tx_in.value(network=self.network), 8)
     # add the sequence of the input in 4 bytes, little endian
     s += tx_in.sequence.serialize()
     # add the HashOutputs
     if (hash_type & 3) not in (SIGHASH_SINGLE, SIGHASH_NONE):
         s += self.hash_outputs()
     elif hash_type & SIGHASH_SINGLE == SIGHASH_SINGLE:
         s += self.tx_outs[input_index].serialize()
     # add the locktime in 4 bytes, little endian
     s += self.locktime.serialize()
     # add the sighash (SIGHASH_ALL) in 4 bytes, little endian
     s += int_to_little_endian(hash_type, 4)
     # hash256 the whole thing, interpret the as a big endian integer using int_to_big_endian
     return big_endian_to_int(hash256(s))
예제 #6
0
 def verify_message(self, message, sig):
     """Verify a message in the form of bytes. Assumes that the z
     is calculated using hash256 interpreted as a big-endian integer"""
     # calculate the hash256 of the message
     h256 = hash256(message)
     # z is the big-endian interpretation. use big_endian_to_int
     z = big_endian_to_int(h256)
     # verify the message using the self.verify method
     return self.verify(z, sig)
예제 #7
0
 def sign_message(self, message):
     """Sign a message in the form of bytes instead of the z. The z should
     be assumed to be the hash256 of the message interpreted as a big-endian
     integer."""
     # compute the hash256 of the message
     h256 = hash256(message)
     # z is the big-endian interpretation. use big_endian_to_int
     z = big_endian_to_int(h256)
     # sign the message using the self.sign method
     return self.sign(z)
예제 #8
0
 def __init__(self, filter_type, stop_hash, previous_filter_header,
              filter_hashes):
     self.filter_type = filter_type
     self.stop_hash = stop_hash
     self.previous_filter_header = previous_filter_header
     self.filter_hashes = filter_hashes
     current = self.previous_filter_header
     for filter_hash in self.filter_hashes:
         current = hash256(filter_hash + current)
     self.last_header = current
예제 #9
0
 def serialize(self):
     """Returns the byte serialization of the entire network message"""
     # add the network magic using self.magic
     result = self.magic
     # command 12 bytes, fill leftover with b'\x00' * (12 - len(self.command))
     result += self.command + b"\x00" * (12 - len(self.command))
     # payload length 4 bytes, little endian
     result += int_to_little_endian(len(self.payload), 4)
     # checksum 4 bytes, first four of hash256 of payload
     result += hash256(self.payload)[:4]
     # payload
     result += self.payload
     return result
예제 #10
0
 def fetch(cls, tx_id, network="mainnet", fresh=False):
     if fresh or (tx_id not in cls.cache):
         url = "{}/tx/{}/hex".format(cls.get_url(network), tx_id)
         req = Request(url, headers={"User-Agent": "Mozilla/5.0"})
         response = urlopen(req).read().decode("utf-8").strip()
         try:
             raw = bytes.fromhex(response)
         except ValueError:
             raise ValueError(f"unexpected response: {response}")
         tx = Tx.parse(BytesIO(raw), network=network)
         # make sure the tx we got matches to the hash we requested
         if tx.segwit:
             computed = tx.id()
         else:
             computed = hash256(raw)[::-1].hex()
         if computed != tx_id:
             raise RuntimeError(f"server lied: {computed} vs {tx_id}")
         cls.cache[tx_id] = tx
     cls.cache[tx_id].network = network
     return cls.cache[tx_id]
예제 #11
0
 def parse(cls, s, network="mainnet"):
     """Takes a stream and creates a NetworkEnvelope"""
     # check the network magic
     magic = s.read(4)
     if magic == b"":
         raise RuntimeError("Connection reset!")
     expected_magic = MAGIC[network]
     if magic != expected_magic:
         raise RuntimeError("magic is not right {} vs {}".format(
             magic.hex(), expected_magic.hex()))
     # command 12 bytes, strip the trailing 0's using .strip(b'\x00')
     command = s.read(12).strip(b"\x00")
     # payload length 4 bytes, little endian
     payload_length = little_endian_to_int(s.read(4))
     # checksum 4 bytes, first four of hash256 of payload
     checksum = s.read(4)
     # payload is of length payload_length
     payload = s.read(payload_length)
     # verify checksum
     calculated_checksum = hash256(payload)[:4]
     if calculated_checksum != checksum:
         raise RuntimeError("checksum does not match")
     return cls(command, payload, network=network)
예제 #12
0
 def hash(self):
     return hash256(self.filter_bytes)
예제 #13
0
 def hash(self):
     return hash256(self.serialize())
예제 #14
0
 def hash(self):
     """Binary hash of the legacy serialization"""
     return hash256(self.serialize_legacy())[::-1]
예제 #15
0
def op_hash256(stack):
    if len(stack) < 1:
        return False
    element = stack.pop()
    stack.append(hash256(element))
    return True
예제 #16
0
def _calculate_msig_digest(quorum_m, root_xfp_hexes):
    fingerprints_to_hash = "-".join(sorted(root_xfp_hexes))
    return hash256(f"{quorum_m}:{fingerprints_to_hash}".encode()).hex()
예제 #17
0
    def sig_hash_legacy(self,
                        input_index,
                        redeem_script=None,
                        hash_type=SIGHASH_ALL):
        """Returns the integer representation of the hash that needs to get
        signed for index input_index"""

        # consensus bugs related to invalid input indices
        DEFAULT = 1 << 248
        if input_index >= len(self.tx_ins):
            return DEFAULT
        elif hash_type & 3 == SIGHASH_SINGLE and input_index >= len(
                self.tx_outs):
            return DEFAULT
        # create the serialization per spec
        # start with version: int_to_little_endian in 4 bytes
        s = int_to_little_endian(self.version, 4)
        # next, how many inputs there are: encode_varint
        s += encode_varint(len(self.tx_ins))
        # loop through each input: for i, tx_in in enumerate(self.tx_ins)
        for i, tx_in in enumerate(self.tx_ins):
            sequence = tx_in.sequence
            # if the input index is the one we're signing
            if i == input_index:
                # if the RedeemScript was passed in, that's the ScriptSig
                if redeem_script:
                    script_sig = redeem_script
                # otherwise the previous tx's ScriptPubkey is the ScriptSig
                else:
                    script_sig = tx_in.script_pubkey(self.network)
            # Otherwise, the ScriptSig is empty
            else:
                script_sig = None
                if hash_type & 3 in (SIGHASH_NONE, SIGHASH_SINGLE):
                    sequence = Sequence(0)
            # create a TxIn object with the prev_tx, prev_index and sequence
            # the same as the current tx_in and the script_sig from above
            new_tx_in = TxIn(
                prev_tx=tx_in.prev_tx,
                prev_index=tx_in.prev_index,
                script_sig=script_sig,
                sequence=sequence,
            )
            # add the serialization of the TxIn object
            if hash_type & SIGHASH_ANYONECANPAY:
                if i == input_index:
                    s += new_tx_in.serialize()
            else:
                s += new_tx_in.serialize()
        # add how many outputs there are using encode_varint
        s += encode_varint(len(self.tx_outs))
        # add the serialization of each output
        for i, tx_out in enumerate(self.tx_outs):
            if hash_type & 3 == SIGHASH_NONE:
                continue
            elif hash_type & 3 == SIGHASH_SINGLE:
                if i == input_index:
                    s += tx_out.serialize()
                    break
                else:
                    s += b"\xff\xff\xff\xff\xff\xff\xff\xff\x00"
            else:
                s += tx_out.serialize()
        # add the locktime using int_to_little_endian in 4 bytes
        s += self.locktime.serialize()
        # add SIGHASH_ALL using int_to_little_endian in 4 bytes
        s += int_to_little_endian(hash_type, 4)
        # hash256 the serialization
        h256 = hash256(s)
        # convert the result to an integer using big_endian_to_int(x)
        return big_endian_to_int(h256)