Ejemplo n.º 1
0
    def _hash_outputs(self, index, sighash_type):
        '''BIP143 hashOutputs implementation

        Args:
            index        (int): index of input being signed
            sighash_type (int): SIGHASH_SINGLE or SIGHASH_ALL
        Returns:
            (bytes): the hashOutputs, a 32 byte hash
        '''
        if sighash_type == shared.SIGHASH_ALL:
            # If the sighash type is ALL,
            # hashOutputs is the double SHA256 of all output amounts
            # paired up with their scriptPubKey;
            outputs = ByteData()
            for tx_out in self.tx_outs:
                outputs += tx_out.to_bytes()
            return utils.hash256(outputs.to_bytes())
        elif (sighash_type == shared.SIGHASH_SINGLE
              and index < len(self.tx_outs)):
            # if sighash type is SINGLE
            # and the input index is smaller than the number of outputs,
            # hashOutputs is the double SHA256 of the output at the same index
            return utils.hash256(self.tx_outs[index].to_bytes())
        else:
            # Otherwise, hashOutputs is a uint256 of 0x0000......0000
            raise NotImplementedError(
                'I refuse to implement the SIGHASH_SINGLE bug.')
Ejemplo n.º 2
0
    def _sighash_final_hashing(self, copy_tx, sighash_type):
        '''
        Tx, int -> bytes
        Returns the hash that should be signed
        https://en.bitcoin.it/wiki/OP_CHECKSIG#Procedure_for_Hashtype_SIGHASH_ANYONECANPAY
        '''
        sighash = ByteData()
        sighash += copy_tx.to_bytes()
        sighash += utils.i2le_padded(sighash_type, 4)

        return utils.hash256(sighash.to_bytes())
Ejemplo n.º 3
0
 def _hash_prevouts(self, anyone_can_pay):
     if anyone_can_pay:
         # If the ANYONECANPAY flag is set,
         # hashPrevouts is a uint256 of 0x0000......0000.
         hash_prevouts = b'\x00' * 32
     else:
         # hashPrevouts is the double SHA256 of all outpoints;
         outpoints = ByteData()
         for tx_in in self.tx_ins:
             outpoints += tx_in.outpoint
         hash_prevouts = utils.hash256(outpoints.to_bytes())
     return hash_prevouts
Ejemplo n.º 4
0
    def segwit_sighash(self,
                       index: int,
                       sighash_type: int,
                       prevout_value: bytes,
                       script: bytes,
                       anyone_can_pay: bool = False) -> bytes:
        '''
        Implements bip143 (witness) sighash. Prefer calling `sighash_all` or
        `sighash_single`.

        For documentation see here:
        https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

        For an excellent pasta dinner, see here:
        https://ricette.giallozafferano.it/Spaghetti-alla-Norma.html
        '''
        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += script

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._segwit_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
Ejemplo n.º 5
0
    def _sighash_forkid(
            self,
            index: int,
            script: bytes,
            prevout_value: bytes,
            sighash_type: int,
            anyone_can_pay: bool = False):
        '''
        Tx, int, byte-like, byte-like, int, bool -> bytes
        https://github.com/bitcoincashorg/spec/blob/master/replay-protected-sighash.md
        '''
        self.validate_bytes(prevout_value, 8)

        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += script

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._forkid_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
Ejemplo n.º 6
0
    def segwit_sighash(self,
                       index,
                       script,
                       prevout_value=None,
                       sighash_type=None,
                       anyone_can_pay=False):
        '''
        this function sets up sighash in BIP143 style
        https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
        https://ricette.giallozafferano.it/Spaghetti-alla-Norma.html
        '''
        data = ByteData()

        # 1. nVersion of the transaction (4-byte little endian)
        data += self.version

        # 2. hashPrevouts (32-byte hash)
        data += self._hash_prevouts(anyone_can_pay=anyone_can_pay)

        # 3. hashSequence (32-byte hash)
        data += self._hash_sequence(sighash_type=sighash_type,
                                    anyone_can_pay=anyone_can_pay)

        # 4. outpoint (32-byte hash + 4-byte little endian)
        data += self.tx_ins[index].outpoint

        # 5. scriptCode of the input (serialized as scripts inside CTxOuts)
        data += self._adjusted_script_code(script=script)

        # 6. value of the output spent by this input (8-byte little endian)
        data += prevout_value

        # 7. nSequence of the input (4-byte little endian)
        data += self.tx_ins[index].sequence

        # 8. hashOutputs (32-byte hash)
        data += self._hash_outputs(index=index, sighash_type=sighash_type)

        # 9. nLocktime of the transaction (4-byte little endian)
        data += self.lock_time

        # 10. sighash type of the signature (4-byte little endian)
        data += self._segwit_sighash_adjustment(sighash_type=sighash_type,
                                                anyone_can_pay=anyone_can_pay)

        return utils.hash256(data.to_bytes())
Ejemplo n.º 7
0
    def _hash_sequence(self, sighash_type, anyone_can_pay):
        '''BIP143 hashSequence implementation

        Args:
            sighash_type    (int): SIGHASH_SINGLE or SIGHASH_ALL
            anyone_can_pay (bool): true if ANYONECANPAY should be set
        Returns:
            (bytes): the hashSequence, a 32 byte hash
        '''
        if anyone_can_pay or sighash_type == shared.SIGHASH_SINGLE:
            # If any of ANYONECANPAY, SINGLE sighash type is set,
            # hashSequence is a uint256 of 0x0000......0000.
            return b'\x00' * 32
        else:
            # hashSequence is the double SHA256 of nSequence of all inputs;
            sequences = ByteData()
            for tx_in in self.tx_ins:
                sequences += tx_in.sequence
            return utils.hash256(sequences.to_bytes())