def get_unspent_testnet(cls, address): # Get current block height: r_block = requests.get(cls.TEST_ENDPOINT + 'blocks/tip/height', timeout=DEFAULT_TIMEOUT) if r_block.status_code != 200: # pragma: no cover raise ConnectionError block_height = int(r_block.text) r = requests.get(cls.TEST_UNSPENT_API.format(address), timeout=DEFAULT_TIMEOUT) if r.status_code == 400: # pragma: no cover return [] elif r.status_code != 200: # pragma: no cover raise ConnectionError script_pubkey = bytes_to_hex(address_to_scriptpubkey(address)) return [ Unspent( tx["value"], block_height - tx["status"]["block_height"] + 1 if tx["status"]["confirmed"] else 0, script_pubkey, tx["txid"], tx["vout"], ) for tx in r.json() ]
def get_unspent(cls, address): # Get current block height: r_block = requests.get(cls.MAIN_ENDPOINT + 'blocks/tip/height', timeout=DEFAULT_TIMEOUT) if r_block.status_code != 200: # pragma: no cover raise ConnectionError block_height = int(r_block.text) r = requests.get(cls.MAIN_UNSPENT_API.format(address), timeout=DEFAULT_TIMEOUT) #! BlockstreamAPI blocks addresses with "too many" UTXOs. if r.status_code == 400 and r.text == "Too many history entries": raise ExcessiveAddress elif r.status_code != 200: # pragma: no cover raise ConnectionError script_pubkey = bytes_to_hex(address_to_scriptpubkey(address)) return sorted( [ Unspent( tx["value"], block_height - tx["status"]["block_height"] + 1 if tx["status"]["confirmed"] else 0, script_pubkey, tx["txid"], tx["vout"], ) for tx in r.json() ], key=lambda u: u.confirmations, )
def test_init_default(self): key1 = PrivateKeyTestnet() key2 = PrivateKeyTestnet() multisig = MultiSigTestnet(key1, [key1.public_key, key2.public_key], 2) assert multisig._address is None assert multisig.balance == 0 assert multisig.unspents == [] assert multisig.transactions == [] assert multisig.m == 2 multisig2 = MultiSigTestnet(key2, [bytes_to_hex(key1.public_key), bytes_to_hex(key2.public_key)], 2) assert multisig2._address is None assert multisig2.balance == 0 assert multisig2.unspents == [] assert multisig2.transactions == [] assert multisig2.m == 2
def read_var_int(): pos[0] += 1 val = int(bytes_to_hex(txhex[pos[0] - 1:pos[0]]), base=16) if val < 253: return val return read_as_int(pow(2, val - 252))
def creaChiavi(self): chiave1 = self.lnChiave1.text() chiave2 = self.lnChiave2.text() priv = hashlib.sha256(chiave2.encode('utf-8')).hexdigest() if (chiave1 == "m"): key = bit.Key.from_hex(priv) else: key = bit.PrivateKeyTestnet.from_hex(priv) hashkey = hashlib.sha256(key.public_key).digest() ripemd160 = hashlib.new("ripemd160") ripemd160.update(hashkey) keyhash = ripemd160.digest() self.lnPrivateKey.setText( key.to_hex()) #print("Private Key: ", key.to_hex()) self.lnPublicKey.setText( utils.bytes_to_hex(key.public_key, True) ) #print("Public Key: ", utils.bytes_to_hex(key.public_key, True)) self.lnKeyHash.setText( keyhash.hex() + " (ripemd160(sha256(pub)))" ) #print("KeyHas: ", keyhash.hex(), "(ripemd160(sha256(pub)))") self.lnWif.setText( key.to_wif()) #print("WIF: ", key.to_wif()) self.lnAddress.setText( key.address + " P2PKH") #print("Address: ", key.address, "P2PKH") self.lnSegwit.setText( key.segwit_address ) #print("SegWit Addr: ", key.segwit_address) if (chiave1 == "m"): bech = bech32.encode('bc', 0, keyhash) else: bech = bech32.encode('tb', 0, keyhash) self.lnBech32.setText(bech) #print("Bech32 Addr: ", bech) #Abilita tutti i pulsanti per copiare nella Clipboard self.btnClipboard_1.setEnabled(True) self.btnClipboard_2.setEnabled(True) self.btnClipboard_3.setEnabled(True) self.btnClipboard_4.setEnabled(True) self.btnClipboard_5.setEnabled(True) self.btnClipboard_6.setEnabled(True) self.btnClipboard_7.setEnabled(True)
def create_p2pkh_transaction(private_key, unspents, outputs): public_key = private_key.public_key public_key_len = len(public_key).to_bytes(1, byteorder='little') version = VERSION_1 lock_time = LOCK_TIME sequence = SEQUENCE hash_type = HASH_TYPE input_count = int_to_unknown_bytes(len(unspents), byteorder='little') output_count = int_to_unknown_bytes(len(outputs), byteorder='little') output_block = construct_output_block(outputs) # Optimize for speed, not memory, by pre-computing values. inputs = [] for unspent in unspents: script = hex_to_bytes(unspent.script) script_len = int_to_unknown_bytes(len(script), byteorder='little') txid = hex_to_bytes(unspent.txid)[::-1] txindex = unspent.txindex.to_bytes(4, byteorder='little') inputs.append(TxIn(script, script_len, txid, txindex)) for i, txin in enumerate(inputs): hashed = sha256(version + input_count + b''.join(ti.txid + ti.txindex + OP_0 + sequence for ti in islice(inputs, i)) + txin.txid + txin.txindex + txin.script_len + txin.script + sequence + b''.join(ti.txid + ti.txindex + OP_0 + sequence for ti in islice(inputs, i + 1, None)) + output_count + output_block + lock_time + hash_type) signature = private_key.sign(hashed) + b'\x01' script_sig = (len(signature).to_bytes(1, byteorder='little') + signature + public_key_len + public_key) txin.script = script_sig txin.script_len = int_to_unknown_bytes(len(script_sig), byteorder='little') return bytes_to_hex(version + input_count + construct_input_block(inputs) + output_count + output_block + lock_time)
def main(): # echo -n "Satoshi Nakamoto" | sha256sum # key = bit.Key.from_hex('a0dc65ffca799873cbea0ac274015b9526505daaaed385155425f7337704883e') # key = bit.Key.from_bytes(b'Satoshi Nakamoto') seed = ''.join(sys.argv[1:]) priv = hashlib.sha256(seed.encode('utf-8')).hexdigest() key = bit.Key.from_hex(priv) #priv="a0dc65ffca799873cbea0ac274015b9526505daaaed385155425f7337704883e" #key = bit.Key.from_hex(priv) ''' print("Private key: ", priv) print("Public key: ", utils.bytes_to_hex(key.public_key, True)) print("WIF: ", key.to_wif()) print("Address: ", key.address) ''' print(priv + ";" + utils.bytes_to_hex(key.public_key, True) + ";" + key.to_wif() + ";" + key.address)
def wif_to_hex(wif): private_key = b58decode_check(wif) version = private_key[:1] if version == MAIN_PRIVATE_KEY: version = 'main' elif version == TEST_PRIVATE_KEY: version = 'test' else: raise ValueError('{} does not correspond to a mainnet nor ' 'testnet address.'.format(private_key[:1])) # Remove version byte and, if present, compression flag. if len(wif) == 52 and private_key[-1] == 1: private_key, compressed = private_key[1:-1], True else: private_key, compressed = private_key[1:], False return bytes_to_hex(private_key), compressed, version
def __init__(self, script, txid, txindex, witness=b'', amount=0, sequence=SEQUENCE, segwit=False): self.script = script self.script_len = int_to_varint(len(script)) self.txid = txid self.txindex = txindex self.witness = witness if amount == 0 and segwit: amount = NetworkAPI.get_tx_amount( bytes_to_hex(self.txid[::-1]), int.from_bytes(self.txindex, byteorder='little')).to_bytes( 8, byteorder='little') self.amount = amount self.sequence = sequence self.segwit = segwit
def to_hex(self): return bytes_to_hex(bytes(self))
def sign_tx(private_key, tx, *, unspents): """Signs inputs in provided transaction object for which unspents are provided and can be signed by the private key. :param private_key: Private key :type private_key: ``PrivateKey`` or ``MultiSig`` :param tx: Transaction object :type tx: ``TxObj`` :param unspents: For inputs to be signed their corresponding Unspent objects must be provided. :returns: The signed transaction as hex. :rtype: ``str`` """ # input_dict contains those unspents that can be signed by private_key, # providing additional information for segwit-inputs (the amount to spend) input_dict = {} try: for unspent in unspents: if not private_key.can_sign_unspent(unspent): continue tx_input = hex_to_bytes(unspent.txid)[::-1] + \ unspent.txindex.to_bytes(4, byteorder='little') input_dict[tx_input] = unspent.to_dict() except TypeError: raise ValueError('Please provide as unspents at least all inputs to ' 'be signed with the function call.') # Determine input indices to sign from input_dict (allows for transaction batching) sign_inputs = [ j for j, i in enumerate(tx.TxIn) if i.txid + i.txindex in input_dict ] segwit_tx = TxObj.is_segwit(tx) public_key = private_key.public_key public_key_push = script_push(len(public_key)) hash_type = HASH_TYPE # Make input parameters for preimage calculation inputs_parameters = [] for i in sign_inputs: # Create transaction object for preimage calculation tx_input = tx.TxIn[i].txid + tx.TxIn[i].txindex segwit_input = input_dict[tx_input]['segwit'] tx.TxIn[i].segwit_input = segwit_input # For partially signed transaction we must extract the signatures: input_script_field = tx.TxIn[i].script_sig script_code = private_key.scriptcode script_code_len = int_to_varint(len(script_code)) # Use scriptCode for preimage calculation of transaction object: tx.TxIn[i].script_sig = script_code tx.TxIn[i].script_sig_len = script_code_len if segwit_input: try: tx.TxIn[i].script_sig += input_dict[tx_input]['amount']\ .to_bytes(8, byteorder='little') # For partially signed transaction we must extract the # signatures: input_script_field = tx.TxIn[i].witness except Attributerror: raise ValueError( 'Cannot sign a segwit input when the input\'s amount is ' 'unknown. Maybe no network connection or the input is ' 'already spent? Then please provide all inputs to sign as ' '`Unspent` objects to the function call.') inputs_parameters.append([i, hash_type, segwit_input]) preimages = calculate_preimages(tx, inputs_parameters) # Calculate signature scripts: for hash, (i, _, segwit_input) in zip(preimages, inputs_parameters): signature = private_key.sign(hash) + b'\x01' # ------------------------------------------------------------------ if (private_key.instance == 'MultiSig' or private_key.instance == 'MultiSigTestnet'): # P2(W)SH input script_blob = b'' sigs = {} # Initial number of witness items (OP_0 + one signature + redeemscript). witness_count = 3 if input_script_field: sig_list = get_signatures_from_script(input_script_field) # Bitcoin Core convention: Every missing signature is denoted # by 0x00. Only used for already partially-signed scriptSigs: script_blob += b'\x00' * (private_key.m - len(sig_list) - 1) # Total number of witness items when partially or fully signed: witness_count = private_key.m + 2 # For a partially signed input make a dictionary containing # all the provided signatures with public-keys as keys: for sig in sig_list: for pub in private_key.public_keys: if verify_sig(sig[:-1], hash, hex_to_bytes(pub)): # If we already found a valid signature for pubkey # we just overwrite it and don't care. sigs[pub] = sig if len(sigs) == private_key.m: raise TypeError('Transaction is already signed with ' 'sufficiently needed signatures.') elif len(sigs) > private_key.m: raise TypeError('Transaction already contains {} ' 'signatures, but only {} needed.').format( len(sigs), private_key.m) sigs[bytes_to_hex(public_key)] = signature witness = b'' # Sort ingthe signatures according to the public-key list: for pub in private_key.public_keys: if pub in sigs: sig = sigs[pub] length = int_to_varint(len(sig)) if segwit_input else \ script_push(len(sig)) witness += length + sig script_sig = b'\x22' + private_key.segwit_scriptcode witness = (int_to_varint(witness_count) if segwit_input else b'') \ + b'\x00' + witness + script_blob witness += (int_to_varint(len(private_key.redeemscript)) if segwit_input else script_push(len(private_key.redeemscript))) \ + private_key.redeemscript script_sig = script_sig if segwit_input else witness witness = witness if segwit_input else b'\x00' if segwit_tx else b'' # ------------------------------------------------------------------ else: # P2(W)PKH input script_sig = b'\x16' + private_key.segwit_scriptcode witness = ((b'\x02' if segwit_input else b'') + # witness counter len(signature).to_bytes(1, byteorder='little') + signature + public_key_push + public_key) script_sig = script_sig if segwit_input else witness witness = witness if segwit_input else b'\x00' if segwit_tx else b'' # Providing the signature(s) to the input tx.TxIn[i].script_sig = script_sig tx.TxIn[i].script_sig_len = int_to_varint(len(script_sig)) tx.TxIn[i].witness = witness return tx.to_hex()
def create_sweep_transaction(private_keys, destination_address, amount=None, currency='satoshi', fee=None, leftover=None, message=None, compressed=True): private_key_map = {} unspents = [] for key in private_keys: utxos = key.get_unspents() unspents += utxos for utx in utxos: private_key_map[utx.txid] = key version = VERSION_1 lock_time = LOCK_TIME sequence = SEQUENCE hash_type = HASH_TYPE input_count = int_to_unknown_bytes(len(unspents), byteorder='little') # Construct the outputs, taking the fee into account sum_of_unspents = sum([int(x.amount) for x in unspents]) amount = amount or sum_of_unspents outputs = [(destination_address, sum_of_unspents, currency)] unspents, outputs = sanitize_tx_data(unspents, outputs, fee or get_fee_cached(), leftover or private_keys[0].address, combine=True, message=message, compressed=compressed, sweep=True) output_count = int_to_unknown_bytes(len(outputs), byteorder='little') output_block = construct_output_block(outputs) # Optimize for speed, not memory, by pre-computing values. inputs = [] for unspent in unspents: script = hex_to_bytes(unspent.script) script_len = int_to_unknown_bytes(len(script), byteorder='little') txid = hex_to_bytes(unspent.txid)[::-1] txindex = unspent.txindex.to_bytes(4, byteorder='little') inputs.append(TxIn(script, script_len, txid, txindex)) for i, txin in enumerate(inputs): hashed = sha256(version + input_count + b''.join(ti.txid + ti.txindex + OP_0 + sequence for ti in islice(inputs, i)) + txin.txid + txin.txindex + txin.script_len + txin.script + sequence + b''.join(ti.txid + ti.txindex + OP_0 + sequence for ti in islice(inputs, i + 1, None)) + output_count + output_block + lock_time + hash_type) private_key = private_key_map[unspents[i].txid] signature = private_key.sign(hashed) + b'\x01' public_key = private_key.public_key public_key_len = len(public_key).to_bytes(1, byteorder='little') script_sig = (len(signature).to_bytes(1, byteorder='little') + signature + public_key_len + public_key) txin.script = script_sig txin.script_len = int_to_unknown_bytes(len(script_sig), byteorder='little') return bytes_to_hex(version + input_count + construct_input_block(inputs) + output_count + output_block + lock_time)
def test_correct(self): assert bytes.fromhex(bytes_to_hex(BYTES_BIG)) == BYTES_BIG
def calc_txid(tx_hex): return bytes_to_hex(double_sha256(hex_to_bytes(tx_hex))[::-1])
def test_int(intk, debug=False, do_endian=True, do_ops=True): if do_ops: test_with_prime21e_ops(intk) if do_endian: n = int(intk) n2 = int.from_bytes(n.to_bytes((n.bit_length() + 7) // 8, 'big') or b'\0', byteorder='little') #print(n, '->', n2) test_int(n2, do_endian=False, do_ops=False) # concat PRIME21E n3 = str(intk) + str(PRIME21E) n4 = str(PRIME21E) + str(intk) test_int(n3, do_endian=False, do_ops=False) test_int(n4, do_endian=False, do_ops=False) #test_int(struct.pack('>L', int(intk))) if int(intk) == 0 or int( intk ) > 115792089237316195423570985008687907852837564279074904382605163141518161494337: return 'invalid size' try: sha_hex = to_hex(intk) sha_key = right_pad_zed(sha_hex) #print(len(sha_key), sha_hex, '->', sha_key) sha_key_compressed = Key.from_hex(sha_key) sha_key_uncompressed = uncompressed_key(sha_key_compressed) priv_key_compressed = Key.from_int(int(intk)) priv_key_uncompressed = uncompressed_key(priv_key_compressed) #priv_key_compressed2 = compressed_key(int(intk)) priv_key_compressed2 = compressed_key(priv_key_compressed) #int(intk)) priv_key_compressed3 = Key.from_int(int(intk) & PRIME21E) priv_key_c2 = Key.from_bytes( b58decode( b58encode(utils.hex_to_bytes(utils.int_to_hex(int(intk)))))) priv_key_uc2 = uncompressed_key(priv_key_c2) except Exception as err: print("ERROR: test_int:", err, 'intk:', intk) traceback.print_exc(file=sys.stdout) return False """Debug: print('addrc:{} addru:{} wifc:{} wifu:{}'.format( priv_key_compressed.address, priv_key_uncompressed.address, priv_key_compressed.to_wif(), priv_key_uncompressed.to_wif(), )) """ if debug: print( intk, priv_key_compressed.address, priv_key_uncompressed.address, bytes_to_hex(priv_key_compressed.public_key), bytes_to_hex(priv_key_uncompressed.public_key), ) if test_key(sha_key_compressed): return True if test_key(sha_key_uncompressed): return True if test_key(priv_key_compressed3): return True if test_key(priv_key_compressed): return True if test_key(priv_key_compressed2): return True if test_key(priv_key_uncompressed): return True if test_key(priv_key_uc2): return True if test_key(priv_key_c2): return True return False
def calc_txid(tx_hex): tx_obj = deserialize(tx_hex) return bytes_to_hex(double_sha256(tx_obj.legacy_repr())[::-1])
def read_as_int(bytez): pos[0] += bytez return int(bytes_to_hex(txhex[pos[0] - bytez:pos[0]][::-1]), base=16)
def deserialize(txhex, sw_dict={}, sw_scriptcode=None): # sw_dict is a dictionary containing segwit-inputs' txid concatenated with txindex using ":" mapping to information of the amount the input contains. # E.g.: sw_dict = {'txid:txindex': amount, ...} if isinstance(txhex, str) and re.match('^[0-9a-fA-F]*$', txhex): return deserialize(hex_to_bytes(txhex), sw_dict, sw_scriptcode) if txhex[ 4: 6] == b'\x00\x01': # ``marker|flag'' == 0001 if segwit-transaction segwit = True else: segwit = False pos = [0] def read_as_int(bytez): pos[0] += bytez return int(bytes_to_hex(txhex[pos[0] - bytez:pos[0]][::-1]), base=16) def read_var_int(): pos[0] += 1 val = int(bytes_to_hex(txhex[pos[0] - 1:pos[0]]), base=16) if val < 253: return val return read_as_int(pow(2, val - 252)) def read_bytes(bytez): pos[0] += bytez return txhex[pos[0] - bytez:pos[0]] def read_var_string(): size = read_var_int() return read_bytes(size) def read_segwit_string(): size = read_var_int() return int_to_varint(size) + read_bytes(size) version = read_as_int(4).to_bytes(4, byteorder='little') if segwit: _ = read_as_int(1).to_bytes(1, byteorder='little') # ``marker`` is read _ = read_as_int(1).to_bytes(1, byteorder='little') # ``flag`` is read ins = read_var_int() inputs = [] for i in range(ins): txid = read_bytes(32) txindex = read_as_int(4).to_bytes(4, byteorder='little') script = read_var_string() sequence = read_as_int(4).to_bytes(4, byteorder='little') # Check if input is segwit: tx_input = bytes_to_hex(txid) + ':' + bytes_to_hex(txindex) sw = True if ( sw_scriptcode == script[1:] or tx_input in sw_dict ) else False # Partially-signed segwit-multisig input or input provided in sw_dict. amount = sw_dict[ tx_input] if tx_input in sw_dict else 0 # Read ``amount`` from sw_dict if it is provided. inputs.append(TxIn(script, txid, txindex, b'', amount, sequence, sw)) outs = read_var_int() outputs = [] for _ in range(outs): value = read_as_int(8).to_bytes(8, byteorder='little') script = read_var_string() outputs.append(TxOut(value, script)) if segwit: for i in range(ins): wnum = read_var_int() witness = int_to_varint(wnum) for _ in range(wnum): witness += read_segwit_string() inputs[i].witness = witness locktime = read_as_int(4).to_bytes(4, byteorder='little') txobj = TxObj(version, inputs, outputs, locktime) return txobj
def test_flip_hex_byte_order(): assert flip_hex_byte_order(bytes_to_hex(BYTES_LITTLE)) == HEX
def test_upper(self): assert bytes_to_hex(BYTES_BIG, upper=True) == HEX.upper()
def test_default(self): assert bytes_to_hex(BYTES_BIG) == HEX
def sign_tx( private_key, tx, j=-1 ): # Future-TODO: add sw_dict to allow override of segwit input dictionary? # j is the input to be signed and can be a single index, a list of indices, or denote all inputs (-1) if not isinstance(tx, TxObj): # Add sw_dict containing unspent segwit txid:txindex and amount to deserialize tx: sw_dict = {} unspents = private_key.unspents for u in unspents: if u.segwit: tx_input = u.txid + ':' + str(u.txindex) sw_dict[tx_input] = u.amount tx = deserialize(tx, sw_dict, private_key.sw_scriptcode) version = tx.version marker = b'\x00' flag = b'\x01' lock_time = tx.locktime hash_type = HASH_TYPE input_count = int_to_varint(tx.input_count) output_count = int_to_varint(tx.output_count) output_block = b'' for i in range(tx.output_count): output_block += tx.TxOut[i].value output_block += tx.TxOut[i].script_len output_block += tx.TxOut[i].script hashPrevouts = double_sha256(b''.join( [i.txid + i.txindex for i in tx.TxIn])) hashSequence = double_sha256(b''.join([i.sequence for i in tx.TxIn])) hashOutputs = double_sha256(b''.join([bytes(o) for o in tx.TxOut])) if j < 0: # Sign all inputs j = range(len(tx.TxIn)) elif not isinstance(j, list): # Sign a single input j = [j] segwit = False # Global check if at least one input is segwit for i in j: # Check if input is segwit or non-segwit: sw = tx.TxIn[i].segwit segwit = segwit or sw # Global check if at least one input is segwit => Transaction must be of segwit-format public_key = private_key.public_key public_key_len = script_push(len(public_key)) scriptCode = private_key.scriptcode scriptCode_len = int_to_varint(len(scriptCode)) if sw == False: hashed = sha256(version + input_count + b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence for ti in islice(tx.TxIn, i)) + tx.TxIn[i].txid + tx.TxIn[i].txindex + scriptCode_len + scriptCode + tx.TxIn[i].sequence + b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence for ti in islice(tx.TxIn, i + 1, None)) + output_count + output_block + lock_time + hash_type) input_script_field = tx.TxIn[i].script else: hashed = sha256( # BIP-143: Used for Segwit version + hashPrevouts + hashSequence + tx.TxIn[i].txid + tx.TxIn[i].txindex + scriptCode_len + scriptCode + tx.TxIn[i].amount + tx.TxIn[i].sequence + hashOutputs + lock_time + hash_type) input_script_field = tx.TxIn[i].witness signature = private_key.sign(hashed) + b'\x01' # ------------------------------------------------------------------ if private_key.instance == 'MultiSig' or private_key.instance == 'MultiSigTestnet': # P2(W)SH input script_blob = b'' sigs = {} if input_script_field: # If tx is already partially signed: Make a dictionary of the provided signatures with public-keys as key-values sig_list = get_signatures_from_script(input_script_field) if len(sig_list) > private_key.m: raise TypeError( 'Transaction is already signed with {} of {} needed signatures.' ).format(len(sig_list), private_key.m) for sig in sig_list: for pub in private_key.public_keys: if verify_sig(sig[:-1], hashed, hex_to_bytes(pub)): sigs[pub] = sig script_blob += b'\x00' * ( private_key.m - len(sig_list) - 1 ) # Bitcoin Core convention: Every missing signature is denoted by 0x00. Only used for already partially-signed scriptSigs. sigs[bytes_to_hex(public_key)] = signature witness = b'' witness_count = 2 # count number of witness items (OP_0 + each signature + redeemscript). for pub in private_key.public_keys: # Sort the signatures according to the public-key list: if pub in sigs: sig = sigs[pub] length = int_to_varint( len(sig)) if sw == True else script_push(len(sig)) witness += length + sig witness_count += 1 script_sig = b'\x22' + private_key.sw_scriptcode witness = (witness_count.to_bytes(1, byteorder='little') if sw == True else b'') + b'\x00' + witness + script_blob witness += (int_to_varint(len( private_key.redeemscript)) if sw == True else script_push( len(private_key.redeemscript))) + private_key.redeemscript script_sig = witness if sw == False else script_sig witness = b'\x00' if sw == False else witness # ------------------------------------------------------------------ else: # P2(W)PKH input script_sig = b'\x16' + private_key.sw_scriptcode witness = ((b'\x02' if sw == True else b'') + # witness counter len(signature).to_bytes(1, byteorder='little') + signature + public_key_len + public_key) script_sig = witness if sw == False else script_sig witness = b'\x00' if sw == False else witness tx.TxIn[i].script = script_sig tx.TxIn[i].script_len = int_to_varint(len(script_sig)) tx.TxIn[i].witness = witness return bytes_to_hex( version + (marker if segwit == True else b'') + (flag if segwit == True else b'') + input_count + construct_input_block(tx.TxIn) + output_count + output_block + (construct_witness_block(tx.TxIn) if segwit == True else b'') + lock_time)
def sign_legacy_tx(private_key, tx, j=-1): # j is the input to be signed and can be a single index, a list of indices, or denote all inputs (-1) if not isinstance(tx, TxObj): tx = deserialize(tx) version = tx.version lock_time = tx.locktime hash_type = HASH_TYPE input_count = int_to_varint(tx.input_count) output_count = int_to_varint(tx.output_count) output_block = b'' for i in range(tx.output_count): output_block += tx.TxOut[i].value output_block += tx.TxOut[i].script_len output_block += tx.TxOut[i].script inputs = tx.TxIn if j < 0: j = range(len(inputs)) elif not isinstance(j, list): j = [j] for i in j: public_key = private_key.public_key public_key_len = script_push(len(public_key)) scriptCode = private_key.scriptcode scriptCode_len = int_to_varint(len(scriptCode)) hashed = sha256(version + input_count + b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence for ti in islice(inputs, i)) + inputs[i].txid + inputs[i].txindex + scriptCode_len + scriptCode + inputs[i].sequence + b''.join(ti.txid + ti.txindex + OP_0 + ti.sequence for ti in islice(inputs, i + 1, None)) + output_count + output_block + lock_time + hash_type) signature = private_key.sign(hashed) + b'\x01' # ------------------------------------------------------------------ if private_key.instance == 'MultiSig' or private_key.instance == 'MultiSigTestnet': script_blob = b'' sigs = {} if tx.TxIn[ i].script: # If tx is already partially signed: Make a dictionary of the provided signatures with public-keys as key-values sig_list = get_signatures_from_script(tx.TxIn[i].script) if len(sig_list) > private_key.m: raise TypeError( 'Transaction is already signed with {} of {} needed signatures.' ).format(len(sig_list), private_key.m) for sig in sig_list: for pub in private_key.public_keys: if verify_sig(sig[:-1], hashed, hex_to_bytes(pub)): sigs[pub] = sig script_blob += b'\x00' * ( private_key.m - len(sig_list) - 1 ) # Bitcoin Core convention: Every missing signature is denoted by 0x00. Only used for already partially-signed scriptSigs. sigs[bytes_to_hex(public_key)] = signature script_sig = b'' # P2SH - Multisig for pub in private_key.public_keys: # Sort the signatures according to the public-key list: if pub in sigs: sig = sigs[pub] length = script_push(len(sig)) script_sig += length + sig script_sig = b'\x00' + script_sig + script_blob script_sig += script_push(len( private_key.redeemscript)) + private_key.redeemscript # ------------------------------------------------------------------ else: script_sig = ( # P2PKH len(signature).to_bytes(1, byteorder='little') + signature + public_key_len + public_key) inputs[i].script = script_sig inputs[i].script_len = int_to_varint(len(script_sig)) return bytes_to_hex(version + input_count + construct_input_block(inputs) + output_count + output_block + lock_time)