예제 #1
0
    def getrawtransaction(self, txid, verbose=False):
        """Return transaction with hash txid

        Raises IndexError if transaction not found.

        verbse - If true a dict is returned instead with additional information
                 on the transaction.

        Note that if all txouts are spent and the transaction index is not
        enabled the transaction may not be available.
        """
        try:
            r = self._call('getrawtransaction', b2lx(txid), 1 if verbose else 0)
        except JSONRPCException as ex:
            raise IndexError('%s.getrawtransaction(): %s (%d)' %
                    (self.__class__.__name__, ex.error['message'], ex.error['code']))
        if verbose:
            r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
            del r['hex']
            del r['txid']
            del r['version']
            del r['locktime']
            del r['vin']
            del r['vout']
            r['blockhash'] = lx(r['blockhash']) if 'blockhash' in r else None
        else:
            r = CTransaction.deserialize(unhexlify(r))

        return r
예제 #2
0
def calculate_tx_fees(coins, currency, tx_hex):
    #Process source TX.
    rpc = coins[currency]["rpc"]["sock"]
    tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))

    #Tally input coins.
    input_total = decimal.Decimal(0)
    for vin in tx.vin:
        txid = b2lx(vin.prevout.hash)
        vin_tx_hex = rpc.getrawtransaction(txid)
        vin_tx = CTransaction.deserialize(binascii.unhexlify(vin_tx_hex))
        input_value = vin_tx.vout[vin.prevout.n].nValue
        input_total += decimal.Decimal(str_money_value(input_value))

    #Tally output coins.
    output_total = decimal.Decimal(0)
    for vout in tx.vout:
        output_value = decimal.Decimal(str_money_value(vout.nValue))
        output_total += output_value

    #TX fees are the difference between the source and
    fees = input_total - output_total

    #Return totals and fees.
    return [input_total, output_total, fees]
예제 #3
0
    def getrawtransaction(self, txid, verbose=False):
        """Return transaction with hash txid

        Raises IndexError if transaction not found.

        verbose - If true a dict is returned instead with additional
        information on the transaction.

        Note that if all txouts are spent and the transaction index is not
        enabled the transaction may not be available.
        """
        try:
            r = self._call("getrawtransaction", b2lx(txid), 1 if verbose else 0)
        except JSONRPCError as ex:
            raise IndexError(
                "%s.getrawtransaction(): %s (%d)" % (self.__class__.__name__, ex.error["message"], ex.error["code"])
            )
        if verbose:
            r["tx"] = CTransaction.deserialize(unhexlify(r["hex"]))
            del r["hex"]
            del r["txid"]
            del r["version"]
            del r["locktime"]
            del r["vin"]
            del r["vout"]
            r["blockhash"] = lx(r["blockhash"]) if "blockhash" in r else None
        else:
            r = CTransaction.deserialize(unhexlify(r))

        return r
예제 #4
0
def calculate_tx_fees(coins, currency, tx_hex):
    #Process source TX.
    rpc = coins[currency]["rpc"]["sock"]
    tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))

    #Tally input coins.
    input_total = decimal.Decimal(0)
    for vin in tx.vin:
        txid = b2lx(vin.prevout.hash) 
        vin_tx_hex = rpc.getrawtransaction(txid)
        vin_tx = CTransaction.deserialize(binascii.unhexlify(vin_tx_hex))
        input_value = vin_tx.vout[vin.prevout.n].nValue
        input_total += decimal.Decimal(str_money_value(input_value))

    #Tally output coins.
    output_total = decimal.Decimal(0)
    for vout in tx.vout:
        output_value = decimal.Decimal(str_money_value(vout.nValue))
        output_total += output_value

    #TX fees are the difference between the source and 
    fees = input_total - output_total
    
    #Return totals and fees.
    return [input_total, output_total, fees]
예제 #5
0
    def add_input(self,
                  serial_id: int,
                  prevtx: str,
                  prevtx_vout: int,
                  script_sig: str,
                  sequence: int,
                  privkey: str = None) -> None:
        # the dummy runner sends empty info, skip
        if len(prevtx) == 0:
            return

        # Find the txid of the transaction
        prev_tx = CTransaction.deserialize(bytes.fromhex(prevtx))
        txin = CTxIn(COutPoint(prev_tx.GetTxid(), prevtx_vout),
                     nSequence=sequence)

        # Get the previous output for its outscript + value
        prev_vout = prev_tx.vout[prevtx_vout]

        self.inputs.append({'input': txin,
                            'serial_id': serial_id,
                            'sats': prev_vout.nValue,
                            'prev_outscript': prev_vout.scriptPubKey.hex(),
                            'redeemscript': script_sig,
                            'privkey': privkey,
                            })
예제 #6
0
파일: tx.py 프로젝트: mbaniasad/ahunavar
    def refund_tx(self, payer_sig, serial_tx, redeem_script):
        '''
            Sends a transaction refunding the funder of
            the P2SH address.
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Set script sig
        txin.scriptSig = CScript([payer_sig + '\x01', OP_FALSE, redeem_script])

        # Verify script
        redeem_script = CScript(redeem_script)
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("refund_tx: TXID is %s", txid)
        self.logger.info("refund_tx: RAW TX is %s", b2x(serial_tx))

        return serial_tx
    def check_refund_works(self, tx_hex, owner_first_sig, owner_second_sig, recipient_sig, actor):
        global error_log_path

        try:
            tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
            redeem_script = bond_redeem_script(self.ecdsa_us, self.ecdsa_them, self.factory.ecdsa_arbiters[0], actor)
            redeem_script_hash160 = hash160_script(redeem_script)

            print(tx_hex)
            print(redeem_script)

            tx.vin[0].scriptSig = CScript([OP_0, owner_first_sig, owner_second_sig, recipient_sig, redeem_script["bin"]])
            p2sh_script_pub_key = CScript([OP_HASH160, redeem_script_hash160["bin"], OP_EQUAL])
            print(redeem_script_hash160)

            VerifyScript(tx.vin[0].scriptSig, p2sh_script_pub_key, tx, 0, (SCRIPT_VERIFY_P2SH,))
            signed_tx_hex = b2x(tx.serialize())
            return {
                "tx_hex": signed_tx_hex,
                "txid": calculate_txid(signed_tx_hex)
            }
        except Exception as e:
            error = parse_exception(e)
            log_exception(error_log_path, error)
            print(error)
            print("Check refund failed.")
            return None
예제 #8
0
	def provide_transaction(self, transaction_data):
		self.send_lock.acquire()

		if self.send_transaction_cache.contains(transaction_data):
			self.send_lock.release()
			return
		if len(transaction_data) > self.MAX_RELAY_TRANSACTION_BYTES and (len(transaction_data) > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES or self.send_transaction_cache.get_flag_count() >= MAX_EXTRA_OVERSIZE_TRANSACTIONS):
			self.send_lock.release()
			return

		try:
			relay_data = pack('>3I', self.MAGIC_BYTES, self.TRANSACTION_TYPE, len(transaction_data))
			relay_data += transaction_data
			self.relay_sock.sendall(relay_data)
			self.send_transaction_cache.add(transaction_data, len(transaction_data) > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES)

			if deserialize_utils:
				transaction = CTransaction.deserialize(transaction_data)
				print("Sent transaction " + str(b2lx(transaction.GetHash())) + " of size " + str(len(transaction_data)))
			else:
				print("Sent transaction of size " + str(len(transaction_data)))
		except (OSError, socket.error) as err:
			print("Failed to send to relay node: ", err)

		self.send_lock.release()
예제 #9
0
파일: tx.py 프로젝트: miklobit/TumbleBit
def spend_escrow(serial_tx, redeem_script, payer_sig, redeemer_sig):
    '''
        Sends a transaction fulfilling the redeem script of escrow tx
    '''
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Set script sig
    txin.scriptSig = CScript([OP_0,
                             payer_sig + '\x01',
                             redeemer_sig + '\x01',
                             redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    serial_tx = tx.serialize()
    VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(),
                 tx, 0, [SCRIPT_VERIFY_P2SH])

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_escrow: TXID is %s" % txid)
    print("spend_escrow: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
예제 #10
0
def adjust_transaction(tx_hex):
    # if you don't want change you wallet signature code
    # you can use this to adjust high S signature to a canonical signature
    tx = CTransaction.deserialize(x(tx_hex))
    for vin in tx.vin:
        script_lst = list(vin.scriptSig)
        sig = script_lst[0]
        # normal signature format <sig> <pubkey>
        if len(script_lst) == 2 and not IsLowDERSignature(sig):
            low_s_sig = signature_to_low_s(sig)#.encode('hex')
            #print sig.encode('hex'), low_s_sig.encode('hex')
            script_lst[0] = low_s_sig
            vin.scriptSig = CScript(script_lst)
        # 2/2 or 2/3 multisig format <0> <signature> <signature> <redeemscript>
        elif len(script_lst) == 4:
            script_lst_new = []
            for idx, sig in enumerate(script_lst[1:3]):
                if not IsLowDERSignature(sig):
                    low_s_sig = signature_to_low_s(sig)#.encode('hex')
                    #print sig.encode('hex'), low_s_sig.encode('hex')
                    script_lst_new.append(low_s_sig)
                else:
                    script_lst_new.append(sig)
            script_lst_new.append(script_lst[3])
            vin.scriptSig = "\x00" + CScript(script_lst_new)
    return b2x(tx.serialize())
예제 #11
0
def assert_tx_matches(serialized_tx: bytes,
                      hash_link: str,
                      tx_hex: str = None) -> None:
    """Verifies if a transaction is correctly formed."""
    tx_id = hash_link.split("/")[-1]

    parsed_tx = CTransaction.deserialize(serialized_tx)
    assert tx_id == parsed_tx.GetTxid()[::-1].hex()
    if tx_hex:
        assert serialized_tx.hex() == tx_hex

    # TODO: we could probably do better than os.environ, this was the easiest solution
    # (we could create a pytest option (and use config.getoption("check-on-chain")),
    # but then each test would need to have access to config via function argument)
    if int(os.environ.get("CHECK_ON_CHAIN", 0)):

        def get_tx_hex(hash_link: str) -> str:
            tx_data = requests.get(hash_link,
                                   headers={
                                       "User-Agent": "BTC transactions test"
                                   }).json(parse_float=Decimal)

            return tx_data["hex"]

        assert serialized_tx.hex() == get_tx_hex(hash_link)
예제 #12
0
    def add_input(self,
                  serial_id: int,
                  prevtx: str,
                  prevtx_vout: int,
                  max_witness_len: int,
                  script: str,
                  sequence: int,
                  privkey: str = None) -> None:
        # Find the txid of the transaction
        prev_tx = CTransaction.deserialize(bytes.fromhex(prevtx))
        txin = CTxIn(COutPoint(prev_tx.GetTxid(), prevtx_vout),
                     nSequence=sequence)

        # Get the previous output for its outscript + value
        prev_vout = prev_tx.vout[prevtx_vout]

        self.inputs.append({
            'input': txin,
            'serial_id': serial_id,
            'sats': prev_vout.nValue,
            'prev_outscript': prev_vout.scriptPubKey.hex(),
            'redeemscript': script,
            'max_witness_len': max_witness_len,
            'privkey': privkey,
        })
예제 #13
0
def cmd_mkwitness(args):
    tx = None
    if args.tx is not None:
        serialized_tx = args.tx
        tx = CTransaction.deserialize(serialized_tx)

    else:
        tx = args.proxy.getrawtransaction(args.txid)

    txproof = TxProof(tx=tx)

    for seal_fd in args.seal_fds:
        seal = BitcoinSingleUseSeal.deserialize(seal_fd.read())

        txinproof = None
        txoutproof = None
        for i, txin in enumerate(txproof.tx.vin):
            if txin.prevout == seal.outpoint:
                txinproof = TxInProof(i=i, txproof=txproof)
                txoutproof = TxOutProof(i=0, txproof=txproof)
                break

        else:
            args.parser.error("Seal '%s' not closed by this transaction" % seal_fd.name)

        witness = BitcoinSealWitness(seal=seal, txinproof=txinproof, txoutproof=txoutproof)

        witness_filename = seal_fd.name + '.witness'
        logging.info("Creating witness file '%s'" % witness_filename)
        with open(seal_fd.name + '.witness', 'xb') as witness_fd:
            witness_fd.write(witness.serialize())
예제 #14
0
파일: tx.py 프로젝트: mbaniasad/ahunavar
    def spend_escrow(self, payer_sig, redeemer_sig, serial_tx, redeem_script):
        '''
            Sends a transaction fulfilling the redeem script of escrow tx
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Set script sig
        txin.scriptSig = CScript([
            OP_FALSE, payer_sig + '\x01', redeemer_sig + '\x01', OP_TRUE,
            redeem_script
        ])

        # Verify script
        redeem_script = CScript(redeem_script)
        serial_tx = tx.serialize()
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("spend_escrow: TXID is %s", txid)
        self.logger.info("spend_escrow: RAW TX is %s", b2x(serial_tx))

        return serial_tx
예제 #15
0
    def createrawtransaction(self, *args):
        """Get rawtransactions when provided vin and vout

        FIXME: Implement options and accept outpoints instead of user args
        """
        r = self._call('createrawtransaction', *args)
        r = str(r)
        tx = CTransaction.deserialize(unhexlify(r))
        return tx
예제 #16
0
def analyze_tx(tx_hex_string):
    output = {}

    # get op_return from transaction
    hex = unhexlify(tx_hex_string)
    deserializedTransaction = CTransaction.deserialize(hex)
    op_return_vout = deserializedTransaction.vout[1].scriptPubKey

    # get redeem script
    redeem_script = ''
    for i in op_return_vout:
        script = bytes(i).decode('utf8')
        if 'REDEEM' in script:
            redeem_script_string = script.replace('REDEEM SCRIPT ', '')
    output['redeemScript'] = redeem_script_string

    # convert redeem script into list
    redeemScript = CScript(unhexlify(redeem_script_string))
    redeem_script_array = []
    for i in redeemScript:
        redeem_script_array.append(i)

    # get redeem script hash (hodl address)
    p2sh_address = P2SHBitcoinAddress.from_redeemScript(redeemScript)
    output['hodlAddress'] = str(p2sh_address)

    # get nlocktime from redeem script
    nlocktime_hex = b2lx(redeem_script_array[0])
    nlocktime = int(nlocktime_hex, 16)
    output['nLockTime'] = nlocktime

    # get authorized key from redeem script
    pubkey = b2x(redeem_script_array[3])

    # get address from authorized key
    pubkey = unhexlify(pubkey)
    P2PKHBitcoinAddress = bitcoin.wallet.P2PKHBitcoinAddress
    addr = P2PKHBitcoinAddress.from_pubkey(pubkey)
    output['authorizedAddress'] = str(addr)

    # get total sent to hodl address
    locked_satoshis = 0
    for i in deserializedTransaction.vout:
        if i.nValue > 0:
            sPK = i.scriptPubKey
            amount = i.nValue
            try:
                vout_p2sh_addr = P2SHBitcoinAddress.from_scriptPubKey(sPK)
                # rewards only paid to really locked funds
                if str(p2sh_address) == str(vout_p2sh_addr):
                    locked_satoshis += amount
            except:
                pass
    output["lockedSatoshis"] = locked_satoshis

    return (output)
예제 #17
0
    def signrawtransaction(self, tx, *args):
        """Sign inputs for transaction

        FIXME: implement options
        """
        hextx = hexlify(tx.serialize())
        r = self._call('signrawtransaction', hextx, *args)
        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']
        return r
 def sign_refund_tx(self, tx_hex, key_no=1, actor="us"):
     key_no -= 1
     if key_no == 0:
         ecdsa = self.ecdsa_us[0]
     if key_no == 1:
         ecdsa = self.ecdsa_us[1]
     tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
     sighash = SignatureHash(bond_redeem_script(self.ecdsa_us, self.ecdsa_them, self.factory.ecdsa_arbiters[0], actor)["bin"], tx, 0, SIGHASH_ALL)
     seckey = CBitcoinSecret.from_secret_bytes(ecdsa.get_private_key("bin"), compressed=True)
     sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
     return sig
예제 #19
0
    def signrawtransactionwithwallet(self, tx, *args):
        """Sign inputs for transaction
            bicoincore >= 0.17.x

        FIXME: implement options
        """
        hextx = hexlify(tx.serialize())
        r = self._call('signrawtransactionwithwallet', hextx, *args)
        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']
        return r
예제 #20
0
def mutate_tx(tx_hex):
    """
    Mutates a raw transaction using TX malleability in the scriptSig (specifically, the OP codes.) This function shouldn't be used beyond testing as it uses an ugly eval() hack.

    https://en.bitcoin.it/wiki/Transaction_Malleability
    """
    tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
    script_sig = repr(tx.vin[0].scriptSig)[9:]
    script_sig = eval("CScript([OP_1, OP_DROP, " + script_sig)
    tx.vin[0].scriptSig = script_sig
    return b2x(tx.serialize())
예제 #21
0
def mutate_tx(tx_hex):
    """
    Mutates a raw transaction using TX malleability in the scriptSig (specifically, the OP codes.) This function shouldn't be used beyond testing as it uses an ugly eval() hack.

    https://en.bitcoin.it/wiki/Transaction_Malleability
    """
    tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
    script_sig = repr(tx.vin[0].scriptSig)[9:]
    script_sig = eval("CScript([OP_1, OP_DROP, " + script_sig)
    tx.vin[0].scriptSig = script_sig
    return b2x(tx.serialize())
예제 #22
0
파일: stack.py 프로젝트: kryptoc/hashmal
 def set_tx(self):
     """Set the spending transaction and (en|dis)able the input index box."""
     txt = str(self.tx_edit.toPlainText())
     if not txt:
         self.tx = None
         self.input_idx.setEnabled(False)
         self.tx_edit.setToolTip('')
         return
     self.tx = CTransaction.deserialize(txt.decode('hex'))
     self.tx_edit.setToolTip(''.join(['Tx ID: ', bitcoin.core.b2lx(self.tx.GetHash())]))
     self.input_idx.setRange(0, len(self.tx.vin) - 1)
     self.input_idx.setEnabled(True)
예제 #23
0
    def __init__(self, tx_hex, targetScriptPubkey: CScript):
        self.tx = CTransaction.deserialize(x(tx_hex))
        self.txid = b2lx(self.tx.GetTxid())

        # TODO: assuming there is only one output with targetScriptPubkey
        self.nout = None
        for i, out in enumerate(self.tx.vout):
            if out.scriptPubKey == targetScriptPubkey:
                self.nout = i
                break

        assert self.nout is not None
        self.outpoint = COutPoint(lx(self.txid), self.nout)
 def set_transaction(self, name, tx_hex):
     self.transactions[name]["hex"] = tx_hex
     if tx_hex == None:
         self.transactions[name]["CTransaction"] = None
         self.transactions[name]["txid_hex"] = None
     else:
         self.transactions[name]["CTransaction"] = CTransaction.deserialize(
             binascii.unhexlify(self.transactions[name]["hex"]))
         self.transactions[name]["txid_hex"] = self.calculate_txid(
             self.transactions[name]["hex"])
     self.transactions[name]["is_broadcast"] = 0
     self.transactions[name]["confirmations"] = 0
     self.transactions[name]["malleability_occured"] = 0
예제 #25
0
    def signrawtransaction(self, tx, *args):
        """Sign inputs for transaction

        FIXME: implement options
        """
        if getattr(tx, "serialize", None) is not None:
            hextx = hexlify(tx.serialize())
        else:
            # then assume we got a raw string already
            hextx = tx
        r = self._call('signrawtransaction', hextx, *args)
        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']
        return r
예제 #26
0
    def signrawtransaction(self, tx, *args):
        """Sign inputs for transaction

        FIXME: implement options
        """
        if getattr(tx, "serialize", None) is not None:
            hextx = hexlify(tx.serialize())
        else:
            # then assume we got a raw string already
            hextx = tx
        r = self._call('signrawtransaction', hextx, *args)
        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']
        return r
예제 #27
0
    def action(self, runner: 'Runner') -> bool:
        super().action(runner)
        utxo_tx = self.resolve_arg('utxo_tx', runner, self.utxo_tx)
        txid = CTransaction.deserialize(
            bytes.fromhex(utxo_tx)).GetTxid()[::-1].hex()

        runner.init_rbf(
            self, self.find_conn(runner),
            self.resolve_arg('channel_id', runner, self.channel_id),
            self.resolve_arg('amount', runner, self.amount), txid,
            self.resolve_arg('utxo_outnum', runner, self.utxo_outnum),
            self.feerate)

        return True
def sign_setup_tx(tx_hex, redeem_script, ecdsa):
    tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
    sighash = SignatureHash(redeem_script["bin"], tx, 0, SIGHASH_ALL)

    print(b"Signing = " + sighash)
    
    print(ecdsa.get_public_key())

    seckey = CBitcoinSecret.from_secret_bytes(ecdsa.get_private_key("bin"), compressed=True)
    sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
    print(b"Pub key = " + ecdsa.get_public_key("bin"))

    print(b"Sig = " + sig)
    print()
    return sig
예제 #29
0
 def get_utxo(self, address):
     """Gets all the Unspent Transaction Outs from a given <address>
     """
     script_pubkey = CBitcoinAddress(address).to_scriptPubKey()
     txs = self.get_response("blockchain.address.get_history", [address])
     spent = {}
     utxos = []
     for tx in txs:
         raw = self.get_raw_transaction(tx["tx_hash"], tx["height"])
         data = CTransaction.deserialize(to_binary(raw))
         for vin in data.vin:
             spent[(to_little_endian_hex(vin.prevout.hash), vin.prevout.n)] = 1
         for outindex, vout in enumerate(data.vout):
             if vout.scriptPubKey == script_pubkey:
                 utxos += [(tx["tx_hash"], outindex, vout.nValue, to_hex(vout.scriptPubKey))]
     return [u for u in utxos if not u[0:2] in spent]
예제 #30
0
 def get_utxo(self, address):
     script_pubkey = CBitcoinAddress(address).to_scriptPubKey()
     txs = self.get_response('blockchain.address.get_history', [address])
     spent = {}
     utxos = []
     for tx in txs:
         print tx
         raw = self.get_raw_transaction(tx['tx_hash'], tx['height'])
         data = CTransaction.deserialize(to_binary(raw))
         for vin in data.vin:
             spent[(to_little_endian_hex(vin.prevout.hash),
                    vin.prevout.n)] = 1
         for outindex, vout in enumerate(data.vout):
             if vout.scriptPubKey == script_pubkey:
                 utxos += [(tx['tx_hash'], outindex, vout.nValue,
                            to_hex(vout.scriptPubKey))]
     return [u for u in utxos if not u[0:2] in spent]
예제 #31
0
def spend_preimage(redeem_script, preimages, redeemer_sig, serial_tx):
    """
    Creates a transaction fulfilling the redeem script of the preimage P2SH.

    Arguements:
        redeem_script (bytes): The script that specifies the conditions that a tx has
                        to fulfill to transfer funds from the `funding_tx`
        preimages (list): The preimages that hash into the hash values
                          specified in the `redeem_script`
        redeemer_sig (bytes): The signature of the redeemer on the `serial_tx`
        serial_tx (bytes): The serial transaction

    Returns:
        The serial raw transaction that passes the script verification
    """
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Setup preimages in reverse order
    script = []
    for p in reversed(preimages):
        script += [p]

    # Create script sig
    txin.scriptSig = CScript([redeemer_sig + '\x01'] + script +
                             [redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    try:
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])
    except ValidationError:
        print("spend_preimage: Script failed to verify")
        return None

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_preimage: TXID is %s" % txid)
    print("spend_preimage: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
예제 #32
0
    def deserialize(self):
        self.clear()
        txt = str(self.raw_tx_edit.toPlainText())
        try:
            txt = txt.decode('hex')
        except Exception:
            self.status_message('Raw transaction must be hex.', True)
            return
        try:
            self.tx = tx = CTransaction.deserialize(txt)
        except Exception:
            self.status_message('Cannot deserialize transaction.', True)
            return

        self.tx_widget.set_tx(tx)

        self.status_message('Deserialized transaction {}'.format(bitcoin.core.b2lx(tx.GetHash())))
    def test_path_from_msg_to_txid(self):
        def T(msg, tx):
            path = path_from_msg_to_txid(msg, tx)
            self.assertEqual(path(msg), tx.GetHash())

        tx = CTransaction.deserialize(x('0100000001e853c9e0c133547fd9e162b1d3860dd0f27d5b9b8a7430d28896c00fbb3f1bc7000000008c49304602210095bcd54ebd0caa7cee75f0f89de472a765e6ef4b98c5fd4b32c7f9d4905db9ae022100ebd3f668e3a1a36d56e30184c27531dbb9fc136c84b1282be562064d86997d1e014104727eb4fdcc90658cd26abe7dcb0ae7297810b15b9e27c32bcf8e3edd934901968806dc18b1276d7273cc4c223feee0070361ed947888a3cef422bebfede96e08ffffffff020065cd1d000000001976a91468c6c2b3c0bc4a8eeb10d16a300d627a31a3b58588ac0008af2f000000001976a9141d87f0a54a1d704ffc70eae83b025698bc0fdcfc88ac00000000'))

        # txid in vin
        T(lx('c71b3fbb0fc09688d230748a9b5b7df2d00d86d3b162e1d97f5433c1e0c953e8'), tx)

        # part of a script
        T(x('1d87f0a54a1d704ffc70eae83b025698bc0fdcfc'), tx)

        # beginning of the tx
        T(x('0100000001e853c9e0c133547fd9'), tx)

        # end of the tx
        T(x('98bc0fdcfc88ac00000000'), tx)
예제 #34
0
def spend_escrow(redeem_script, payer_sig, redeemer_sig, serial_tx):
    """
    Creates a transaction fulfilling the redeem script of the escrow P2SH.

    Arguements:
        redeem_script (bytes): The script that specifies the conditions that a tx has
                        to fulfill to transfer funds from the `funding_tx`
        payer_sig (bytes): The signature of the payer on the `serial_tx`
        redeemer_sig (bytes): The signature of the redeemer on the `serial_tx`
        serial_tx (bytes): The serial transaction

    Returns:
        The serial raw transaction that passes the script verification
    """
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Set script sig
    txin.scriptSig = CScript(
        [OP_0, payer_sig + '\x01', redeemer_sig + '\x01', redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    serial_tx = tx.serialize()

    try:
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])
    except ValidationError:
        print("spend_escrow: Script failed to verify")
        return None

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_escrow: TXID is %s" % txid)
    print("spend_escrow: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
def load_test_vectors(name):
    with open(os.path.dirname(__file__) + '/data/' + name, 'r') as fd:
        for test_case in json.load(fd):
            # Comments designated by single length strings
            if len(test_case) == 1:
                continue
            assert len(test_case) == 3

            prevouts = {}
            for json_prevout in test_case[0]:
                assert len(json_prevout) == 3
                n = json_prevout[1]
                if n == -1:
                    n = 0xffffffff
                prevout = COutPoint(lx(json_prevout[0]), n)
                prevouts[prevout] = parse_script(json_prevout[2])

            tx = CTransaction.deserialize(x(test_case[1]))
            enforceP2SH = test_case[2]

            yield (prevouts, tx, enforceP2SH)
예제 #36
0
    def fundrawtransaction(self, tx, include_watching=False):
        """Add inputs to a transaction until it has enough in value to meet its out value.

        include_watching - Also select inputs which are watch only

        Returns dict:

        {'tx':        Resulting tx,
         'fee':       Fee the resulting transaction pays,
         'changepos': Position of added change output, or -1,
        }
        """
        hextx = hexlify(tx.serialize())
        r = self._call('fundrawtransaction', hextx, include_watching)

        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']

        r['fee'] = int(r['fee'] * COIN)

        return r
예제 #37
0
    def fundrawtransaction(self, tx, include_watching=False):
        """Add inputs to a transaction until it has enough in value to meet its out value.

        include_watching - Also select inputs which are watch only

        Returns dict:

        {'tx':        Resulting tx,
         'fee':       Fee the resulting transaction pays,
         'changepos': Position of added change output, or -1,
        }
        """
        hextx = hexlify(tx.serialize())
        r = self._call('fundrawtransaction', hextx, include_watching)

        r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
        del r['hex']

        r['fee'] = int(r['fee'] * COIN)

        return r
예제 #38
0
def load_test_vectors(name):
    with open(os.path.dirname(__file__) + '/data/' + name, 'r') as fd:
        for test_case in json.load(fd):
            # Comments designated by single length strings
            if len(test_case) == 1:
                continue
            assert len(test_case) == 3

            prevouts = {}
            for json_prevout in test_case[0]:
                assert len(json_prevout) == 3
                n = json_prevout[1]
                if n == -1:
                    n = 0xffffffff
                prevout = COutPoint(lx(json_prevout[0]), n)
                prevouts[prevout] = parse_script(json_prevout[2])

            tx = CTransaction.deserialize(x(test_case[1]))
            enforceP2SH = test_case[2]

            yield (prevouts, tx, enforceP2SH)
예제 #39
0
파일: tx.py 프로젝트: mbaniasad/ahunavar
    def get_keys_from_tx(self, serial_tx, n_keys=15):
        '''Extracts n_keys from tx in serial form'''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        # Keys are in txin.scriptSig
        txin = tx.vin[0]
        script = txin.scriptSig

        # Extract keys from script
        keys = []
        for i, op in enumerate(script):
            if i in range(1, n_keys + 1):
                keys += [op]

        # Serialize keys in correct order
        serial_keys = ""
        for op in reversed(keys):
            serial_keys += op

        return serial_keys
def check_setup_works(tx_hex, redeem_script, owner_first_sig, owner_second_sig, third_party_sig):
    try:
        tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
        redeem_script_hash160 = hash160_script(redeem_script)

        if owner_first_sig != None and owner_second_sig != None and third_party_sig != None:
            tx.vin[0].scriptSig = CScript([OP_0, owner_first_sig, owner_second_sig, third_party_sig, redeem_script["bin"]])
        p2sh_script_pub_key = CScript([OP_HASH160, redeem_script_hash160["bin"], OP_EQUAL])

        VerifyScript(tx.vin[0].scriptSig, p2sh_script_pub_key, tx, 0, (SCRIPT_VERIFY_P2SH,))
        signed_tx_hex = b2x(tx.serialize())
        return {
            "tx_hex": signed_tx_hex,
            "txid": calculate_txid(signed_tx_hex)
        }
    except Exception as e:
        error = parse_exception(e)
        log_exception(error_log_path, error)
        print(error)
        print("Check setup works failed.")
        print(e)
        return None
예제 #41
0
    def deserialize_raw_transaction(raw_transaction: str) -> CTransaction:
        '''
        Checking if transaction can be deserialized (is not corrupted).

        Args:
            raw_transaction (str): transaction to check

        Returns:
            CTransaction: transaction object

        Raises:
            ImpossibleDeserialization: when transaction is corrupted

        Example:
            >>> from clove.network import Litecoin
            >>> network = Litecoin()
            >>> network.deserialize_raw_transaction('0100000001aa25fd5f63cb41d6ee7dd495256046b4c3f17d4540a1b258a06bfefac30da60900000000fdff0047304402201c8869d359b5599ecffd51a96f0a8799392c98c4e15242762ba455e37b1f5d6302203f2974e9afc8d641f9363167df48e5a845a8deba1381bf5a1b549ac04718a1ac01410459cdb91eb7298bc2578dc4e7ac2109ac3cfd9dc9818795c5583e720d2114d540724bf26b4541f683ff51968db627a04eecd1f5cff615b6350dad5fb595f8adf420c480afb333623864901c968022a07dd93fe3c06f5684ea728b8113e17fa91bd9514c5163a61450314a793bf317665ecdc54c2e843bb106aeee158876a91485c0522f6e23beb11cc3d066cd20ed732648a4e66704926db75bb17576a914621f617c765c3caa5ce1bb67f6a3e51382b8da296888ac00000000015a7b0100000000001976a91485c0522f6e23beb11cc3d066cd20ed732648a4e688ac00000000')  # noqa: E501
            CTransaction((CTxIn(COutPoint(lx('09a60dc3fafe6ba058b2a140457df1c3b446602595d47deed641cb635ffd25aa'), 0), CScript([x('304402201c8869d359b5599ecffd51a96f0a8799392c98c4e15242762ba455e37b1f5d6302203f2974e9afc8d641f9363167df48e5a845a8deba1381bf5a1b549ac04718a1ac01'), x('0459cdb91eb7298bc2578dc4e7ac2109ac3cfd9dc9818795c5583e720d2114d540724bf26b4541f683ff51968db627a04eecd1f5cff615b6350dad5fb595f8adf4'), x('c480afb333623864901c968022a07dd93fe3c06f5684ea728b8113e17fa91bd9'), 1, x('63a61450314a793bf317665ecdc54c2e843bb106aeee158876a91485c0522f6e23beb11cc3d066cd20ed732648a4e66704926db75bb17576a914621f617c765c3caa5ce1bb67f6a3e51382b8da296888ac')]), 0x0),), (CTxOut(0.00097114*COIN, CScript([OP_DUP, OP_HASH160, x('85c0522f6e23beb11cc3d066cd20ed732648a4e6'), OP_EQUALVERIFY, OP_CHECKSIG])),), 0, 1, CTxWitness())  # noqa: E501
        '''
        try:
            return CTransaction.deserialize(x(raw_transaction))
        except Exception:
            raise ImpossibleDeserialization()
예제 #42
0
파일: tx.py 프로젝트: mbaniasad/ahunavar
    def spend_preimage(self, preimages, redeemer_sig, serial_tx,
                       redeem_script):
        '''
            Sends a transaction fulfilling the redeem script
            of the preimage P2SH
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Setup preimages in reverse order
        script = []
        for p in reversed(preimages):
            script += [p]

        # Create script sig
        txin.scriptSig = CScript([redeemer_sig + '\x01'] + script +
                                 [OP_TRUE, redeem_script])

        # Verify script
        redeem_script = CScript(redeem_script)
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("spend_preimage: TXID is %s", txid)
        self.logger.info("spend_preimage: RAW TX is %s", b2x(serial_tx))

        return serial_tx
예제 #43
0
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(unhexlify(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return hexlify(bytearray(tx_id)[::-1])
예제 #44
0
 def get_tx(self, txhash):
     """Get the transaction object given a transaction hash.
     """
     txhex = self.get_raw_transaction(txhash)
     tx = CTransaction.deserialize(to_binary(txhex))
     return blockchain.CTransaction.from_bitcoincore(txhash, tx, self)
예제 #45
0
 def get_tx(self, txhash):
     """Get the transaction object given a transaction hash.
     """
     txhex = self.get_raw_transaction(txhash)
     tx = CTransaction.deserialize(to_binary(txhex))
     return blockchain.CTransaction.from_bitcoincore(txhash, tx, self)
예제 #46
0
    def str_tree(self, indent=0, verbosity=0):
        """Convert to tree (for debugging)"""

        class bcolors:
            HEADER = '\033[95m'
            OKBLUE = '\033[94m'
            OKGREEN = '\033[92m'
            WARNING = '\033[93m'
            FAIL = '\033[91m'
            ENDC = '\033[0m'
            BOLD = '\033[1m'
            UNDERLINE = '\033[4m'

        def str_result(verb, parameter, result):
            rr = ""
            if verb > 0 and result is not None:
                rr += " == "
                result_hex = b2x(result)
                if parameter is not None:
                    parameter_hex = b2x(parameter)
                    try:
                        index = result_hex.index(parameter_hex)
                        parameter_hex_highlight = bcolors.BOLD + parameter_hex + bcolors.ENDC
                        if index == 0:
                            rr += parameter_hex_highlight + result_hex[index+len(parameter_hex):]
                        else:
                            rr += result_hex[0:index] + parameter_hex_highlight
                    except ValueError:
                        rr += result_hex
                else:
                    rr += result_hex

            return rr

        r = ""
        if len(self.attestations) > 0:
            for attestation in sorted(self.attestations):
                r += " "*indent + "verify %s" % str(attestation) + str_result(verbosity, self.msg, None) + "\n"
                if attestation.__class__ == BitcoinBlockHeaderAttestation:
                    r += " "*indent + "# Bitcoin block merkle root " + b2lx(self.msg) + "\n"

        if len(self.ops) > 1:
            for op, timestamp in sorted(self.ops.items()):
                try:
                    CTransaction.deserialize(self.msg)
                    r += " " * indent + "* Bitcoin transaction id " + b2lx(
                        OpSHA256()(OpSHA256()(self.msg))) + "\n"
                except SerializationError:
                    pass
                cur_res = op(self.msg)
                cur_par = op[0]
                r += " " * indent + " -> " + "%s" % str(op) + str_result(verbosity, cur_par, cur_res) + "\n"
                r += timestamp.str_tree(indent+4, verbosity=verbosity)
        elif len(self.ops) > 0:
            try:
                CTransaction.deserialize(self.msg)
                r += " " * indent + "# Bitcoin transaction id " + \
                     b2lx(OpSHA256()(OpSHA256()(self.msg))) + "\n"
            except SerializationError:
                pass
            op = tuple(self.ops.keys())[0]
            cur_res = op(self.msg)
            cur_par = op[0] if len(op) > 0 else None
            r += " " * indent + "%s" % str(op) + str_result(verbosity, cur_par, cur_res) + "\n"
            r += tuple(self.ops.values())[0].str_tree(indent, verbosity=verbosity)

        return r
예제 #47
0
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(h2b(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return b2h_rev(tx_id)
예제 #48
0
def bitcoind_broadcast(hextx):
    tx = CTransaction.deserialize(unhexlify(hextx))
    txid = bitcoin.rpc.Proxy().sendrawtransaction(tx)
    return hexlify(txid)
예제 #49
0
def compare_transactions(tx_hex1, tx_hex2):
    """
    This function compares two transactions. It is required
    because attackers can change serialized transactions without
    invalidating the transaction by modifying a scriptSig or
    by changing a signature which would change the transaction
    ID. This function considers transactions equivalent if
    they share the same inputs and outputs. The scriptSig
    doesn't matter for the purposes of this function. The
    risk of replacing a valid transaction with an invalid
    one with false scriptSigs doesn't occur as subsequent
    code [in this module] only replaces transactions if
    they have at least 1 confirmation. I'm sure Bitcoind
    also wouldn't allow invalid transactions into the
    mempool, disk, etc.
    """
    try:
        if tx_hex1 == tx_hex2:
            #Well, that was easy. Now for the hard part.
            return 1
        
        tx1 = CTransaction.deserialize(binascii.unhexlify(tx_hex1))
        tx2 = CTransaction.deserialize(binascii.unhexlify(tx_hex2))
        
        #Compare number of inputs.
        if len(tx1.vin) != len(tx2.vin):
            return 0
        
        #Compare number of outputs.
        if len(tx1.vout) != len(tx2.vout):
            return 0
            
        #Compare nVersion.
        if tx1.nVersion != tx2.nVersion:
            return 0
            
        #Compare nLockTime.
        if tx1.nLockTime != tx2.nLockTime:
            return 0
            
        #Compare inputs.
        for i in range(0, len(tx1.vin)):
            #Compare sequences.
            #To keep it simple: tx replacement isn't supported.
            if tx1.vin[i].nSequence != tx2.vin[i].nSequence:
                return 0
            
            #Compare outpoints.
            if tx1.vin[i].prevout.hash != tx2.vin[i].prevout.hash:
                return 0
            if tx1.vin[i].nSequence != tx2.vin[i].nSequence:
                return 0

        #Compare outputs.
        for i in range(0, len(tx2.vout)):
            if tx1.vout[i] != tx2.vout[i]:
                return 0

        #Sighash and sigs aren't checked as this code is run on TXs returned from *coind.
        
        return 1
    except:
        return 0
    def adjust_refund_tx(self, our_setup_txid, their_setup_tx_hex, their_refund_tx_hex, received_tx_hex=None, their_first_sig=None, their_second_sig=None):
        #Calculate chunk sizes.
        remaining = self.upload_amount - self.trade.sent
        send_chunk_size = self.our_chunk_size
        if send_chunk_size > remaining:
            send_chunk_size = remaining
        remaining = self.download_amount - self.trade.recv
        recv_chunk_size = self.their_chunk_size
        if recv_chunk_size > remaining:
            recv_chunk_size = remaining

        #Validate transactions.
        if received_tx_hex != None and their_first_sig != None and their_second_sig != None:
            #Check their refund spends the output of the bond.
            their_refund_tx = CTransaction.deserialize(binascii.unhexlify(their_refund_tx_hex))
            their_setup_txid = calculate_txid(their_setup_tx_hex)
            if reverse_hex(binascii.hexlify(their_refund_tx.vin[0].prevout.hash).decode("utf-8")) != their_setup_txid:
                print("11111")
                return None
            else:
                """
                try:
                    #Ensure the bond transaction has been broadcast.
                    self.recv_coin_rpc.sendrawtransaction(their_bond_tx_hex)

                    #(Subsequent code will fail since bond has only just been broadcast.)
                    #return None
                except Exception as e:
                    #Transaction already in block chain.
                    pass
                """

            #Check our received payment is as expected.
            unsigned_tx = CTransaction.deserialize(binascii.unhexlify(received_tx_hex))
            expected = self.trade.recv + recv_chunk_size

            #Check transaction input.
            their_alleged_setup_txid = reverse_hex(binascii.hexlify(unsigned_tx.vin[0].prevout.hash).decode("utf-8"))
            if their_alleged_setup_txid != their_setup_txid:
                #Give them the benefit of the doubt - look for tx malluability.
                alleged_setup_tx_hex = recv_coin_rpc.getrawtransaction(their_alleged_setup_txid)
                if not compare_transactions(alleged_setup_tx_hex, their_setup_tx_hex):
                    print("22222222@")
                    return None

            #This is what our output -should- look like.
            our_address = deconstruct_address(self.our_address)["hash"]
            our_pub_key = CScript([OP_DUP, OP_HASH160, our_address, OP_EQUALVERIFY, OP_CHECKSIG])

            #Check an output goes to us with expected amount.
            amount_found = 0
            for output in unsigned_tx.vout:
                print(output.scriptPubKey)
                print(our_pub_key)
                if output.scriptPubKey == our_pub_key:
                    amount_found = Decimal(str_money_value(output.nValue))
                    break
            if not amount_found:
                print(our_pub_key)
                print(unsigned_tx.vout)
                print("333333333333")
                return None
            else:
                #Check amount.
                if amount_found < expected.as_decimal:
                    print("43535345346")
                    print(amount_found)
                    print(expected.as_decimal)
                    return None

            #Check transaction isn't time locked.
            if unsigned_tx.nLockTime:
                print("4444444444")
                return None

            #Check sequences are final.
            for input in unsigned_tx.vin:
                if input.nSequence != 0xffffffff:
                    print("55555555555")
                    return None

            #Check transaction can be spent.
            our_first_sig = self.sign_refund_tx(received_tx_hex, 1, "them")
            ret = self.check_refund_works(received_tx_hex, their_first_sig, their_second_sig, our_first_sig, "them")
            if ret == None:
                print("6666666666666")
                return None
            self.details["our_download"] = ret
        else:
            #The first call to this function has nothing to evaluate -- you are receiving nothing.
            recv_chunk_size = 0

        #Adjust refund.
        refund_amount = self.trade.sent + send_chunk_size
        print("sdfsdfsdf--------")
        print(refund_amount)
        refund_tx_hex = self.build_refund_tx(our_setup_txid, refund_amount)["tx_hex"]
        self.trade.sent += send_chunk_size
        self.trade.recv += recv_chunk_size

        #Save details.
        self.update()

        #Is transfer complete? I.e. no change = transfer complete.
        if send_chunk_size == C(0) and recv_chunk_size == C(0):
            #I liek chocolate milk.
            return 1
        
        #Return result.
        our_first_sig = self.sign_refund_tx(refund_tx_hex, 1)
        our_second_sig = self.sign_refund_tx(refund_tx_hex, 2)
        return {
            "tx_hex": refund_tx_hex,
            "first_sig": our_first_sig,
            "second_sig": our_second_sig
        }
예제 #51
0
 def ctx_deserialize(cls, ctx):
     serialized_tx = ctx.read_bytes('tx')
     return CTransaction.deserialize(serialized_tx)
예제 #52
0
    def str_tree(self, indent=0, verbosity=0):
        """Convert to tree (for debugging)"""
        class bcolors:
            HEADER = '\033[95m'
            OKBLUE = '\033[94m'
            OKGREEN = '\033[92m'
            WARNING = '\033[93m'
            FAIL = '\033[91m'
            ENDC = '\033[0m'
            BOLD = '\033[1m'
            UNDERLINE = '\033[4m'

        def str_result(verb, parameter, result):
            rr = ""
            if verb > 0 and result is not None:
                rr += " == "
                result_hex = b2x(result)
                if parameter is not None:
                    parameter_hex = b2x(parameter)
                    try:
                        index = result_hex.index(parameter_hex)
                        parameter_hex_highlight = bcolors.BOLD + parameter_hex + bcolors.ENDC
                        if index == 0:
                            rr += parameter_hex_highlight + result_hex[
                                index + len(parameter_hex):]
                        else:
                            rr += result_hex[0:index] + parameter_hex_highlight
                    except ValueError:
                        rr += result_hex
                else:
                    rr += result_hex

            return rr

        r = ""
        if len(self.attestations) > 0:
            for attestation in sorted(self.attestations):
                r += " " * indent + "verify %s" % str(
                    attestation) + str_result(verbosity, self.msg, None) + "\n"
                if attestation.__class__ == BitcoinBlockHeaderAttestation:
                    r += " " * indent + "# Bitcoin block merkle root " + b2lx(
                        self.msg) + "\n"

        if len(self.ops) > 1:
            for op, timestamp in sorted(self.ops.items()):
                try:
                    CTransaction.deserialize(self.msg)
                    r += " " * indent + "* Bitcoin transaction id " + b2lx(
                        OpSHA256()(OpSHA256()(self.msg))) + "\n"
                except SerializationError:
                    pass
                cur_res = op(self.msg)
                cur_par = op[0]
                r += " " * indent + " -> " + "%s" % str(op) + str_result(
                    verbosity, cur_par, cur_res) + "\n"
                r += timestamp.str_tree(indent + 4, verbosity=verbosity)
        elif len(self.ops) > 0:
            try:
                CTransaction.deserialize(self.msg)
                r += " " * indent + "# Bitcoin transaction id " + \
                     b2lx(OpSHA256()(OpSHA256()(self.msg))) + "\n"
            except SerializationError:
                pass
            op = tuple(self.ops.keys())[0]
            cur_res = op(self.msg)
            cur_par = op[0] if len(op) > 0 else None
            r += " " * indent + "%s" % str(op) + str_result(
                verbosity, cur_par, cur_res) + "\n"
            r += tuple(self.ops.values())[0].str_tree(indent,
                                                      verbosity=verbosity)

        return r
예제 #53
0
 def broadcast_tx(self, transaction):
     as_hex = transaction.as_hex()
     transaction = CTransaction.deserialize(unhexlify(as_hex))
     tx_id = bitcoin.rpc.Proxy().sendrawtransaction(transaction)
     # reverse endianness for bitcoind
     return hexlify(bytearray(tx_id)[::-1])
예제 #54
0
if args.testnet:
    bitcoin.SelectParams('testnet')

proxy = bitcoin.rpc.Proxy()

txins = []
prevouts = set()
sum_value_in = 0
line = -1
for l in sys.stdin.readlines():
    line += 1

    l = l.strip()

    try:
        tx = CTransaction.deserialize(x(l))
    except Exception:
        continue


    for txin in tx.vin:
        try:
            txout_info = proxy.gettxout(txin.prevout)
        except IndexError:
            print('Already spent! line %d, txid %s %d' % \
                    (line, b2lx(txin.prevout.hash), txin.prevout.n),
                    file=sys.stderr)
            continue

        print('line %d: %s %d: %s' % \
                (line, b2lx(txin.prevout.hash), txin.prevout.n,
예제 #55
0
 def __init__(self, txid, rawhex):
     self.ct = CTransaction.deserialize(x(rawhex))
     self.txid = txid
예제 #56
0
 def deserialize_raw_transaction(raw_transaction: str) -> CTransaction:
     try:
         return CTransaction.deserialize(x(raw_transaction))
     except Exception:
         raise ImpossibleDeserialization()
예제 #57
0
	def connect(self):
		self.send_lock.acquire()
		self.recv_transaction_cache = FlaggedArraySet(1000)
		self.send_transaction_cache = FlaggedArraySet(1000)
		self.relay_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		self.relay_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
		try:
			try:
				self.relay_sock.connect((self.server, 8336))
				self.relay_sock.sendall(pack('>3I', self.MAGIC_BYTES, self.VERSION_TYPE, len(self.VERSION_STRING)))
				self.relay_sock.sendall(self.VERSION_STRING)
			finally:
				self.send_lock.release()

			while True:
				msg_header = unpack('>3I', self.relay_sock.recv(3 * 4, socket.MSG_WAITALL))
				if msg_header[0] != self.MAGIC_BYTES:
					raise ProtocolError("Invalid magic bytes: " + str(msg_header[0]) + " != " +  str(self.MAGIC_BYTES))
				if msg_header[2] > 1000000:
					raise ProtocolError("Got message too large: " + str(msg_header[2]))

				if msg_header[1] == self.VERSION_TYPE:
					version = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					if version != self.VERSION_STRING:
						raise ProtocolError("Got back unknown version type " + str(version))
					print("Connected to relay node with protocol version " + str(version))
				elif msg_header[1] == self.BLOCK_TYPE:
					if msg_header[2] > 10000:
						raise ProtocolError("Got a BLOCK message with far too many transactions: " + str(msg_header[2]))

					wire_bytes = 3 * 4

					header_data = self.relay_sock.recv(80, socket.MSG_WAITALL)
					wire_bytes += 80
					self.data_recipient.provide_block_header(header_data)
					if deserialize_utils:
						header = CBlockHeader.deserialize(header_data)
						print("Got block header: " + str(b2lx(header.GetHash())))

					if msg_header[2] < 0xfd:
						block_data = header_data + pack('B', msg_header[2])
					elif msg_header[2] < 0xffff:
						block_data = header_data + b'\xfd' + pack('<H', msg_header[2])
					elif msg_header[2] < 0xffffffff:
						block_data = header_data + b'\xfe' + pack('<I', msg_header[2])
					else:
						raise ProtocolError("WTF?????")

					for i in range(0, msg_header[2]):
						index = unpack('>H', self.relay_sock.recv(2, socket.MSG_WAITALL))[0]
						wire_bytes += 2
						if index == 0xffff:
							data_length = unpack('>HB', self.relay_sock.recv(3, socket.MSG_WAITALL))
							wire_bytes += 3
							data_length = data_length[0] << 8 | data_length[1]
							if data_length > 1000000:
								raise ProtocolError("Got in-block transaction of size > MAX_BLOCK_SIZE: " + str(dat_length))
							transaction_data = self.relay_sock.recv(data_length, socket.MSG_WAITALL)
							wire_bytes += data_length
							if deserialize_utils:
								transaction = CTransaction.deserialize(transaction_data)
								print("Got in-block full transaction: " + str(b2lx(transaction.GetHash())) + " of length " + str(data_length))
							else:
								print("Got in-block full transaction of length " + str(data_length))
							block_data += transaction_data
						else:
							transaction_data = self.recv_transaction_cache.get_by_index(index)
							if transaction_data is None:
								raise ProtocolError("Got index for a transaction we didn't have")
							self.recv_transaction_cache.remove(transaction_data)
							block_data += transaction_data

					self.data_recipient.provide_block(block_data)

					if deserialize_utils:
						print("Got full block " + str(b2lx(header.GetHash())) + " with " + str(msg_header[2]) + " transactions in " + str(wire_bytes) + " wire bytes")
						block = CBlock.deserialize(block_data)
						print("Deserialized full block " + str(b2lx(block.GetHash())))
					else:
						print("Got full block with " + str(msg_header[2]) + " transactions in " + str(wire_bytes) + " wire bytes")

					if unpack('>3I', self.relay_sock.recv(3 * 4, socket.MSG_WAITALL)) != (self.MAGIC_BYTES, self.END_BLOCK_TYPE, 0):
						raise ProtocolError("Invalid END_BLOCK message after block")

				elif msg_header[1] == self.TRANSACTION_TYPE:
					if msg_header[2] > self.MAX_RELAY_TRANSACTION_BYTES and (self.recv_transaction_cache.get_flag_count() >= self.MAX_EXTRA_OVERSIZE_TRANSACTIONS or msg_header[2] > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES):
						raise ProtocolError("Got a freely relayed transaction too large (" + str(msg_header[2]) + ") bytes")
					transaction_data = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					self.recv_transaction_cache.add(transaction_data, msg_header[2] > self.MAX_RELAY_OVERSIZE_TRANSACTION_BYTES)

					self.data_recipient.provide_transaction(transaction_data)

					if deserialize_utils:
						transaction = CTransaction.deserialize(transaction_data)
						print("Got transaction: " + str(b2lx(transaction.GetHash())))
					else:
						print("Got transaction of length " + str(msg_header[2]))

				elif msg_header[1] == self.MAX_VERSION_TYPE:
					version = self.relay_sock.recv(msg_header[2], socket.MSG_WAITALL)
					print("Relay network now uses version " + str(version) + " (PLEASE UPGRADE)")

				else:
					raise ProtocolError("Unknown message type: " + str(msg_header[1]))

		except (OSError, socket.error) as err:
			print("Lost connect to relay node:", err)
			self.reconnect()
		except ProtocolError as err:
			print("Error processing data from relay node:", err)
			self.reconnect()
		except Exception as err:
			print("Unknown error processing data from relay node:", err)
			self.reconnect()