def stream(self, f, blank_solutions=False, include_unspents=False, include_witness_data=True): """Stream a Bitcoin transaction Tx to the file-like object f. :param f: writable file-like object to stream binary data of transaction :param blank_solutions: (optional) clear out the solutions scripts, effectively "unsigning" the transaction before writing it. Defaults to False :param include_unspents: (optional) stread out the Spendable objects after streaming the transaction. This is a pycoin-specific extension. Defaults to False. :param include_witness_data: (optional) stream segwit transactions including the witness data if the transaction has any witness data. Defaults to True. """ include_witnesses = include_witness_data and self.has_witness_data() stream_struct("L", f, self.version) if include_witnesses: f.write(b'\0\1') stream_struct("I", f, len(self.txs_in)) for t in self.txs_in: t.stream(f, blank_solutions=blank_solutions) stream_struct("I", f, len(self.txs_out)) for t in self.txs_out: t.stream(f) if include_witnesses: for tx_in in self.txs_in: witness = tx_in.witness stream_struct("I", f, len(witness)) for w in witness: stream_satoshi_string(f, w) stream_struct("L", f, self.lock_time) if include_unspents and not self.missing_unspents(): self.stream_unspents(f)
def hash_for_signing(self, msg): """ Return a hash of msg, according to odd bitcoin method: double SHA256 over a bitcoin encoded stream of two strings: a fixed magic prefix and the actual message. """ magic = self.msg_magic_for_netcode() fd = io.BytesIO() stream_satoshi_string(fd, magic.encode('utf8')) stream_satoshi_string(fd, msg.encode('utf8')) # return as a number, since it's an input to signing algos like that anyway return from_bytes_32(double_sha256(fd.getvalue()))
def _segwit_signature_preimage(self, script, tx_in_idx, hash_type): f = io.BytesIO() stream_struct("L", f, self.tx.version) # calculate hash prevouts f.write(self._hash_prevouts(hash_type)) f.write(self._hash_sequence(hash_type)) tx_in = self.tx.txs_in[tx_in_idx] f.write(tx_in.previous_hash) stream_struct("L", f, tx_in.previous_index) tx_out = self.tx.unspents[tx_in_idx] stream_satoshi_string(f, script) stream_struct("Q", f, tx_out.coin_value) stream_struct("L", f, tx_in.sequence) f.write(self._hash_outputs(hash_type, tx_in_idx)) stream_struct("L", f, self.tx.lock_time) stream_struct("L", f, hash_type) return f.getvalue()