def update_signatures(self, signatures): """Add new signatures to a transaction `signatures` is expected to be a list of binary sigs with signatures[i] intended for self._inputs[i], without the SIGHASH appended. This is used by hardware device code. """ if self.is_complete(): return if len(self.inputs()) != len(signatures): raise RuntimeError('expected {} signatures; got {}'.format( len(self.inputs()), len(signatures))) for i, txin in enumerate(self.inputs()): pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin) sig = bh2u(signatures[i] + bytes([self.nHashType() & 255])) logger.warning(f'Signature {i}: {sig}') if sig in txin.get('signatures'): continue pre_hash = self.preimage_hash(i) rec_sig_base = der_signature_to_compact(signatures[i]) for recid in range(4): rec_sig = rec_sig_base + bytes([recid]) try: public_key = PublicKey.from_recoverable_signature( rec_sig, pre_hash, None) except (InvalidSignatureError, ValueError): # the point might not be on the curve for some recid values continue # public key is compressed pubkey_hex = public_key.to_hex() if pubkey_hex in pubkeys: try: public_key.verify_recoverable_signature( rec_sig, pre_hash, None) except Exception: logger.exception('') continue j = pubkeys.index(pubkey_hex) logger.debug(f'adding sig {i} {j} {pubkey_hex} {sig}') self.add_signature_to_txin(i, j, sig) break # redo raw self.raw = self.serialize()
def update_signatures(self, signatures): """Add new signatures to a transaction `signatures` is expected to be a list of binary sigs with signatures[i] intended for self.inputs[i], without the SIGHASH appended. This is used by hardware device code. """ if self.is_complete(): return if len(self.inputs) != len(signatures): raise RuntimeError('expected {} signatures; got {}'.format( len(self.inputs), len(signatures))) for txin, signature in zip(self.inputs, signatures): full_sig = signature + bytes([self.nHashType()]) logger.warning(f'Signature: {full_sig.hex()}') if full_sig in txin.signatures: continue pubkeys = [x_pubkey.to_public_key() for x_pubkey in txin.x_pubkeys] pre_hash = self.preimage_hash(txin) rec_sig_base = der_signature_to_compact(signature) for recid in range(4): rec_sig = rec_sig_base + bytes([recid]) try: public_key = PublicKey.from_recoverable_signature( rec_sig, pre_hash, None) except (InvalidSignatureError, ValueError): # the point might not be on the curve for some recid values continue if public_key in pubkeys: try: public_key.verify_recoverable_signature( rec_sig, pre_hash, None) except Exception: logger.exception('') continue j = pubkeys.index(public_key) logger.debug(f'adding sig {j} {public_key} {full_sig}') txin.signatures[j] = full_sig break