def to_scriptPubKey(self): """Convert an address to a scriptPubKey""" if self.nVersion == bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR']: return script.CScript([script.OP_DUP, script.OP_HASH160, self, script.OP_EQUALVERIFY, script.OP_CHECKSIG]) elif self.nVersion == bitcoin.params.BASE58_PREFIXES['SCRIPT_ADDR']: return script.CScript([script.OP_HASH160, self, script.OP_EQUAL]) else: raise ValueError("CBitcoinAddress: Don't know how to convert version %d to a scriptPubKey" % self.nVersion)
def from_scriptPubKey(cls, scriptPubKey, accept_non_canonical_pushdata=True, accept_bare_checksig=True): """Convert a scriptPubKey to a P2PKH address Raises CBitcoinAddressError if the scriptPubKey isn't of the correct form. accept_non_canonical_pushdata - Allow non-canonical pushes (default True) accept_bare_checksig - Treat bare-checksig as P2PKH scriptPubKeys (default True) """ if accept_non_canonical_pushdata: # Canonicalize script pushes scriptPubKey = script.CScript( scriptPubKey) # in case it's not a CScript instance yet try: scriptPubKey = script.CScript( tuple(scriptPubKey)) # canonicalize except bitcoin.core.script.CScriptInvalidError: raise CBitcoinAddressError( 'not a P2PKH scriptPubKey: script is invalid') if (len(scriptPubKey) == 25 and _bord(scriptPubKey[0]) == script.OP_DUP and _bord(scriptPubKey[1]) == script.OP_HASH160 and _bord(scriptPubKey[2]) == 0x14 and _bord(scriptPubKey[23]) == script.OP_EQUALVERIFY and _bord(scriptPubKey[24]) == script.OP_CHECKSIG): return cls.from_bytes( scriptPubKey[3:23], bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR']) elif accept_bare_checksig: pubkey = None # We can operate on the raw bytes directly because we've # canonicalized everything above. if (len(scriptPubKey) == 35 # compressed and _bord(scriptPubKey[0]) == 0x21 and _bord(scriptPubKey[34]) == script.OP_CHECKSIG): pubkey = scriptPubKey[1:34] elif (len(scriptPubKey) == 67 # uncompressed and _bord(scriptPubKey[0]) == 0x41 and _bord(scriptPubKey[66]) == script.OP_CHECKSIG): pubkey = scriptPubKey[1:65] if pubkey is not None: return cls.from_pubkey(pubkey, accept_invalid=True) raise CBitcoinAddressError('not a P2PKH scriptPubKey')
def to_scriptPubKey(self): """Convert an address to a scriptPubKey""" if self.nVersion in (self.PUBKEY_ADDRESS, self.PUBKEY_ADDRESS_TEST): return script.CScript([ script.OP_DUP, script.OP_HASH160, self, script.OP_EQUALVERIFY, script.OP_CHECKSIG ]) elif self.nVersion in (self.SCRIPT_ADDRESS, self.SCRIPT_ADDRESS_TEST): return script.CScript([script.OP_HASH160, self, script.OP_EQUAL]) else: raise ValueError( "CBitcoinAddress: Don't know how to convert version %d to a scriptPubKey" % self.nVersion)
def boucle_outputs(transaction, longueurOutPuts, senderAdress, boolSegWit, timeStamp, t, positions, hsh): receiverAdressJoin = ' ' allValues = [] for k in range(longueurOutPuts): value = (transaction.vout[k].nValue) * 0.00000001 allValues.append(value) if value != 0: try: scrPubKey = b2x(transaction.vout[k].scriptPubKey) bcBool = int(scrPubKey[0:1],16) if bcBool == 0: n = 2 liste = [int(scrPubKey[i:i+n],16) for i in range(0, len(scrPubKey), n)] liste[0:2]=[] receiverAdress = encode('bc', bcBool, liste) else: ScriptPubKey = script.CScript(x(scrPubKey)) receiverAdress = CBitcoinAddress.from_scriptPubKey(ScriptPubKey) except CBitcoinAddressError: receiverAdress = "no address found" receiverAdressJoin = receiverAdressJoin + "_" + str(receiverAdress) allTransactions['transactions'].append({'Sender': senderAdress, 'receiver': receiverAdressJoin, 'ammount': allValues, 'time': timeStamp, 'txID': t, 'positions': positions, 'txHash': hsh}) return (allTransactions, value)
def to_scriptPubKey(self, nested=False): """Convert an address to a scriptPubKey""" assert self.nVersion == bitcoin.params.BASE58_PREFIXES['PUBKEY_ADDR'] return script.CScript([ script.OP_DUP, script.OP_HASH160, self, script.OP_EQUALVERIFY, script.OP_CHECKSIG ])
def sign(self, default_wallet: BitcoinWallet = None): """Signing transaction using the wallet object.""" for tx_index, tx_in in enumerate(self.tx.vin): utxo = self.solvable_utxo[tx_index] wallet = utxo.wallet or default_wallet if wallet is None: raise RuntimeError('Cannot sign transaction without a wallet.') tx_script = utxo.parsed_script if utxo.contract: sig_hash = script.SignatureHash( script.CScript.fromhex(utxo.contract), self.tx, tx_index, script.SIGHASH_ALL) else: sig_hash = script.SignatureHash(tx_script, self.tx, tx_index, script.SIGHASH_ALL) sig = wallet.private_key.sign(sig_hash) + struct.pack( '<B', script.SIGHASH_ALL) script_sig = [sig, wallet.private_key.pub ] + utxo.unsigned_script_sig tx_in.scriptSig = script.CScript(script_sig) VerifyScript(tx_in.scriptSig, tx_script, self.tx, tx_index, (SCRIPT_VERIFY_P2SH, )) self.signed = True
def create_tx(n, addressFrom, addressTo, mixer_list, fee=None): pre_tx = transaction(n, addressFrom, addressTo, mixer_list, fee=None) own_n = len(pre_tx.own_inputs) # Get inputs signed by each of the miners for x in pre_tx.mixer_inputs: sig_mixer, pubKey_mixer = send_tx(pre_tx.tx, x, pre_tx.pruned_mixer_inputs) x.scriptSig = bcs.CScript([sig_mixer, pubKey_mixer]) # Sign inputs owned by sender's address txin_scriptPubKey = bcs.CScript([bcs.OP_DUP, bcs.OP_HASH160, bc.Hash160(addressFrom.pubKey), bcs.OP_EQUALVERIFY, bcs.OP_CHECKSIG]) for i in range(own_n): sighash = bcs.SignatureHash(txin_scriptPubKey, pre_tx.tx, i, bcs.SIGHASH_ALL) sig = addressFrom.priv.sign(sighash) + bytes([bcs.SIGHASH_ALL]) pre_tx.inputs[i].scriptSig = bcs.CScript([sig, addressFrom.pubKey]) bcseval.VerifyScript(pre_tx.inputs[i].scriptSig, txin_scriptPubKey, pre_tx.tx, i, (bcseval.SCRIPT_VERIFY_P2SH,)) return pre_tx
def get_receiver_Address(transaction): rec = '' try: scrPubKey = b2x(transaction.vout[0].scriptPubKey) ScriptPubKey = script.CScript(x(scrPubKey)) rec = CBitcoinAddress.from_scriptPubKey(ScriptPubKey) rec1 = str(rec) except CBitcoinAddressError: rec1 = "no Address found" return(rec1)
def test_audit_contract_non_matching_contract(_, signed_transaction): btc_network = BitcoinTestNet() transaction_details = signed_transaction.show_details() contract = script.CScript([script.OP_TRUE]).hex() with raises(ValueError, match='Given transaction is not a valid contract.'): btc_network.audit_contract(contract, transaction_details['contract_transaction'])
def build_atomic_swap_contract(self): self.contract = script.CScript([ script.OP_IF, script.OP_RIPEMD160, self.secret_hash, script.OP_EQUALVERIFY, script.OP_DUP, script.OP_HASH160, CBitcoinAddress(self.recipient_address), script.OP_ELSE, int(self.locktime.replace(tzinfo=timezone.utc).timestamp()), script.OP_CHECKLOCKTIMEVERIFY, script.OP_DROP, script.OP_DUP, script.OP_HASH160, CBitcoinAddress(self.sender_address), script.OP_ENDIF, script.OP_EQUALVERIFY, script.OP_CHECKSIG, ])
def _received_htlc_output(self, htlc: HTLC, side: Side) -> Tuple[script.CScript, int]: # BOLT #3: This output sends funds to either the remote node after the # HTLC-timeout or using the revocation key, or to an HTLC-success # transaction with a successful payment preimage. The output is a # P2WSH, with a witness script: # # # To remote node with revocation key # OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL # OP_IF # OP_CHECKSIG # OP_ELSE # <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL # OP_IF # # To local node via HTLC-success transaction. # OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY # 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG # OP_ELSE # # To remote node after timeout. # OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP # OP_CHECKSIG # OP_ENDIF # OP_ENDIF htlc_script = script.CScript([ script.OP_DUP, script.OP_HASH160, Hash160(self.revocation_pubkey(side).format()), script.OP_EQUAL, script.OP_IF, script.OP_CHECKSIG, script.OP_ELSE, self.remote_htlc_pubkey(side).format(), script.OP_SWAP, script.OP_SIZE, 32, script.OP_EQUAL, script.OP_IF, script.OP_HASH160, self.ripemd160(htlc.raw_payment_hash()), script.OP_EQUALVERIFY, 2, script.OP_SWAP, self.local_htlc_pubkey(side).format(), 2, script.OP_CHECKMULTISIG, script.OP_ELSE, script.OP_DROP, htlc.cltv_expiry, script.OP_CHECKLOCKTIMEVERIFY, script.OP_DROP, script.OP_CHECKSIG, script.OP_ENDIF, script.OP_ENDIF ]) # BOLT #3: The amounts for each output MUST be rounded down to whole # satoshis. return htlc_script, htlc.amount_msat // 1000
def _to_local_output(self, fee: int, side: Side) -> Tuple[script.CScript, int]: # BOLT #3: # #### `to_local` Output # # This output sends funds back to the owner of this commitment # transaction and thus must be timelocked using # `OP_CHECKSEQUENCEVERIFY`. It can be claimed, without delay, by the # other party if they know the revocation private key. The output is a # version-0 P2WSH, with a witness script: # # OP_IF # # Penalty transaction # <revocationpubkey> # OP_ELSE # `to_self_delay` # OP_CHECKSEQUENCEVERIFY # OP_DROP # <local_delayedpubkey> # OP_ENDIF # OP_CHECKSIG to_self_script = script.CScript([ script.OP_IF, self.revocation_pubkey(side).format(), script.OP_ELSE, self.self_delay[side], script.OP_CHECKSEQUENCEVERIFY, script.OP_DROP, self.delayed_pubkey(side).format(), script.OP_ENDIF, script.OP_CHECKSIG ]) # BOLT #3: The amounts for each output MUST be rounded down to whole # satoshis. If this amount, minus the fees for the HTLC transaction, # is less than the `dust_limit_satoshis` set by the owner of the # commitment transaction, the output MUST NOT be produced (thus the # funds add to fees). amount_to_self = self.amounts[side] // 1000 if side == self.opener: amount_to_self -= fee return to_self_script, amount_to_self
def generate_multisig_redeem_script(pubkeys: List[str], m: int) -> str: """ Creates a M-of-N P2SH-multisig bitcoin redeemscript Args: pubkeys: List of hex-encoded compressed public keys Returns: hex-encoded redeem script Example: TODO """ OP_M = script.CScriptOp.encode_op_n(m) OP_N = script.CScriptOp.encode_op_n(len(pubkeys)) redeem_list = [x(pubkey) for pubkey in pubkeys] redeem_list.insert(0, OP_M) redeem_list.append(OP_N) redeem_list.append(script.OP_CHECKMULTISIG) redeem_script = script.CScript(redeem_list).hex() return redeem_script
def transform(self, source): if isinstance(source, list): source = ''.join(source) if source.startswith('0x'): source = source[2:] src = script.CScript(x(source)) iterator = iter(src) for value in iterator: op = None s = str(value) if s.startswith('OP_'): op = types.opcode_by_name(s)() elif isinstance(value, int): op = types.small_int_opcode(value)() else: op = types.Push(data=value) if op is not None: self.add_instruction(op) return self.instructions
def _offered_htlc_output(self, htlc: HTLC, side: Side) -> Tuple[script.CScript, int]: # BOLT #3: This output sends funds to either an HTLC-timeout # transaction after the HTLC-timeout or to the remote node # using the payment preimage or the revocation key. The output # is a P2WSH, with a witness script: # # # To remote node with revocation key # OP_DUP OP_HASH160 <RIPEMD160(SHA256(revocationpubkey))> OP_EQUAL # OP_IF # OP_CHECKSIG # OP_ELSE # <remote_htlcpubkey> OP_SWAP OP_SIZE 32 OP_EQUAL # OP_NOTIF # # To local node via HTLC-timeout transaction (timelocked). # OP_DROP 2 OP_SWAP <local_htlcpubkey> 2 OP_CHECKMULTISIG # OP_ELSE # # To remote node with preimage. # OP_HASH160 <RIPEMD160(payment_hash)> OP_EQUALVERIFY # OP_CHECKSIG # OP_ENDIF # OP_ENDIF htlc_script = script.CScript([ script.OP_DUP, script.OP_HASH160, Hash160(self.revocation_pubkey(side).format()), script.OP_EQUAL, script.OP_IF, script.OP_CHECKSIG, script.OP_ELSE, self.remote_htlc_pubkey(side).format(), script.OP_SWAP, script.OP_SIZE, 32, script.OP_EQUAL, script.OP_NOTIF, script.OP_DROP, 2, script.OP_SWAP, self.local_htlc_pubkey(side).format(), 2, script.OP_CHECKMULTISIG, script.OP_ELSE, script.OP_HASH160, self.ripemd160(htlc.raw_payment_hash()), script.OP_EQUALVERIFY, script.OP_CHECKSIG, script.OP_ENDIF, script.OP_ENDIF ]) # BOLT #3: The amounts for each output MUST be rounded down to whole # satoshis. return htlc_script, htlc.amount_msat // 1000
def to_redeemScript(self): return script.CScript([ script.OP_DUP, script.OP_HASH160, self, script.OP_EQUALVERIFY, script.OP_CHECKSIG ])
def to_scriptPubKey(self): """Convert an address to a scriptPubKey""" assert self.witver == 0 return script.CScript([0, self])
def to_scriptPubKey(self): """Convert an address to a scriptPubKey""" assert self.nVersion == bitcoin.params.BASE58_PREFIXES['SCRIPT_ADDR'] return script.CScript([script.OP_HASH160, self, script.OP_EQUAL])
def __init__( self, network, contract: str, raw_transaction: Optional[str]=None, transaction_address: Optional[str]=None ): if not raw_transaction and not transaction_address: raise ValueError('Provide raw_transaction or transaction_address argument.') self.network = network self.symbol = self.network.default_symbol self.contract = contract self.tx = None self.vout = None self.confirmations = None self.tx_address = transaction_address if raw_transaction: self.tx = self.network.deserialize_raw_transaction(raw_transaction) try: self.vout = self.tx.vout[0] except IndexError: raise ValueError('Given transaction has no outputs.') else: tx_json = get_transaction(network.default_symbol, transaction_address, network.is_test_network()) if not tx_json: raise ValueError('No transaction found under given address.') if 'hex' in tx_json: # transaction from blockcypher or raven explorer self.tx = self.network.deserialize_raw_transaction(tx_json['hex']) self.vout = self.tx.vout[0] else: # transaction from cryptoid incorrect_cscript = script.CScript.fromhex(tx_json['outputs'][0]['script']) correct_cscript = script.CScript([script.OP_HASH160, list(incorrect_cscript)[2], script.OP_EQUAL]) nValue = to_base_units(tx_json['outputs'][0]['amount']) self.vout = CTxOut(nValue, correct_cscript) if 'confirmations' in tx_json: self.confirmations = tx_json['confirmations'] elif 'block_height' in tx_json: self.confirmations = self.network.latest_block - tx_json['block_height'] elif 'block' in tx_json: self.confirmations = self.network.latest_block - tx_json['block'] if not self.vout: raise ValueError('Given transaction has no outputs.') contract_tx_out = self.vout contract_script = script.CScript.fromhex(self.contract) script_pub_key = contract_script.to_p2sh_scriptPubKey() valid_p2sh = script_pub_key == contract_tx_out.scriptPubKey self.address = str(CBitcoinAddress.from_scriptPubKey(script_pub_key)) self.balance = get_balance(self.network, self.address) script_ops = list(contract_script) if valid_p2sh and self.is_valid_contract_script(script_ops): self.recipient_address = str(P2PKHBitcoinAddress.from_bytes(script_ops[6])) self.refund_address = str(P2PKHBitcoinAddress.from_bytes(script_ops[13])) self.locktime_timestamp = int.from_bytes(script_ops[8], byteorder='little') self.locktime = datetime.utcfromtimestamp(self.locktime_timestamp) self.secret_hash = b2x(script_ops[2]) self.value = from_base_units(contract_tx_out.nValue) else: raise ValueError('Given transaction is not a valid contract.')
def construct_signed_transaction(redeem_script: str, sig_files: List[str], inputs_file: str, outputs_file: str, testnet: bool = False) -> str: """ Construct a hex-encoded serialized bitcoin transaction fully-signed and ready for broadcast for a 2-of-3 P2SH-multisig address Args: redeem_script: hex-encoded redeem script (see generate_multisig_redeem_script.py) sig_files: List of 2 JSON signature files containing a public key and signatures for each UTXO (see sign_multisig_spend.py) inputs_file: JSON file of UTXOs to be spent (see get_utxo_set.py) outputs_file: JSON file of destination addresses (see generate_outputs.py) testnet: Is this a testnet or mainnet transaction? Returns: fully-signed hex-encoded serialized Bitcoin transaction Raises: ValueError: If sig_files doesn't have exactly 2 elements. Example: TODO """ if testnet: SelectParams('testnet') else: SelectParams('mainnet') # Input validation if len(sig_files) != 2: raise ValueError("Two Signature Files are Required") # load inputs, outputs, and signatures with open(inputs_file, 'r') as f: inputs = json.load(f) with open(outputs_file, 'r') as f: outputs = json.load(f) signatures = [] for sig_file in sig_files: with open(sig_file, 'r') as f: signatures.append(json.load(f)) # Order Signatures parsed_redeem_script = btc_utils.parse_redeem_script(redeem_script) sig1_index = parsed_redeem_script['pubkeys'].index(signatures[0]['pubkey']) sig2_index = parsed_redeem_script['pubkeys'].index(signatures[1]['pubkey']) if sig2_index < sig1_index: signatures = [signatures[1], signatures[0]] # Construct ScriptSigs zipped_sigs = zip(signatures[0]['signatures'], signatures[1]['signatures']) scriptsigs = [ script.CScript([ OP_0, x(sig1) + bytes([SIGHASH_ALL]), x(sig2) + bytes([SIGHASH_ALL]), x(redeem_script) ]) for (sig1, sig2) in zipped_sigs ] # Construct Inputs List TxIns = [] for input in inputs: txid = lx(input['txid']) vout = input['n'] TxIns.append(CMutableTxIn(COutPoint(txid, vout))) # Insert ScriptSigs for i in range(len(TxIns)): TxIns[i].scriptSig = scriptsigs[i] # Construct Outputs List TxOuts = [] for output in outputs: output_script = CBitcoinAddress(output['address']).to_scriptPubKey() TxOuts.append(CMutableTxOut(output['amount'], output_script)) # Construct TX tx = CMutableTransaction(TxIns, TxOuts) return b2x(tx.serialize())
def htlc_tx(self, commit_tx: CMutableTransaction, outnum: int, side: Side, amount_sat: int, locktime: int) -> CMutableTransaction: # BOLT #3: # ## HTLC-Timeout and HTLC-Success Transactions # # These HTLC transactions are almost identical, except the # HTLC-timeout transaction is timelocked. Both # HTLC-timeout/HTLC-success transactions can be spent by a valid # penalty transaction. # BOLT #3: # ## HTLC-Timeout and HTLC-Success Transactions # ... # * txin count: 1 # * `txin[0]` outpoint: `txid` of the commitment transaction and # `output_index` of the matching HTLC output for the HTLC transaction # * `txin[0]` sequence: `0` # * `txin[0]` script bytes: `0` txin = CTxIn(COutPoint(commit_tx.GetTxid(), outnum), nSequence=0x0) # BOLT #3: # ## HTLC-Timeout and HTLC-Success Transactions # ... # * txout count: 1 # * `txout[0]` amount: the HTLC amount minus fees (see [Fee # Calculation](#fee-calculation)) # * `txout[0]` script: version-0 P2WSH with witness script as shown below # # The witness script for the output is: # OP_IF # # Penalty transaction # <revocationpubkey> # OP_ELSE # `to_self_delay` # OP_CHECKSEQUENCEVERIFY # OP_DROP # <local_delayedpubkey> # OP_ENDIF # OP_CHECKSIG redeemscript = script.CScript([ script.OP_IF, self.revocation_pubkey(side).format(), script.OP_ELSE, self.self_delay[side], script.OP_CHECKSEQUENCEVERIFY, script.OP_DROP, self.delayed_pubkey(side).format(), script.OP_ENDIF, script.OP_CHECKSIG ]) print("htlc redeemscript = {}".format(redeemscript.hex())) txout = CTxOut(amount_sat, CScript([script.OP_0, sha256(redeemscript).digest()])) # BOLT #3: # ## HTLC-Timeout and HTLC-Success Transactions # ... # * version: 2 # * locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout return CMutableTransaction(vin=[txin], vout=[txout], nVersion=2, nLockTime=locktime)
def get_first_vout_from_tx_json(cls, tx_json: dict) -> CTxOut: incorrect_cscript = script.CScript.fromhex(tx_json['outputs'][0]['script']) correct_cscript = script.CScript([script.OP_HASH160, list(incorrect_cscript)[2], script.OP_EQUAL]) nValue = to_base_units(tx_json['outputs'][0]['amount']) return CTxOut(nValue, correct_cscript)
def tx_in(self): return CMutableTxIn(self.outpoint, scriptSig=script.CScript(self.unsigned_script_sig), nSequence=0)
def sign_inputs(tx, inputs, sig, pubKey): for i in range(len(inputs)): inputs[i].scriptSig = bcs.CScript([sig, pubKey])