def merge_nulldatas_from_block_obj(block, block_hash, block_height, verbose=True, session=DBSession, bitcoind=bitcoind): try: if get_block_by_hash(block_hash) is not None: logging.info("already merged block %d, %s" % (block_height, block_hash)) return # we have this block already for tx_n, tx in enumerate(block.txs): for tx_out_n, tx_out in enumerate(tx.txs_out): if tx_out.script[0:1] == b'\x6a': try: script_object = script_obj_from_script(tx_out.script) except ScriptError as e: logging.warning("Found OP_RETURN tx with bad nulldata: %s, %d" % (tx.hash()[::-1], tx_out_n)) continue if type(script_object) == ScriptNulldata: id_tx_reference = tx.txs_in[0] # tx containing the identity if id_tx_reference.is_coinbase(): sender_address = 'COINBASE' else: id_tx_json = bitcoind.getrawtransaction(hexlify(id_tx_reference.previous_hash[::-1]), 1) sender_address = id_tx_json['vout'][id_tx_reference.previous_index]['scriptPubKey']['addresses'][0] session.merge(Nulldatas(in_block_hash=block_hash, txid=hexlify(tx.hash()[::-1]), script=hexlify(tx_out.script), tx_n=tx_n, tx_out_n=tx_out_n, timestamp=block.timestamp, sender=sender_address)) if verbose: logging.info("%s, %s, %s" % (script_object, tx.hash(), block_height)) session.merge(Blocks(block_hash=block_hash, height=block_height, prev_block_hash=block.previous_block_id())) except Exception as e: session.rollback() raise e else: session.commit() if verbose: logging.info('Scanned %s' % block_height)
def test_sign(self): sv = 33143560198659167577410026742586567991638126035902913554051654024377193788946 tx_out_script = b'v\xa9\x14\x91\xb2K\xf9\xf5(\x852\x96\n\xc6\x87\xab\xb05\x12{\x1d(\xa5\x88\xac' st = script_obj_from_script(tx_out_script) hl = build_hash160_lookup([1]) solution = st.solve(hash160_lookup=hl, sign_value=sv, signature_type=SIGHASH_ALL) self.assertEqual(solution, b'G0D\x02 ^=\xf5\xb5[\xe6!@\x04,"\x0b\x1f\xdf\x10\\\xc8Q\x13\xafV*!\\\x1f\xc5\xb5\xc5"\xd1\xb3\xd3\x02 8\xc9YK\x15o\xae\xd7\xf3|0\x07z\xff\xbfj\xcfB\xbf\x17\xb1\xe69\xa1\xfc\xc6\xc5\x1ag\xab\xa2\x16\x01A\x04y\xbef~\xf9\xdc\xbb\xacU\xa0b\x95\xce\x87\x0b\x07\x02\x9b\xfc\xdb-\xce(\xd9Y\xf2\x81[\x16\xf8\x17\x98H:\xdaw&\xa3\xc4e]\xa4\xfb\xfc\x0e\x11\x08\xa8\xfd\x17\xb4H\xa6\x85T\x19\x9cG\xd0\x8f\xfb\x10\xd4\xb8')
def test_recognize_multisig(self): h = '010000000139c92b102879eb95f14e7344e4dd7d481e1238b1bfb1fa0f735068d2927b231400000000910047304402208fc06d216ebb4b6a3a3e0f906e1512c372fa8a9c2a92505d04e9b451ea7acd0c0220764303bb7e514ddd77855949d941c934e9cbda8e3c3827bfdb5777477e73885b014730440220569ec6d2e81625dd18c73920e0079cdb4c1d67d3d7616759eb0c18cf566b3d3402201c60318f0a62e3ba85ca0f158d4dfe63c0779269eb6765b6fc939fc51e7a8ea901ffffffff0140787d01000000001976a914641ad5051edd97029a003fe9efb29359fcee409d88ac0000000040787d0100000000c952410496ec45f878b62c46c4be8e336dff7cc58df9b502178cc240eb3d31b1266f69f5767071aa3e017d1b82a0bb28dab5e27d4d8e9725b3e68ed5f8a2d45c730621e34104cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4410461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af53ae' f = io.BytesIO(h2b(h)) tx = Tx.parse(f) tx.parse_unspents(f) self.assertEqual(tx.id(), "10c61e258e0a2b19b245a96a2d0a1538fe81cd4ecd547e0a3df7ed6fd3761ada") the_script = tx.unspents[0].script s = script_obj_from_script(tx.unspents[0].script) self.assertEqual(s.script(), the_script)
def test_script_type_pay_to_public_pair(self): for se in range(1, 100): key = Key(secret_exponent=se) for b in [True, False]: st = ScriptPayToPublicKey.from_key(key, use_uncompressed=b) addr = key.address(use_uncompressed=b) self.assertEqual(st.address(), addr) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def test_script_type_pay_to_address(self): for se in range(1, 100): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = script_obj_from_address(addr) self.assertEqual(st.address(), addr) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def solve(self, hash160_lookup, tx_in_idx, tx_out_script, hash_type=None, **kwargs): """ Sign a standard transaction. hash160_lookup: An object with a get method that accepts a hash160 and returns the corresponding (secret exponent, public_pair, is_compressed) tuple or None if it's unknown (in which case the script will obviously not be signed). A standard dictionary will do nicely here. tx_in_idx: the index of the tx_in we are currently signing tx_out: the tx_out referenced by the given tx_in """ if hash_type is None: hash_type = self.SIGHASH_ALL tx_in = self.txs_in[tx_in_idx] is_p2h = (len(tx_out_script) == 23 and byte_to_int(tx_out_script[0]) == opcodes.OP_HASH160 and byte_to_int(tx_out_script[-1]) == opcodes.OP_EQUAL) if is_p2h: hash160 = ScriptPayToScript.from_script(tx_out_script).hash160 p2sh_lookup = kwargs.get("p2sh_lookup") if p2sh_lookup is None: raise ValueError("p2sh_lookup not set") if hash160 not in p2sh_lookup: raise ValueError("hash160=%s not found in p2sh_lookup" % b2h(hash160)) script_to_hash = p2sh_lookup[hash160] else: script_to_hash = tx_out_script # Leave out the signature from the hash, since a signature can't sign itself. # The checksig op will also drop the signatures from its hash. def signature_for_hash_type_f(hash_type, script): return self.signature_hash(script, tx_in_idx, hash_type) def witness_signature_for_hash_type(hash_type, script): return self.signature_for_hash_type_segwit(script, tx_in_idx, hash_type) witness_signature_for_hash_type.skip_delete = True signature_for_hash_type_f.witness = witness_signature_for_hash_type if tx_in.verify( tx_out_script, signature_for_hash_type_f, lock_time=self.lock_time, tx_version=self.version): return the_script = script_obj_from_script(tx_out_script) solution = the_script.solve( hash160_lookup=hash160_lookup, signature_type=hash_type, existing_script=self.txs_in[tx_in_idx].script, existing_witness=tx_in.witness, script_to_hash=script_to_hash, signature_for_hash_type_f=signature_for_hash_type_f, **kwargs) return solution
def test_sign(self): sv = 33143560198659167577410026742586567991638126035902913554051654024377193788946 tx_out_script = b'v\xa9\x14\x91\xb2K\xf9\xf5(\x852\x96\n\xc6\x87\xab\xb05\x12{\x1d(\xa5\x88\xac' st = script_obj_from_script(tx_out_script) hl = build_hash160_lookup([1]) solution = st.solve(hash160_lookup=hl, signature_for_hash_type_f=const_f(sv), signature_type=SIGHASH_ALL) self.assertEqual( solution, h2b( "47304402205e3df5b55be62140042c220b1fdf105cc85113af562a215c1fc5b5c522d1" "b3d3022038c9594b156faed7f37c30077affbf6acf42bf17b1e639a1fcc6c51a67aba2" "1601410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817" "98483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8"))
def test_solve_pay_to_address(self): for se in range(1, 10): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = script_obj_from_address(addr) self.assertEqual(st.address(), addr) hl = build_hash160_lookup([se]) sv = 100 solution = st.solve(hash160_lookup=hl, signature_for_hash_type_f=const_f(sv), signature_type=SIGHASH_ALL) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def test_solve_pay_to_public_pair(self): for se in range(1, 10): key = Key(secret_exponent=se) for b in [True, False]: addr = key.address(use_uncompressed=b) st = ScriptPayToPublicKey.from_key(key, use_uncompressed=b) self.assertEqual(st.address(), addr) hl = build_hash160_lookup([se]) sv = 100 solution = st.solve(hash160_lookup=hl, sign_value=sv, signature_type=SIGHASH_ALL) sc = st.script() st = script_obj_from_script(sc) self.assertEqual(st.address(), addr)
def script_obj_from_address(address, netcodes=None): netcode, key_type, data = netcode_and_type_for_text(address, netcodes) if key_type == 'pay_to_script': return ScriptPayToScript(hash160=data) if key_type == 'address': return ScriptPayToAddress(hash160=data) if key_type == 'address_wit': return ScriptPayToAddressWit(version=data[:1], hash160=data[2:]) if key_type == 'pay_to_script_wit': return ScriptPayToScriptWit(version=data[:1], hash256=data[2:]) if key_type == 'segwit': return script_obj_from_script(data) raise ValueError("bad text")
def test_sign(self): sv = 33143560198659167577410026742586567991638126035902913554051654024377193788946 tx_out_script = b'v\xa9\x14\x91\xb2K\xf9\xf5(\x852\x96\n\xc6\x87\xab\xb05\x12{\x1d(\xa5\x88\xac' st = script_obj_from_script(tx_out_script) hl = build_hash160_lookup([1]) solution = st.solve(hash160_lookup=hl, signature_for_hash_type_f=const_f(sv), signature_type=SIGHASH_ALL) self.assertEqual( solution, h2b("47304402205e3df5b55be62140042c220b1fdf105cc85113af562a215c1fc5b5c522d1" "b3d3022038c9594b156faed7f37c30077affbf6acf42bf17b1e639a1fcc6c51a67aba2" "1601410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f817" "98483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" ))
def who_signed_tx(tx, tx_in_idx, netcode='BTC'): """ Given a transaction (tx) an input index (tx_in_idx), attempt to figure out which addresses where used in signing (so far). This method depends on tx.unspents being properly configured. This should work on partially-signed MULTISIG transactions (it will return as many addresses as there are good signatures). Returns a list of ( address, sig_type ) pairs. Raises NoAddressesForScriptTypeError if addresses cannot be determined for the input's script. TODO: This does not yet support P2SH. """ tx_in = tx.txs_in[tx_in_idx] parent_tx_out_idx = tx_in.previous_index parent_tx_out_script = tx.unspents[tx_in_idx].script script_obj = script_obj_from_script(parent_tx_out_script) signed_by = [] if type(script_obj) not in (ScriptPayToAddress, ScriptPayToPublicKey, ScriptMultisig): raise NoAddressesForScriptTypeError( 'unable to determine signing addresses for script type of parent tx {}[{}]' .format(b2h_rev(tx_in.previous_hash), parent_tx_out_idx)) script = tx_in.script pc = 0 while pc < len(script): opcode, data, pc = get_opcode(script, pc) if data is None: continue try: sig_pair, sig_type = parse_signature_blob(data) except (ValueError, TypeError, binascii.Error, UnexpectedDER): continue sig_hash = tx.signature_hash(parent_tx_out_script, parent_tx_out_idx, sig_type) for sec_key in script_obj.sec_keys: public_pair = sec_to_public_pair(sec_key) if ecdsa_verify(generator_secp256k1, public_pair, sig_hash, sig_pair): addr_pfx = address_prefix_for_netcode(netcode) addr = public_pair_to_bitcoin_address(public_pair, address_prefix=addr_pfx) signed_by.append((addr, sig_type)) return signed_by
def signTx(tx, pre_out_ids=[]): pubkey_addr = '' outscript = r'' for pre_out_id in pre_out_ids: if '' != pre_out_id: pre_out = TransactionOutDao.searchById(pre_out_id) pubkey_addr = pre_out.address() outscript = pre_out.script if '' != pubkey_addr: secretKey = SecretKeyDao.searchByPubAddr(pubkey_addr) key = Key( public_pair=[int(secretKey.publicKey), int(secretKey.privateKey)]) tx.sign({ script_obj_from_script(outscript).hash160: [secretKey.sec_num, key.public_pair(), True], }) return tx
def sign_tx_in(self, hash160_lookup, tx_in_idx, tx_out_script, hash_type=SIGHASH_ALL, **kwargs): tx_in = self.txs_in[tx_in_idx] is_p2h = (len(tx_out_script) == 23 and byte_to_int(tx_out_script[0]) == opcodes.OP_HASH160 and byte_to_int(tx_out_script[-1]) == opcodes.OP_EQUAL) script_to_hash = tx_out_script if is_p2h: hash160 = ScriptPayToScript.from_script(tx_out_script).hash160 p2sh_lookup = kwargs.get("p2sh_lookup") if p2sh_lookup is None: raise ValueError("p2sh_lookup not set") if hash160 not in p2sh_lookup: raise ValueError("hash160=%s not found in p2sh_lookup" % b2h(hash160)) script_to_hash = p2sh_lookup[hash160] signature_for_hash_type_f = lambda hash_type: self.signature_hash( tx_out_script, tx_in_idx, hash_type) if tx_in.verify(tx_out_script, signature_for_hash_type_f, lock_time=kwargs.get('lock_time')): return sign_value = self.signature_hash(script_to_hash, tx_in_idx, hash_type=hash_type) the_script = script_obj_from_script(tx_out_script) solution = the_script.solve(hash160_lookup=hash160_lookup, sign_value=sign_value, signature_type=hash_type, existing_script=self.txs_in[tx_in_idx].script, **kwargs) tx_in.script = solution
def sign_tx_in(self, hash160_lookup, tx_in_idx, tx_out_script, hash_type=SIGHASH_ALL, **kwargs): tx_in = self.txs_in[tx_in_idx] is_p2h = (len(tx_out_script) == 23 and byte_to_int(tx_out_script[0]) == opcodes.OP_HASH160 and byte_to_int(tx_out_script[-1]) == opcodes.OP_EQUAL) script_to_hash = tx_out_script if is_p2h: hash160 = ScriptPayToScript.from_script(tx_out_script).hash160 p2sh_lookup = kwargs.get("p2sh_lookup") if p2sh_lookup is None: raise ValueError("p2sh_lookup not set") if hash160 not in p2sh_lookup: raise ValueError("hash160=%s not found in p2sh_lookup" % b2h(hash160)) script_to_hash = p2sh_lookup[hash160] signature_for_hash_type_f = lambda hash_type: self.signature_hash(tx_out_script, tx_in_idx, hash_type) if tx_in.verify(tx_out_script, signature_for_hash_type_f): return sign_value = self.signature_hash(script_to_hash, tx_in_idx, hash_type=hash_type) the_script = script_obj_from_script(tx_out_script) solution = the_script.solve(hash160_lookup=hash160_lookup, sign_value=sign_value, signature_type=hash_type,existing_script=self.txs_in[tx_in_idx].script, **kwargs) tx_in.script = solution
def address(self, netcode=None): # attempt to return the destination address, or None on failure return script_obj_from_script(self.script).address(netcode=netcode)
def hash160(self): # attempt to return the destination hash160, or None on failure info = script_obj_from_script(self.script).info() return info.get("hash160")
def test_weird_tx(self): # this is from tx 12a8d1d62d12307eac6e62f2f14d7e826604e53c320a154593845aa7c8e59fbf st = script_obj_from_script(b'Q') self.assertNotEqual(st, None)