Ejemplo n.º 1
0
def is_valid_addr(address: str, token_name: str) -> bool:

    try:
        if token_name == 'HTDF':
            return len(address) == 43 and  address.startswith('htdf1') and address.islower()
        elif token_name == 'ETH' or token_name == 'USDT':
            return len(address) == 42 and  address.startswith('0x') and  int(address, base=16)
        elif token_name == 'BTC':
            if g_IS_MAINNET:
                SelectParams('mainnet')
                addr = CBitcoinAddress(s = address)
            else:
                SelectParams('testnet')
                addr = CBitcoinAddress(s = address)

            assert addr is not None , 'addr is None'

            #如果没有抛异常直接返回即可
            return True
        else:
            raise RuntimeError(f"unknow token_name: {token_name}")
    except Exception as e:
        logger.error(f'is_valid_addr() , {address} is invalid address, error:{e}')
        return False
    pass
Ejemplo n.º 2
0
def test_emergency_txout(bitcoind):
    """Test mostly the emergency tx locktime"""
    amount = Decimal("50") - Decimal("500") / Decimal(COIN)
    privkeys = [CKey(os.urandom(32)) for _ in range(4)]
    pubkeys = [k.pub for k in privkeys]
    txo = emergency_txout(pubkeys, COIN * amount)
    addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    # This makes a transaction with only one vout
    txid = bitcoind.pay_to(addr, amount)
    new_amount = amount - Decimal("500") / Decimal(COIN)
    addr = bitcoind.getnewaddress()
    txin = CTxIn(COutPoint(lx(txid), 0), nSequence=4464)
    txout = CTxOut(new_amount * COIN, CBitcoinAddress(addr).to_scriptPubKey())
    tx = CMutableTransaction([txin], [txout], nVersion=2)
    tx_hash = SignatureHash(emergency_script(pubkeys), tx, 0, SIGHASH_ALL,
                            int(amount * COIN), SIGVERSION_WITNESS_V0)
    sigs = [k.sign(tx_hash) + bytes([SIGHASH_ALL]) for k in privkeys]
    witness_script = [bytes(0), *sigs, emergency_script(pubkeys)]
    tx.wit = CTxWitness([CTxInWitness(CScriptWitness(witness_script))])
    # 1 month of locktime
    bitcoind.generate_block(4464 - 2)
    with pytest.raises(VerifyRejectedError, match="non-BIP68-final"):
        bitcoind.send_tx(tx.serialize().hex())
    bitcoind.generate_block(1)
    bitcoind.send_tx(tx.serialize().hex())
    assert bitcoind.has_utxo(addr)
Ejemplo n.º 3
0
def partial_spend_p2sh_mediator(redeemScript,
                                rein,
                                mediator_address,
                                mediator_sig=False):
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    (txins, total_value) = unspent_txins(txin_p2sh_address, rein.testnet)
    if len(txins) == 0:
        raise ValueError('No unspent txins found')
    txins_str = ""
    txins_obj = []
    for txid, vout in txins:
        txins_str += " " + txid + "-" + str(vout)
        txins_obj.append(CMutableTxIn(COutPoint(lx(txid), vout)))
    fee = 0.00025
    amount = round(total_value - fee, 8)
    if amount <= 0:
        raise ValueError('Not enough value in the inputs')
    if mediator_sig:
        txout = CMutableTxOut(
            amount * COIN,
            CBitcoinAddress(mediator_address).to_scriptPubKey())
        tx = CMutableTransaction(txins_obj, [txout])
        seckey = CBitcoinSecret(rein.user.dkey)
        ntxins = len(txins_obj)
        sig = ""
        for i in range(0, ntxins):
            sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
            sig += " " + b2x(seckey.sign(sighash) + x("01"))
        return (txins_str[1:], "{:.8f}".format(amount), str(mediator_address),
                sig[1:])
    return (txins_str[1:], "{:.8f}".format(amount), str(mediator_address))
Ejemplo n.º 4
0
def hashtimelockcontract(funder, redeemer, secret, locktime):
    funderAddr = CBitcoinAddress(funder)
    redeemerAddr = CBitcoinAddress(redeemer)
    h = sha256(secret)
    blocknum = bitcoind.getblockcount()
    print("Current blocknum", blocknum)
    redeemblocknum = blocknum + locktime
    print("REDEEMBLOCKNUM BITCOIN", redeemblocknum)
    redeemScript = CScript([
        OP_IF, OP_SHA256, h, OP_EQUALVERIFY, OP_DUP, OP_HASH160, redeemerAddr,
        OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_DUP,
        OP_HASH160, funderAddr, OP_ENDIF, OP_EQUALVERIFY, OP_CHECKSIG
    ])
    print("Redeem script for p2sh contract on Bitcoin blockchain:",
          b2x(redeemScript))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    # Convert the P2SH scriptPubKey to a base58 Bitcoin address
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    p2sh = str(txin_p2sh_address)
    return {
        'p2sh': p2sh,
        'redeemblocknum': redeemblocknum,
        'redeemScript': b2x(redeemScript),
        'redeemer': redeemer,
        'funder': funder
    }
Ejemplo n.º 5
0
def hashtimelockcontract(proxy, funder, redeemer, commitment, locktime):
    funderAddr = CBitcoinAddress('ms6KpXRvUwwygwzgRoANRwgcGskXcnEwAr')
    redeemerAddr = CBitcoinAddress('mph94e6SCNUPpyZBhBXHdRZyz1f4DDzeJK')

    if type(commitment) == str:
        commitment = x(commitment)
    else:
        raise ValueError("Commitment was not a string: {0}".format(commitment))
    blocknum = proxy.getblockcount()
    print("Current blocknum on Bitcoin: ", blocknum)
    redeemblocknum = blocknum + locktime
    print("Redeemblocknum on Bitcoin: ", redeemblocknum)
    redeemScript = CScript([
        OP_IF, OP_SHA256, commitment, OP_EQUALVERIFY, OP_DUP, OP_HASH160,
        redeemerAddr, OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY,
        OP_DROP, OP_DUP, OP_HASH160, funderAddr, OP_ENDIF, OP_EQUALVERIFY,
        OP_CHECKSIG])
    # print("Redeem script for p2sh contract on Bitcoin blockchain: "
    #        "{0}".format(b2x(redeemScript)))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    # Convert the P2SH scriptPubKey to a base58 Bitcoin address
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(
        txin_scriptPubKey)
    p2sh = str(txin_p2sh_address)
    # Import address at same time you create
    proxy.importaddress(p2sh, "", False)
    print("p2sh computed", p2sh)
    return {'p2sh': p2sh,
            'redeemblocknum': redeemblocknum,
            'redeemScript': b2x(redeemScript),
            'redeemer': redeemer,
            'funder': funder,
            'locktime': locktime}
Ejemplo n.º 6
0
def create_transaction_output(address, transaction_fee):
    """
    Create a single transaction output
    :param address:
    :param transaction_fee:
    :return:
    """
    addr = CBitcoinAddress(address)
    tx_out = CMutableTxOut(transaction_fee, addr.to_scriptPubKey())
    return tx_out
Ejemplo n.º 7
0
def create_transaction_output(address, transaction_fee):
    """
    Create a single transaction output
    :param address:
    :param transaction_fee:
    :return:
    """
    bitcoin_address = CBitcoinAddress(address)
    tx_out = CMutableTxOut(transaction_fee, bitcoin_address.to_scriptPubKey())
    return tx_out
Ejemplo n.º 8
0
def create_transaction_output(address, output_value):
    """
    Create a single transaction output
    :param address:
    :param output_value:
    :return:
    """
    bitcoin_address = CBitcoinAddress(address)
    tx_out = CMutableTxOut(output_value, bitcoin_address.to_scriptPubKey())
    return tx_out
Ejemplo n.º 9
0
def partial_spend_p2sh(redeemScript,
                       rein,
                       daddr=None,
                       alt_amount=None,
                       alt_daddr=None):
    if daddr is None:
        daddr = rein.user.daddr
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    (txins, total_value) = unspent_txins(txin_p2sh_address, rein.testnet)
    if len(txins) == 0:
        raise ValueError(
            'Primary escrow is empty. Please inform client to add funds.')
    txins_str = ""
    txins_obj = []
    for txid, vout in txins:
        txins_str += " " + txid + "-" + str(vout)
        txins_obj.append(CMutableTxIn(COutPoint(lx(txid), vout)))
    fee = float(PersistConfig.get(rein, 'fee', 0.001))
    amount = round(total_value - fee, 8)
    if alt_amount:
        amount = round(amount - alt_amount, 8)
    if amount <= 0. or alt_amount > total_value - fee:
        click.echo("amount: " + str(amount) + " alt_amount: " +
                   str(alt_amount) + " total_value: " + str(total_value))
        raise ValueError(
            'Primary escrow balance too low. Please inform client to add funds.'
        )
    txouts = []
    txout = CMutableTxOut(amount * COIN,
                          CBitcoinAddress(daddr).to_scriptPubKey())
    txouts.append(txout)
    if alt_amount:
        txout_alt = CMutableTxOut(
            round(alt_amount, 8) * COIN,
            CBitcoinAddress(alt_daddr).to_scriptPubKey())
        txouts.append(txout_alt)
    tx = CMutableTransaction(txins_obj, txouts)
    ntxins = len(txins_obj)
    seckey = CBitcoinSecret(rein.user.dkey)
    sig = ""
    for i in range(0, ntxins):
        sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
        sig += " " + b2x(seckey.sign(sighash)) + "01"
    if alt_amount:
        return (txins_str[1:], "{:.8f}".format(amount), daddr,
                "{:.8f}".format(alt_amount), alt_daddr, sig[1:])
    return (txins_str[1:], "{:.8f}".format(amount), daddr, sig[1:])
    def make_unsigned(cls,
                      outpoints,
                      outputs,
                      tx_fee=TRANSACTION_FEE,
                      testnet=False,
                      out_value=None):
        """
        Build an unsigned transaction.

        Args:
            outpoints: A `list` of `dict` objects which contain a txid, vout, value, and scriptPubkey.
            outputs: If a single address the full value of the inputs (minus the tx fee) will be sent there.
                Otherwise it should be a `list` of `dict` objects containing address and value.
            tx_fee: The Bitcoin network fee to be paid on this transaction.
            testnet: Should this transaction be built for testnet?
            out_value: used if you want to specify a specific output value otherwise the full value
                of the inputs (minus the tx fee) will be used.
        """
        # build the inputs from the outpoints object
        SelectParams("testnet" if testnet else "mainnet")
        txins = []
        in_value = 0
        for outpoint in outpoints:
            in_value += outpoint["value"]
            txin = CMutableTxIn(
                COutPoint(lx(outpoint["txid"]), outpoint["vout"]))
            txin.scriptSig = CScript(x(outpoint["scriptPubKey"]))
            txins.append(txin)

        # build the outputs
        txouts = []
        if isinstance(outputs, list):
            for output in outputs:
                value = output["value"]
                address = output["address"]
                txouts.append(
                    CMutableTxOut(value,
                                  CBitcoinAddress(address).to_scriptPubKey()))
        else:
            value = out_value if out_value is not None else (in_value - tx_fee)
            txouts.append(
                CMutableTxOut(value,
                              CBitcoinAddress(outputs).to_scriptPubKey()))

        # make the transaction
        tx = CMutableTransaction(txins, txouts)

        return BitcoinTransaction(tx)
Ejemplo n.º 11
0
 def find_transaction_to_address(self, p2sh):
     self.bitcoind.importaddress(p2sh, "", False)
     txs = self.bitcoind.listunspent()
     for tx in txs:
         if tx['address'] == CBitcoinAddress(p2sh):
             logging.debug("Found tx to p2sh: {0}".format(p2sh))
             return tx
Ejemplo n.º 12
0
def get_coinbase_info(blockheight):
    '''Gets coinbase tag and addresses of a block with specified height.

    Returns:
        addresses - A list of p2sh/p2pkh addresses corresponding to the
                    outputs. Returns None in place of an unrecognizable
                    scriptPubKey.
        tag - the UTF-8 decoded scriptSig.
    Raises:
        Exceptions originating from bitcoin.rpc.Proxy, if there is a problem
        with JSON-RPC.
    '''
    block = proxy.getblock(proxy.getblockhash(blockheight))
    coinbase_tx = block.vtx[0]
    assert coinbase_tx.is_coinbase()
    addresses = []
    for output in coinbase_tx.vout:
        try:
            addr = str(CBitcoinAddress.from_scriptPubKey(output.scriptPubKey))
        except (CBitcoinAddressError, ValueError):
            addr = None
        else:
            addr = addr.decode('ascii')
        addresses.append(addr)

    tag = str(coinbase_tx.vin[0].scriptSig).decode('utf-8', 'ignore')

    return addresses, tag
Ejemplo n.º 13
0
def send_ulogos(request):
    try:
        user = request.user
        address = CBitcoinAddress(request.POST['address'])
        if not str(address).startswith('1'):
            return fail(10104, '暂不支持该类型比特币地址领取ULOGOS')
        signature = request.POST['signature']
        if not verify_signature(address, signature):
            return fail(10099, '签名不正确')
    except Base58Error:
        return fail(10098, '比特币地址输入不正确')
    except Exception as e:
        logger.error(e)
        return fail()

    try:
        balance = redis_server.get(str(address))
        if not balance:
            return fail(10101, '比特币区块高度478558快照中不存在该地址')
        balance = Decimal(str(balance)) / 100000000
        if balance <= 0:
            return fail(10102, '比特币地址余额不对')
    except Exception as e:
        logger.error(e)
        return fail(10103, '比特币地址余额获取失败')

    try:
        create_ulogos_dispatch(user, str(address), signature, balance)
        return success(data={'btc': balance, 'ulogos': balance, 'bitcoinlogo': balance})
    except Exception as e:
        logger.error(e)
        return fail(10100, '您已提交过领币申请,请勿重复提交')
Ejemplo n.º 14
0
    def listunspent(self, minconf=0, maxconf=9999999, addrs=None):
        """Return unspent transaction outputs in wallet

        Outputs will have between minconf and maxconf (inclusive)
        confirmations, optionally filtered to only include txouts paid to
        addresses in addrs.
        """
        r = None
        if addrs is None:
            r = self._call('listunspent', minconf, maxconf)
        else:
            addrs = [str(addr) for addr in addrs]
            r = self._call('listunspent', minconf, maxconf, addrs)

        r2 = []
        for unspent in r:
            unspent['outpoint'] = COutPoint(lx(unspent['txid']),
                                            unspent['vout'])
            del unspent['txid']
            del unspent['vout']

            # address isn't always available as Bitcoin Core allows scripts w/o
            # an address type to be imported into the wallet, e.g. non-p2sh
            # segwit
            try:
                unspent['address'] = CBitcoinAddress(unspent['address'])
            except KeyError:
                pass
            unspent['scriptPubKey'] = CScript(
                unhexlify(unspent['scriptPubKey']))
            unspent['amount'] = int(unspent['amount'] * COIN)
            r2.append(unspent)
        return r2
Ejemplo n.º 15
0
 def validateaddress(self, address):
     """Return information about an address"""
     r = self._call('validateaddress', str(address))
     r['address'] = CBitcoinAddress(r['address'])
     if 'pubkey' in r:
         r['pubkey'] = unhexlify(r['pubkey'])
     return r
Ejemplo n.º 16
0
def spend_p2sh_mediator(redeemScript, txins_str, amounts, daddrs, sig, rein):
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txins_obj = []
    for txin_str in txins_str.split():
        txin_list = txin_str.split("-")
        txins_obj.append(
            CMutableTxIn(COutPoint(lx(txin_list[0]), int(txin_list[1]))))
    txouts = []
    len_amounts = len(amounts)
    for i in range(0, len_amounts):
        txouts.append(
            CMutableTxOut(
                round(amounts[i], 8) * COIN,
                CBitcoinAddress(daddrs[i]).to_scriptPubKey()))
    tx = CMutableTransaction(txins_obj, txouts)
    seckey = CBitcoinSecret(rein.user.dkey)
    ntxins = len(txins_obj)
    sig_list = []
    for s in sig.split():
        sig_list.append(x(s))
    sig2_str = ""
    for i in range(0, ntxins):
        sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
        sig2 = seckey.sign(sighash) + x("01")
        sig2_str += " " + b2x(sig2)
        txins_obj[i].scriptSig = CScript(
            [OP_0, sig2, sig_list[i], txin_redeemScript])
        VerifyScript(txins_obj[i].scriptSig, txin_scriptPubKey, tx, i,
                     (SCRIPT_VERIFY_P2SH, ))
    tx_bytes = tx.serialize()
    hash = sha256(sha256(tx_bytes).digest()).digest()
    txid = b2x(hash[::-1])
    txid_causeway = broadcast_tx(b2x(tx_bytes), rein)
    return (txid, sig2_str[1:])
    def build_bounce_tx(self, txid_hex):
        #Generate p2sh script pub key.
        redeem_script = self.fund_redeem_script(self.my)
        redeem_script_hash160 = self.hash160_script(redeem_script)
        txin_script_pub_key = CScript(
            [OP_HASH160, redeem_script_hash160["bin"], OP_EQUAL])

        #Generate address to receive bounce.
        if "bounce" not in self.key_pairs:
            self.key_pairs["bounce"] = self.key_pair_from_address(
                self.jsonrpc[self.my].getnewaddress(), self.my)

        #Setup tx inputs and outputs.
        txid = lx(txid_hex)
        vout = 0
        txin = CTxIn(COutPoint(txid, vout), CScript(), 0)  #Sequence number 0.
        txout = CTxOut(
            (self.send_amount -
             decimal.Decimal(coinbend.config["mining_fee"]["standard"])) *
            COIN,
            CBitcoinAddress(
                self.key_pairs["bounce"]["addr"]["base58"]).to_scriptPubKey())

        #Locktime is unsigned int 4, unix timestamp in little endian format.
        #(Conversion to little endian is handled by the library already.)
        nlock_time = datetime.datetime.now() + datetime.timedelta(
            seconds=self.future_minutes * 60)
        nlock_time = int(nlock_time.strftime("%s"))

        #Create unsigned transaction.
        tx = CTransaction([txin], [txout], nlock_time)
        return b2x(tx.serialize())
Ejemplo n.º 18
0
def test_vault_txout(bitcoind):
    """Test that vault_txout() produces a valid output."""
    amount = Decimal("50") - Decimal("500") / Decimal(COIN)
    addresses = [bitcoind.rpc.getnewaddress() for i in range(4)]
    pubkeys = [bytes.fromhex(bitcoind.rpc.getaddressinfo(addr)["pubkey"])
               for addr in addresses]
    privkeys = [bitcoind.rpc.dumpprivkey(addr) for addr in addresses]
    txo = vault_txout(pubkeys, COIN * amount)
    addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    # This makes a transaction with only one vout
    txid = bitcoind.pay_to(addr, amount)
    new_amount = amount - Decimal("500") / Decimal(COIN)
    addr = bitcoind.getnewaddress()
    tx = bitcoind.rpc.createrawtransaction([{"txid": txid, "vout": 0}],
                                           [{addr: float(new_amount)}])
    tx = bitcoind.rpc.signrawtransactionwithkey(tx, privkeys, [
        {
            "txid": txid,
            "vout": 0,  # no change output
            "scriptPubKey": b2x(txo.scriptPubKey),
            "witnessScript": b2x(vault_script(pubkeys)),
            "amount": str(amount)
         }
    ])
    bitcoind.send_tx(tx["hex"])
    assert bitcoind.has_utxo(addr)
Ejemplo n.º 19
0
def get_coinbase_info(blockheight):
    '''Gets coinbase tag and addresses of a block with specified height.

    Returns:
        addresses - A list of p2sh/p2pkh addresses corresponding to the
                    outputs. Returns None in place of an unrecognizable
                    scriptPubKey.
        tag - the UTF-8 decoded scriptSig.
    Raises:
        Exceptions originating from bitcoin.rpc.Proxy, if there is a problem
        with JSON-RPC.
    '''
    block = proxy.getblock(proxy.getblockhash(blockheight))
    coinbase_tx = block.vtx[0]
    assert coinbase_tx.is_coinbase()
    addresses = []
    for output in coinbase_tx.vout:
        try:
            addr = str(CBitcoinAddress.from_scriptPubKey(output.scriptPubKey))
        except (CBitcoinAddressError, ValueError):
            addr = None
        else:
            addr = addr.decode('ascii')
        addresses.append(addr)

    tag = str(coinbase_tx.vin[0].scriptSig).decode('utf-8', 'ignore')

    return addresses, tag
Ejemplo n.º 20
0
 def find_transaction_to_address(self, p2sh):
     self.bitcoind.importaddress(p2sh, "", False)
     txs = self.bitcoind.listunspent()
     for tx in txs:
         if tx['address'] == CBitcoinAddress(p2sh):
             print("Found tx to p2sh", p2sh)
             return tx
Ejemplo n.º 21
0
    def getrawchangeaddress(self):
        """Returns a new Bitcoin address, for receiving change.

        This is for use with raw transactions, NOT normal use.
        """
        r = self._call('getrawchangeaddress')
        return CBitcoinAddress(r)
Ejemplo n.º 22
0
    def _validate_output(self, output: Dict) -> None:
        if 'address' not in output:
            raise InvalidSignatureRequest("no address in output")
        if not isinstance(output['address'], (str, )):
            err_msg = "output addresses must be base58-encoded strings"
            raise InvalidSignatureRequest(err_msg)

        if output['address'][:2] in ('bc', 'tb'):
            err_msg = "bech32 addresses are unsupported (output)"
            raise InvalidSignatureRequest(err_msg)
        try:
            base58.CBase58Data(output['address'])
        except base58.InvalidBase58Error:
            err_msg = "output addresses must be base58-encoded strings"
            raise InvalidSignatureRequest(err_msg)
        except base58.Base58ChecksumError:
            err_msg = "invalid output address checksum"
            raise InvalidSignatureRequest(err_msg)
        try:
            CBitcoinAddress(output['address'])
        except CBitcoinAddressError:
            err_msg = "invalid output address (check mainnet vs. testnet)"
            raise InvalidSignatureRequest(err_msg)

        if 'amount' not in output:
            raise InvalidSignatureRequest("no amount in output")
        if type(output['amount']) != int:
            err_msg = "output amount must be an integer (satoshis)"
            raise InvalidSignatureRequest(err_msg)
        if output['amount'] <= 0:
            raise InvalidSignatureRequest("invalid output amount")
Ejemplo n.º 23
0
def creates_add_input(bitcoind, tx):
    """Creates and add an input to a CMutableTransaction, SIGHASH_ALL.

    :returns: The txid of the first stage fee bumping tx (for convenience)
    """
    # First we get some coins
    privkey = CKey(os.urandom(32))
    scriptPubKey = CScript([OP_0, Hash160(privkey.pub)])
    address = CBitcoinAddress.from_scriptPubKey(scriptPubKey)
    # Let's say we want to increase the fees by 5000 sats
    amount = 5000

    # Bitcoind is nice and will create the first stage transaction
    first_txid = bitcoind.rpc.sendtoaddress(str(address), amount / COIN)
    vout_index = get_output_index(
        bitcoind.rpc.getrawtransaction(first_txid, 1), amount)
    # === We don't generate a block yet ! ===

    tx.vin.append(
        CTxIn(COutPoint(lx(first_txid), vout_index), nSequence=0xfffffffe))
    # Sign the new input with ALL
    tx_hash = SignatureHash(address.to_redeemScript(), tx, 1, SIGHASH_ALL,
                            amount, SIGVERSION_WITNESS_V0)
    sig = privkey.sign(tx_hash) + bytes([SIGHASH_ALL])
    tx.wit.vtxinwit.append(CTxInWitness(CScriptWitness([sig, privkey.pub])))

    return first_txid
Ejemplo n.º 24
0
    def listunspent(self, minconf=0, maxconf=9999999, addrs=None):
        """Return unspent transaction outputs in wallet

        Outputs will have between minconf and maxconf (inclusive)
        confirmations, optionally filtered to only include txouts paid to
        addresses in addrs.
        """
        r = None
        if addrs is None:
            r = self._call('listunspent', minconf, maxconf)
        else:
            addrs = [str(addr) for addr in addrs]
            r = self._call('listunspent', minconf, maxconf, addrs)

        r2 = []
        for unspent in r:
            unspent['outpoint'] = COutPoint(lx(unspent['txid']), unspent['vout'])
            del unspent['txid']
            del unspent['vout']

            unspent['address'] = CBitcoinAddress(unspent['address'])
            unspent['scriptPubKey'] = CScript(unhexlify(unspent['scriptPubKey']))
            unspent['amount'] = int(unspent['amount'] * COIN)
            r2.append(unspent)
        return r2
Ejemplo n.º 25
0
    def is_valid_address(cls, address: str) -> bool:
        try:
            CBitcoinAddress(address)
        except (CBitcoinAddressError, Base58ChecksumError, InvalidBase58Error):
            return False

        return True
Ejemplo n.º 26
0
def spend_command(args):
    args.addr = CBitcoinAddress(args.addr)

    redeemScript = hodl_redeemScript(args.privkey, args.nLockTime)
    scriptPubKey = redeemScript.to_p2sh_scriptPubKey()

    proxy = bitcoin.rpc.Proxy()

    prevouts = []
    for prevout in args.prevouts:
        try:
            txid, n = prevout.split(':')

            txid = lx(txid)
            n = int(n)

            outpoint = COutPoint(txid, n)
        except ValueError:
            args.parser.error('Invalid output: %s' % prevout)

        try:
            prevout = proxy.gettxout(outpoint)
        except IndexError:
            args.parser.error('Outpoint %s not found' % outpoint)

        prevout = prevout['txout']
        if prevout.scriptPubKey != scriptPubKey:
            args.parser.error('Outpoint not correct scriptPubKey')

        prevouts.append((outpoint, prevout))

    sum_in = sum(prev_txout.nValue for outpoint, prev_txout in prevouts)

    tx_size = (
        4 +  # version field
        2 +  # # of txins
        len(prevouts) * 153 +  # txins, including sigs
        1 +  # # of txouts
        34 +  # txout
        4  # nLockTime field
    )

    feerate = int(proxy._call('estimatefee', 1) * COIN)  # satoshi's per KB
    if feerate <= 0:
        feerate = 10000
    fees = int(tx_size / 1000 * feerate)

    unsigned_tx = CTransaction(
        [CTxIn(outpoint, nSequence=0) for outpoint, prevout in prevouts],
        [CTxOut(sum_in - fees, args.addr.to_scriptPubKey())], args.nLockTime)

    signed_tx = CTransaction([
        CTxIn(txin.prevout,
              spend_hodl_redeemScript(args.privkey, args.nLockTime,
                                      unsigned_tx, i),
              nSequence=0) for i, txin in enumerate(unsigned_tx.vin)
    ], unsigned_tx.vout, unsigned_tx.nLockTime)

    print(b2x(signed_tx.serialize()))
Ejemplo n.º 27
0
def collect_transactions():
    blockchain = Blockchain()

    count = blockchain.get_block_count()
    start = Info.objects.get(id=1)
    logger.info('Blockchain count: %d' % count)
    logger.info('Fetching blocks from %d' % (start.height + 1))

    for height in range(start.height + 1, count + 1):
        block = blockchain.get_block_by_height(height)
        for tx in block.vtx:
            txid = b2lx(tx.GetTxid())
            txsrlzr = BaseTransactionSerializer(data={
                'id': txid,
                'vin': [],
                'vout': []
            })
            if txsrlzr.is_valid():
                newtx = txsrlzr.save()
            else:
                newtx = Transaction.objects.get(id=txid)

            for v in tx.vin:
                newtx.vin = []
                if not v.prevout.is_null():
                    t = Transaction.objects.get(id=b2lx(v.prevout.hash))
                    coin_id = t.vout[v.prevout.n]
                    newtx.vin.append(coin_id)
                    coin = Coin.objects.get(id=coin_id)
                    coin.spendable = False
                    coin.frozen = False
                    coin.save()

            for i, v in enumerate(tx.vout):
                newtx.vout = []
                if v.nValue > 0:
                    data = {
                        'txid': txid,
                        'vout': i,
                        'owner': str(CBitcoinAddress.from_scriptPubKey(v.scriptPubKey)),
                        'value': v.nValue,
                        'height': height,
                        'spendable': True,
                        'frozen': False,
                    }
                    serializer = BaseCoinSerializer(data=data)
                    if serializer.is_valid():
                        coin = serializer.save()
                    else:
                        coin = Coin.objects.get(txid=data['txid'], vout=i)
                    newtx.vout.append(coin.id)
                # else:
                #     print(blockchain.get_data_from_vout(v))
            newtx.save()

    start.height = count
    start.save()

    logger.info('Successfully loaded all transactions.')
Ejemplo n.º 28
0
def create_transaction_output(output_):
    """
	transform the transaction output into hex code
	:param output__: unsigned transaction output
	:return: output formatted as transaction hex code
	"""
    return CMutableTxOut(output_['value'],
                         CBitcoinAddress(output_['address']).to_scriptPubKey())
Ejemplo n.º 29
0
    def addr_from_script(script):
        """Generate output addres from scriptPubKey"""
        try:
            addr = str(CBitcoinAddress.from_scriptPubKey(script))
        except CBitcoinAddressError:
            addr = None

        return addr
Ejemplo n.º 30
0
 def validateaddress(self, address):
     """Return information about an address"""
     r = self._call('validateaddress', str(address))
     if r['isvalid']:
         r['address'] = CBitcoinAddress(r['address'])
     if 'scriptPubKey' in r:
         r['scriptPubKey'] = unhexlify(r['scriptPubKey'])
     return r
Ejemplo n.º 31
0
    def do(self, args):
        genesis_outpoints = {}
        genesis_scriptPubKeys = set()

        for str_outpoint, str_qty in args.genesis_outpoints:
            outpoint = ParseCOutPointArg.str_to_COutPoint(
                str_outpoint, args.parser)
            qty = int(str_qty)

            if outpoint in genesis_outpoints:
                args.parser.exit('dup outpoint %r' % outpoint)

            logging.debug('Genesis outpoint: %s:%d %d' %
                          (b2lx(outpoint.hash), outpoint.n, qty))
            genesis_outpoints[outpoint] = qty

        for str_addr in args.genesis_addrs:
            addr = CBitcoinAddress(str_addr)

            scriptPubKey = addr.to_scriptPubKey()
            if scriptPubKey in genesis_scriptPubKeys:
                args.parser.exit('dup addr %s' % str_addr)

            logging.debug('Genesis scriptPubKey: %s (%s)' %
                          (b2x(scriptPubKey), str(addr)))
            genesis_scriptPubKeys.add(scriptPubKey)

        for hex_scriptPubKey in args.genesis_scriptPubKeys:
            scriptPubKey = CScript(x(hex_scriptPubKey))

            if scriptPubKey in genesis_scriptPubKeys:
                args.parser.exit('dup addr %s' % hex_scriptPubKey)

            logging.debug('Genesis scriptPubKey: %s' % b2x(scriptPubKey))
            genesis_scriptPubKeys.add(scriptPubKey)

        stegkey = os.urandom(ColorDef.STEGKEY_LEN)
        if args.stegkey is not None:
            stegkey = x(args.stegkey)

        colordef = ColorDef(genesis_outpoints=genesis_outpoints,
                            genesis_scriptPubKeys=genesis_scriptPubKeys,
                            birthdate_blockheight=args.birthdate_blockheight,
                            stegkey=stegkey)

        ColorDefFileSerializer.stream_serialize(colordef, args.fd)
Ejemplo n.º 32
0
def send_vault_tx(bitcoind, pubkeys, amount):
    """Creates a vault transaction for {amount} *sats*"""
    txo = vault_txout(pubkeys, amount)
    addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    # This makes a transaction with only one vout
    amount_for_bitcoind = Decimal(amount) / Decimal(COIN)
    txid = bitcoind.pay_to(addr, amount_for_bitcoind)
    return txid
Ejemplo n.º 33
0
    def do(self, args):
        genesis_outpoints = {}
        genesis_scriptPubKeys = set()

        for str_outpoint, str_qty in args.genesis_outpoints:
            outpoint = ParseCOutPointArg.str_to_COutPoint(str_outpoint, args.parser)
            qty = int(str_qty)

            if outpoint in genesis_outpoints:
                args.parser.exit('dup outpoint %r' % outpoint)

            logging.debug('Genesis outpoint: %s:%d %d' % (b2lx(outpoint.hash), outpoint.n, qty))
            genesis_outpoints[outpoint] = qty

        for str_addr in args.genesis_addrs:
            addr = CBitcoinAddress(str_addr)

            scriptPubKey = addr.to_scriptPubKey()
            if scriptPubKey in genesis_scriptPubKeys:
                args.parser.exit('dup addr %s' % str_addr)

            logging.debug('Genesis scriptPubKey: %s (%s)' % (b2x(scriptPubKey), str(addr)))
            genesis_scriptPubKeys.add(scriptPubKey)

        for hex_scriptPubKey in args.genesis_scriptPubKeys:
            scriptPubKey = CScript(x(hex_scriptPubKey))

            if scriptPubKey in genesis_scriptPubKeys:
                args.parser.exit('dup addr %s' % hex_scriptPubKey)

            logging.debug('Genesis scriptPubKey: %s' % b2x(scriptPubKey))
            genesis_scriptPubKeys.add(scriptPubKey)

        stegkey = os.urandom(ColorDef.STEGKEY_LEN)
        if args.stegkey is not None:
            stegkey = x(args.stegkey)

        colordef = ColorDef(genesis_outpoints=genesis_outpoints,
                            genesis_scriptPubKeys=genesis_scriptPubKeys,
                            birthdate_blockheight=args.birthdate_blockheight,
                            stegkey=stegkey)

        ColorDefFileSerializer.stream_serialize(colordef, args.fd)
Ejemplo n.º 34
0
def _check_output_address(mytx):
    print
    for vout in mytx.vout:
        pubkey = vout.scriptPubKey
        address = b2lx(CBitcoinAddress.from_scriptPubKey(pubkey))
        address = "".join(map(str.__add__, address[-2::-2], address[-1::-2]))
        #print address
        address = int(address, 16)
        for bl in blacklist:
            if hex(bl.start) <= hex(address) <= hex(bl.end):
                print "This address use by: " + bl.name
                return False
    return True
Ejemplo n.º 35
0
class SpendScripts(object):
    def __init__(self, payto_addr):
        self.payto = CBitcoinAddress(payto_addr)
        self.proxy = bitcoin.rpc.Proxy()
        self.prevouts = []

    def add_prevout(self, txid, vout, redeemer):
        outpoint = COutPoint(lx(txid), vout)
        try:
            prevout = self.proxy.gettxout(outpoint)
        except IndexError:
            raise Exception("Outpoint %s not found" % (outpoint,))
        prevtx = prevout['txout']
        if prevtx.scriptPubKey != redeemer.p2sh_scriptPubKey:
            raise Exception("Outpoint %s has incorrect scriptPubKey (%s; expected %s)" % (outpoint, b2x(prevtx.scriptPubKey), b2x(redeemer.p2sh_scriptPubKey)))
        self.prevouts.append((outpoint, prevtx, redeemer))

    def as_tx(self):
        sum_in = sum(prevtx.nValue for _,prevtx,_ in self.prevouts)
        sig_size = sum(redeemer.spendbytes for _,_,redeemer in self.prevouts)
        tx_size = (4                        + # version field
                   2                        + # # of txins
                   len(self.prevouts) * 41  + # txins, excluding sigs
                   sig_size                 + # txins, sigs only
                   1                        + # # of txouts
                   34                       + # txout
                   4                          # nLockTime field
                   )
        feerate = int(self.proxy._call('estimatefee', 1) * COIN) 
        # satoshi's per KB
        if feerate <= 0:
            feerate = 10000
        fees = int(tx_size * feerate / 1000)

        tx = CMutableTransaction(
                [CTxIn(outpoint, nSequence=0)
                    for outpoint,_,_ in self.prevouts],
                [CTxOut(sum_in - fees, self.payto.to_scriptPubKey())],
                0)

        for n,(_,_,redeemer) in enumerate(self.prevouts):
            redeemer.mutate_spend(tx, n)

        unsigned_tx = CTransaction.from_tx(tx)

        for n,(_,_,redeemer) in enumerate(self.prevouts):
            txin = CMutableTxIn.from_txin(tx.vin[n])
            txin.scriptSig = redeemer.sign_spend(unsigned_tx, n)
            tx.vin[n] = CTxIn.from_txin(txin)

        print(b2x(tx.serialize()))
Ejemplo n.º 36
0
def recover_command(args):
    args.fee_per_kb = int(args.fee_per_kb * COIN)
    addr = CBitcoinAddress(args.addr)

    tx = CTransaction()

    sum_value_in = 0
    dummy_scriptSig = CScript([b'\x00'*74])
    inputs = {}
    for outpoint, txout in tuple(args.wallet.unspent_txouts.items())[0:500]:
        sum_value_in += txout.nValue
        tx.vin.append(CTxIn(outpoint, dummy_scriptSig))
        inputs[outpoint] = txout

    tx.vout.append(CTxOut(-1, addr.to_scriptPubKey()))

    fees = int((len(tx.serialize())/1000) * args.fee_per_kb)

    tx.vout[0].nValue = sum_value_in - fees

    # Sign the transaction
    for (i, txin) in enumerate(tx.vin):
        prevout_scriptPubKey = inputs[txin.prevout].scriptPubKey
        sighash = SignatureHash(prevout_scriptPubKey, tx, i, SIGHASH_ALL)
        seckey = args.wallet.keypairs[prevout_scriptPubKey]
        sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

        if prevout_scriptPubKey[-1] == OP_CHECKMULTISIG:
            txin.scriptSig = CScript([OP_0, sig])

        elif prevout_scriptPubKey[-1] == OP_CHECKSIG and prevout_scriptPubKey[-2] == OP_EQUALVERIFY:
            txin.scriptSig = CScript([sig, seckey.pub])

        VerifyScript(txin.scriptSig, prevout_scriptPubKey, tx, i)

    print(b2x(tx.serialize()))
def payment_ack(serialized_Payment_message):
    """Generates a PaymentACK object, captures client refund address and returns a message"""

    pao = o.PaymentACK()
    pao.payment.ParseFromString(serialized_Payment_message)
    pao.memo = "String shown to user after payment confirmation"

    refund_address = CBitcoinAddress.from_scriptPubKey(CScript(pao.payment.refund_to[0].script))

    sds_pa = pao.SerializeToString()

    open("sds_pa_blob", "wb").write(sds_pa)
    headers = {"Content-Type": "application/bitcoin-payment", "Accept": "application/bitcoin-paymentack"}
    http_response_object = urllib2.Request("file:sds_pa_blob", None, headers)

    return http_response_object
Ejemplo n.º 38
0
 def get(cls, address):
     """Get a Channel with the specified address."""
     row = g.dat.execute(
         "SELECT * from CHANNELS WHERE address = ?", (address,)).fetchone()
     if row is None:
         raise Exception("Unknown address", address)
     address, commitment = row
     commitment = CMutableTransaction.deserialize(commitment)
     commitment = CMutableTransaction.from_tx(commitment)
     assert len(commitment.vin) == 1
     assert len(commitment.vout) == 2
     commitment.vin[0].scriptSig = AnchorScriptSig.from_script(
         commitment.vin[0].scriptSig)
     for tx_out in commitment.vout:
         tx_out.scriptPubKey = CBitcoinAddress.from_scriptPubKey(tx_out.scriptPubKey)
     return cls(address,
                commitment.vin[0],
                commitment.vout[0],
                commitment.vout[1])
Ejemplo n.º 39
0
    def check_for_funding(self, address):
        """
        Check to see if any of the outputs pay the given address

        Args:
            address: base58check encoded bitcoin address

        Returns: a `list` of `dict` outpoints if any of the outputs match
            the address else None.
        """

        outpoints = []
        for i in range(len(self.tx.vout)):
            addr = CBitcoinAddress.from_scriptPubKey(self.tx.vout[i].scriptPubKey)
            if str(addr) == address:
                o = {
                    "txid": b2lx(self.tx.GetHash()),
                    "vout": i,
                    "value": self.tx.vout[i].nValue,
                    "scriptPubKey": self.tx.vout[i].scriptPubKey.encode("hex")
                }
                outpoints.append(o)
        return outpoints if len(outpoints) > 0 else None
Ejemplo n.º 40
0
def create_transaction_output(address, transaction_fee):
    """Create a transaction output"""
    addr = CBitcoinAddress(address)
    tx_out = CMutableTxOut(transaction_fee, addr.to_scriptPubKey())
    return tx_out
Ejemplo n.º 41
0
    def dataReceived(self, data):
        self.buffer += data
        header = MsgHeader.from_bytes(self.buffer)
        if len(self.buffer) < header.msglen + 24:
            return
        try:
            stream = BytesIO(self.buffer)
            m = MsgSerializable.stream_deserialize(stream)
            self.buffer = stream.read()

            if m.command == "verack":
                self.timeouts["verack"].cancel()
                del self.timeouts["verack"]
                if "version" not in self.timeouts:
                    self.on_handshake_complete()

            elif m.command == "version":
                self.version = m
                if m.nVersion < 70001 or m.nServices != 1:
                    self.transport.loseConnection()
                self.timeouts["version"].cancel()
                del self.timeouts["version"]
                msg_verack().stream_serialize(self.transport)
                if self.blockchain is not None:
                    self.to_download = self.version.nStartingHeight - self.blockchain.get_height()
                if "verack" not in self.timeouts:
                    self.on_handshake_complete()

            elif m.command == "getdata":
                for item in m.inv:
                    if item.hash in self.inventory and item.type == 1:
                        transaction = msg_tx()
                        transaction.tx = self.inventory[item.hash]
                        transaction.stream_serialize(self.transport)

            elif m.command == "inv":
                for item in m.inv:
                    # This is either an announcement of tx we broadcast ourselves or a tx we have already downloaded.
                    # In either case we only need to callback here.
                    if item.type == 1 and item.hash in self.subscriptions:
                        self.subscriptions[item.hash]["callback"](item.hash)

                    # This is the first time we are seeing this txid. Let's download it and check to see if it sends
                    # coins to any addresses in our subscriptions.
                    elif item.type == 1 and item.hash not in self.inventory:
                        self.timeouts[item.hash] = reactor.callLater(5, self.response_timeout, item.hash)

                        cinv = CInv()
                        cinv.type = 1
                        cinv.hash = item.hash

                        getdata_packet = msg_getdata()
                        getdata_packet.inv.append(cinv)

                        getdata_packet.stream_serialize(self.transport)

                    # The peer announced a new block. Unlike txs, we should download it, even if we've previously
                    # downloaded it from another peer, to make sure it doesn't contain any txs we didn't know about.
                    elif item.type == 2 or item.type == 3:
                        if self.state == State.DOWNLOADING:
                            self.download_tracker[0] += 1
                        cinv = CInv()
                        cinv.type = 3
                        cinv.hash = item.hash

                        getdata_packet = msg_getdata()
                        getdata_packet.inv.append(cinv)

                        getdata_packet.stream_serialize(self.transport)

                    if self.state != State.DOWNLOADING:
                        self.log.debug("Peer %s:%s announced new %s %s" % (self.transport.getPeer().host, self.transport.getPeer().port, CInv.typemap[item.type], b2lx(item.hash)))

            elif m.command == "tx":
                if m.tx.GetHash() in self.timeouts:
                    self.timeouts[m.tx.GetHash()].cancel()
                for out in m.tx.vout:
                    try:
                        addr = str(CBitcoinAddress.from_scriptPubKey(out.scriptPubKey))
                    except Exception:
                        addr = None

                    if addr in self.subscriptions:
                        if m.tx.GetHash() not in self.subscriptions:
                            # It's possible the first time we are hearing about this tx is following block
                            # inclusion. If this is the case, let's make sure we include the correct number
                            # of confirmations.
                            in_blocks = self.inventory[m.tx.GetHash()] if m.tx.GetHash() in self.inventory else []
                            confirms = []
                            if len(in_blocks) > 0:
                                for block in in_blocks:
                                    confirms.append(self.blockchain.get_confirmations(block))
                            self.subscriptions[m.tx.GetHash()] = {
                                "announced": 0,
                                "ann_threshold": self.subscriptions[addr][0],
                                "confirmations": max(confirms) if len(confirms) > 0 else 0,
                                "last_confirmation": 0,
                                "callback": self.subscriptions[addr][1],
                                "in_blocks": in_blocks,
                                "tx": m.tx
                            }
                            self.subscriptions[addr][1](m.tx.GetHash())
                        if m.tx.GetHash() in self.inventory:
                            del self.inventory[m.tx.GetHash()]

            elif m.command == "merkleblock":
                if self.blockchain is not None:
                    self.blockchain.process_block(m.block)
                    if self.state != State.DOWNLOADING:
                        self.blockchain.save()
                    # check for block inclusion of subscribed txs
                    for match in m.block.get_matched_txs():
                        if match in self.subscriptions:
                            self.subscriptions[match]["in_blocks"].append(m.block.GetHash())
                        else:
                            # stick the hash here in case this is the first we are hearing about this tx.
                            # when the tx comes over the wire after this block, we will append this hash.
                            self.inventory[match] = [m.block.GetHash()]
                    # run through subscriptions and callback with updated confirmations
                    for txid in self.subscriptions:
                        try:
                            confirms = []
                            for block in self.subscriptions[txid]["in_blocks"]:
                                confirms.append(self.blockchain.get_confirmations(block))
                            self.subscriptions[txid]["confirmations"] = max(confirms)
                            self.subscriptions[txid]["callback"](txid)
                        except Exception:
                            pass

                    # If we are in the middle of an initial chain download, let's check to see if we have
                    # either reached the end of the download or if we need to loop back around and make
                    # another get_blocks call.
                    if self.state == State.DOWNLOADING:
                        self.download_count += 1
                        percent = int((self.download_count / float(self.to_download))*100)
                        if self.download_listener is not None:
                            self.download_listener.progress(percent, self.download_count)
                            self.download_listener.on_block_downloaded((self.transport.getPeer().host, self.transport.getPeer().port), header, self.to_download - self.download_count + 1)
                        if percent == 100:
                            if self.download_listener is not None:
                                self.download_listener.download_complete()
                            self.log.info("Chain download 100% complete")
                        self.download_tracker[1] += 1
                        # We've downloaded every block in the inv packet and still have more to go.
                        if (self.download_tracker[0] == self.download_tracker[1] and
                           self.blockchain.get_height() < self.version.nStartingHeight):
                            if self.timeouts["download"].active():
                                self.timeouts["download"].cancel()
                            self.download_blocks(self.callbacks["download"])
                        # We've downloaded everything so let's callback to the client.
                        elif self.blockchain.get_height() >= self.version.nStartingHeight:
                            self.blockchain.save()
                            self.state = State.CONNECTED
                            self.callbacks["download"]()
                            if self.timeouts["download"].active():
                                self.timeouts["download"].cancel()

            elif m.command == "headers":
                if self.timeouts["download"].active():
                    self.timeouts["download"].cancel()
                for header in m.headers:
                    # If this node sent a block with no parent then disconnect from it and callback
                    # on client.check_for_more_blocks.
                    if self.blockchain.process_block(header) is None:
                        self.blockchain.save()
                        self.callbacks["download"]()
                        self.transport.loseConnection()
                        return
                    self.download_count += 1
                    percent = int((self.download_count / float(self.to_download))*100)
                    if self.download_listener is not None:
                        self.download_listener.progress(percent, self.download_count)
                        self.download_listener.on_block_downloaded((self.transport.getPeer().host, self.transport.getPeer().port), header, self.to_download - self.download_count + 1)
                    if percent == 100:
                        if self.download_listener is not None:
                            self.download_listener.download_complete()
                        self.log.info("Chain download 100% complete")
                # The headers message only comes in batches of 500 blocks. If we still have more blocks to download
                # loop back around and call get_headers again.
                if self.blockchain.get_height() < self.version.nStartingHeight:
                    self.download_blocks(self.callbacks["download"])
                else:
                    self.blockchain.save()
                    self.callbacks["download"]()
                    self.state = State.CONNECTED

            elif m.command == "ping":
                msg_pong(nonce=m.nonce).stream_serialize(self.transport)

            else:
                self.log.debug("Received message %s from %s:%s" % (m.command, self.transport.getPeer().host, self.transport.getPeer().port))

            if len(self.buffer) >= 24: self.dataReceived("")
        except Exception:
            traceback.print_exc()
Ejemplo n.º 42
0
    def dataReceived(self, data):
        self.buffer += data
        # if self.buffer.length >= sizeof(message header)
        #   messageHeader := MessageHeader.deserialize(self.buffer)
        #   if messageHeader.payloadLength > someBigNumber
        #     throw DropConnection
        #   if self.buffer.length < messageHeader.payloadLength
        #     return
        try:
            m = MsgSerializable.from_bytes(self.buffer)
            self.buffer = ""
            if m.command == "verack":
                self.timeouts["verack"].cancel()
                del self.timeouts["verack"]
                if "version" not in self.timeouts:
                    self.on_handshake_complete()

            elif m.command == "version":
                self.version = m
                if m.nVersion < 70001:
                    self.transport.loseConnection()
                self.timeouts["version"].cancel()
                del self.timeouts["version"]
                msg_verack().stream_serialize(self.transport)
                if "verack" not in self.timeouts:
                    self.on_handshake_complete()

            elif m.command == "getdata":
                for item in m.inv:
                    if item.hash in self.inventory and item.type == 1:
                        transaction = msg_tx()
                        transaction.tx = self.inventory[item.hash]
                        transaction.stream_serialize(self.transport)

            elif m.command == "inv":
                for item in m.inv:
                    # callback tx
                    if item.type == 1 and item.hash in self.subscriptions:
                        self.subscriptions[item.hash]["callback"](item.hash)

                    # download tx and check subscription
                    elif item.type == 1 and item.hash not in self.inventory:
                        self.timeouts[item.hash] = reactor.callLater(5, self.response_timeout, item.hash)

                        cinv = CInv()
                        cinv.type = 1
                        cinv.hash = item.hash

                        getdata_packet = msg_getdata()
                        getdata_packet.inv.append(cinv)

                        getdata_packet.stream_serialize(self.transport)

                    # download block
                    elif item.type == 2 or item.type == 3:
                        cinv = CInv()
                        cinv.type = 3
                        cinv.hash = item.hash

                        getdata_packet = msg_getdata()
                        getdata_packet.inv.append(cinv)

                        getdata_packet.stream_serialize(self.transport)

                    print "Peer %s:%s announced new %s %s" % (self.transport.getPeer().host, self.transport.getPeer().port, CInv.typemap[item.type], b2lx(item.hash))

            elif m.command == "tx":
                if m.tx.GetHash() in self.timeouts:
                    self.timeouts[m.tx.GetHash()].cancel()
                for out in m.tx.vout:
                    addr = str(CBitcoinAddress.from_scriptPubKey(out.scriptPubKey))
                    if addr in self.subscriptions:
                        if m.tx.GetHash() not in self.subscriptions:
                            self.subscriptions[m.tx.GetHash()] = {
                                "announced": 0,
                                "ann_threshold": self.subscriptions[addr][0],
                                "confirmations": 0,
                                "callback": self.subscriptions[addr][1],
                                "in_blocks": self.inventory[m.tx.GetHash()] if m.tx.GetHash() in self.inventory else [],
                                "tx": m.tx
                            }
                            self.subscriptions[addr][1](m.tx.GetHash())
                        if m.tx.GetHash() in self.inventory:
                            del self.inventory[m.tx.GetHash()]

            elif m.command == "merkleblock":
                self.blockchain.process_block(m.block)
                if self.blockchain is not None:
                    # check for block inclusion of subscribed txs
                    for match in m.block.get_matched_txs():
                        if match in self.subscriptions:
                            self.subscriptions[match]["in_blocks"].append(m.block.GetHash())
                        else:
                            # stick the hash here in case this is a tx we missed on broadcast.
                            # when the tx comes over the wire after this block, we will append this hash.
                            self.inventory[match] = [m.block.GetHash()]
                    # run through subscriptions and callback with updated confirmations
                    for txid in self.subscriptions:
                        if len(txid) == 32:
                            confirms = []
                            for block in self.subscriptions[txid]["in_blocks"]:
                                confirms.append(self.blockchain.get_confirmations(block))
                            self.subscriptions[txid]["confirmations"] = max(confirms)
                            self.subscriptions[txid]["callback"](txid)

            elif m.command == "headers":
                self.timeouts["download"].cancel()
                to_download = self.version.nStartingHeight - self.blockchain.get_height()
                i = 1
                for header in m.headers:
                    self.blockchain.process_block(header)
                    if i % 50 == 0 or int((i / float(to_download))*100) == 100:
                        print "Chain download %s%% complete" % int((i / float(to_download))*100)
                    i += 1
                if self.blockchain.get_height() < self.version.nStartingHeight:
                    self.download_blocks(self.callbacks["download"])
                elif self.callbacks["download"]:
                    self.callbacks["download"]()

            else:
                print "Received message %s from %s:%s" % (m.command, self.transport.getPeer().host, self.transport.getPeer().port)
        except Exception:
            pass
Ejemplo n.º 43
0
def getnewaddress_command(args):
    fund_addr = CBitcoinAddress.from_scriptPubKey(args.wallet.make_paytopubkeyhash())
    args.wallet.save()
    print('Pay to %s to fund your wallet' % fund_addr)
Ejemplo n.º 44
0
 def __init__(self, payto_addr):
     self.payto = CBitcoinAddress(payto_addr)
     self.proxy = bitcoin.rpc.Proxy()
     self.prevouts = []
Ejemplo n.º 45
0
def build_mandatory_multisig(mandatory_pubkey, other_pubkeys):
    txin_redeemScript = CScript([x(mandatory_pubkey), OP_CHECKSIGVERIFY, 1, x(other_pubkeys[0]), x(other_pubkeys[1]), 2, OP_CHECKMULTISIG])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))
Ejemplo n.º 46
0
args = parser.parse_args()

logging.root.setLevel('DEBUG')

if args.testnet:
    bitcoin.SelectParams('testnet')

rpc = bitcoin.rpc.Proxy()

args.dust = int(args.dust * COIN)

feeperbyte1 = args.fee1 / 1000 * COIN
feeperbyte2 = args.fee2 / 1000 * COIN

# Construct payment tx
payment_address = CBitcoinAddress(args.address)

payment_txout = CTxOut(int(args.amount * COIN), payment_address.to_scriptPubKey())
change_txout = CTxOut(0, rpc.getnewaddress().to_scriptPubKey())

tx = CTransaction()
tx.vout.append(change_txout)
tx.vout.append(payment_txout)

# Add all undesirable txouts meant to reduce propagation
if args.op_return:
    op_ret_txout = CTxOut(0, CScript([OP_RETURN, b'\x00unsuccessful double-spend attempt\x00']))
    tx.vout.append(op_ret_txout)

if args.multisig:
    multisig_txout = CTxOut(args.dust,
Ejemplo n.º 47
0
try:
    rpc.gettransaction(args.txid)
except IndexError as err:
    parser.exit('Invalid txid: Not in wallet.')

txinfo = rpc.getrawtransaction(args.txid, True)
tx = CMutableTransaction.from_tx(txinfo['tx'])

if 'confirmations' in txinfo and txinfo['confirmations'] > 0:
    parser.exit("Transaction already mined; %d confirmations." % txinfo['confirmations'])

# Find a txout that was being used for change
change_txout = None
for vout in tx.vout:
    try:
        addr = CBitcoinAddress.from_scriptPubKey(vout.scriptPubKey)
    except ValueError:
        continue

    if rpc.validateaddress(addr)['ismine']:
        change_txout = vout
        break

if change_txout is None:
    # No suitable change txout; no txout was an address in our wallet.
    #
    # Create a new txout for use as change.
    addr = rpc.getrawchangeaddress()
    change_txout = CMutableTxOut(0, addr.to_scriptPubKey())
    tx.vout.append(change_txout)
Ejemplo n.º 48
0
def build_2_of_3(pubkeys):
    txin_redeemScript = CScript([2, x(pubkeys[0]), x(pubkeys[1]), x(pubkeys[2]), 3, OP_CHECKMULTISIG])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))
seckey = CBitcoinSecret.from_secret_bytes(h)

# Create a redeemScript. Similar to a scriptPubKey the redeemScript must be
# satisfied for the funds to be spent.
txin_redeemScript = CScript([seckey.pub, OP_CHECKSIG])
print(b2x(txin_redeemScript))

# Create the magic P2SH scriptPubKey format from that redeemScript. You should
# look at the CScript.to_p2sh_scriptPubKey() function in bitcoin.core.script to
# understand what's happening, as well as read BIP16:
# https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()

# Convert the P2SH scriptPubKey to a base58 Bitcoin address and print it.
# You'll need to send some funds to it to create a txout to spend.
txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
print('Pay to:',str(txin_p2sh_address))

# Same as the txid:vout the createrawtransaction RPC call requires
#
# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin
# transaction hashes are shown little-endian rather than the usual big-endian.
# There's also a corresponding x() convenience function that takes big-endian
# hex and converts it to bytes.
txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae')
vout = 0

# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))
Ejemplo n.º 50
0
# wouldn't conflict with the old one and you'd pay everyone twice!
tx2.vin = tx2.vin[0:1]

if not args.first_seen_safe and len(tx2.vout) > 0:
    # Delete the change output.
    #
    # Unfortunately there isn't any way to ask Bitcoin Core if a given address
    # is a change address; if you're sending yourself funds to test the feature
    # it's not possible to distinguish change from send-to-self outputs.
    #
    # So instead we always build transactions such that the first output is
    # change, and we delete only that output. Not pretty - you don't want to do
    # something that dumb and anti-privacy in a real wallet - but without a way
    # of keeping state this is the best we've got.
    try:
        addr = CBitcoinAddress.from_scriptPubKey(tx2.vout[0].scriptPubKey)
    except ValueError:
        pass
    else:
        # There is an edge case not handled: if we have multiple outputs but
        # didn't need a change output. But whatever, this is just a demo!
        if len(tx2.vout) > 1 and rpc.validateaddress(addr)['ismine']:
            tx2.vout = tx2.vout[1:]


# Add the new output
payment_txout = CMutableTxOut(args.amount, args.address.to_scriptPubKey())
tx2.vout.append(payment_txout)

r = rpc.fundrawtransaction(tx2)
tx2 = CMutableTransaction.from_tx(r['tx'])