Esempio n. 1
0
def main():
    access = ServiceProxy("http://*****:*****@127.0.0.1:8332")
    txid = sys.argv[1]
    # print txid
    txinfo = access.gettransaction(txid)
    pprint.pprint(txinfo)

    # Check the details to make sure it's an incoming transaction
    # Ensure everything is incoming, to avoid 
    # mirroring change/consolidation transactions.    
    myaddresses = set()
    for details in txinfo["details"]:
        # print details
        if details["category"] != "receive":
            return
        myaddresses.add(details["address"])

    tx = access.decoderawtransaction(txinfo["hex"])
    pprint.pprint(tx)
    # Now gather all the outputs to send back
    newtx_inputs = []
    total_amount = Decimal(0)
    for vout in tx["vout"]:
        for address in vout["scriptPubKey"]["addresses"]:
            if address in myaddresses:
                newtx_inputs.append({"txid":txid,"vout":vout["n"]})
                total_amount += vout["value"]
                break

    print newtx_inputs
    print total_amount
    
    # Now find the sendign addresses, and choose one at random
    # to receive the funds.
    total_inputs = Decimal("0")
    addresses = []
    for vin in tx["vin"]:
        intxid = vin["txid"]
        invout = vin["vout"]

        # Get the outputs of the input transaction
        intx = access.getrawtransaction(intxid,1)
        # print intxid, invout
        vout = intx["vout"][invout]
        # pprint.pprint(vout)
        total_inputs += vout["value"]
        addresses.extend(vout["scriptPubKey"]["addresses"])
    print "Total inputs: %f" % total_inputs
    print addresses
    to_address = random.choice(addresses)

    # Build a transaction with the output of the original transaction as input
    # and to_address as output.
    newtx_hex = access.createrawtransaction(newtx_inputs,{to_address:float(total_amount)})
    newtx_hex = access.signrawtransaction(newtx_hex)["hex"]
    print newtx_hex
    # print >>open("/home/user/a.txt","a"), access.decoderawtransaction(newtx_hex)
    access.sendrawtransaction(newtx_hex)
class BitcoinRPC:
    def __init__(self):
        self.connection = None
        self.network_info = None
        self.version = None
        self.relay_fee = None
        self.establish_connection()

    def establish_connection(self):
        endpoint = 'http://{user}:{pwd}@{host}:{port}'.format(
            user=NETWORK_SETTINGS['BTC']['user'],
            pwd=NETWORK_SETTINGS['BTC']['password'],
            host=NETWORK_SETTINGS['BTC']['host'],
            port=NETWORK_SETTINGS['BTC']['port'])
        print(endpoint)
        self.connection = AuthServiceProxy(endpoint)
        self.network_info = self.connection.getnetworkinfo()
        self.version = int(str(self.network_info['version'])[:2])
        res = requests.get('https://api.bitcore.io/api/BTC/mainnet/fee/3')
        self.relay_fee = int(json.loads(res.text)['feerate'] * DECIMALS['BTC'])

    def reconnect(self):
        self.establish_connection()

    def create_raw_transaction(self, input_params, output_params):
        self.reconnect()
        return self.connection.createrawtransaction(input_params,
                                                    output_params)

    def sign_raw_transaction(self, tx, private_key):
        self.reconnect()
        if self.version >= 17:
            return self.connection.signrawtransactionwithkey(tx, [private_key])
        else:
            return self.connection.signrawtransaction(tx, None, [private_key])

    def send_raw_transaction(self, tx_hex):
        self.reconnect()
        return self.connection.sendrawtransaction(tx_hex)

    def construct_and_send_tx(self, input_params, output_params, private_key):
        tx = self.create_raw_transaction(input_params, output_params)

        signed = self.sign_raw_transaction(tx, private_key)

        try:
            tx_hash = self.send_raw_transaction(signed['hex'])
            print('tx', tx_hash, flush=True)
            return tx_hash
        except Exception as e:
            print('FAILED SENDING TRANSACTION', flush=True)
            print(e, flush=True)
            return None

    def validateaddress(self, address):
        self.reconnect()
        return self.connection.validateaddress(address)
Esempio n. 3
0
def main():
    rpc_user = '******'
    rpc_password = '******'
    rpc = AuthServiceProxy(f'http://{rpc_user}:{rpc_password}@127.0.0.1:18332/')
    #rpc = AuthServiceProxy(f'http://{rpc_user}:{rpc_password}@172.17.0.2:18332/')
    print(rpc.getinfo())
    best_block_hash = rpc.getbestblockhash()
    print(rpc.getblock(best_block_hash))
    blhash = rpc.getblockhash(0) #blhashはブロックのhash文字列
    bl = rpc.getblock(blhash) #blはブロック情報
    print(bl)
    dummy_address = '2MudgRfNaaw96kqAWziZ5JGsPbo2pzQp7Jy'
    change_address = '2NAVrak22jX3DQyDqnoqdm5ZTak1RgXWPzo'

    filename = 'mark_token.btc.json'
    url='https://drive.google.com/file/d/1ZR6Q5sCM_acUpPy7s3d9GJH8I2Plh4FI/view?usp=sharing'

    with open(filename, 'rb') as f:
        data2 = f.read()
    hashdata=hashlib.sha256(data2).hexdigest()
    js={'file_hash':hashdata,'url':url}
    data=json.dumps(js).encode("UTF-8")


    while True:
        if len(data) >= 80:
            buffer = data[:80]
            data = data[80:]
        elif len(data) == 0:
            break
        else:
            buffer = data
            data = b''

        first_unspent = rpc.listunspent()[0]
        txid = first_unspent['txid']
        vout = first_unspent['vout']
        input_amount = first_unspent['amount']
        SATOSHI = Decimal("0.00000001")
        change_amount = input_amount - Decimal("0.005") - SATOSHI

        tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}],[{change_address: change_amount}, {'data': hexlify(buffer).decode('utf-8')}, ])
        tx = rpc.signrawtransactionwithwallet(tx)['hex']
        rpc.sendrawtransaction(tx)

    block_hash = rpc.generatetoaddress(1, change_address)[0]
    block = rpc.getblock(block_hash)
    txs = block['tx'][1:]

    print(f'# of txs: {len(txs)}')
    pprint(txs)

    for tx_hash in txs:
        raw_tx = rpc.gettransaction(tx_hash)['hex']
        decoded_tx = rpc.decoderawtransaction(raw_tx)
        # pprint(decoded_tx)
        print(decoded_tx['vout'][1]['scriptPubKey']['asm'])
Esempio n. 4
0
def transfer_coins():
    success = False
    txid = '0000'
    vout = 0
    rpc_connection = AuthServiceProxy("http://%s:%[email protected]:52541" %
                                      (rpcuser, rpcpassword))

    # STEP 1. select best, smallest, txid to transfer
    # bulwark-cli listunspent 70 9999999 '''["bRTwEvdihGjjCKRSiLM84xZaiwgfZCADFx"]'''
    addr = [bwkaddress_from]
    listunspent = rpc_connection.listunspent(70, 999999, addr)
    #print len(listunspent)
    smallestvalidamount = 100000000.0
    for k in range(len(listunspent)):
        if listunspent[k]["amount"] >= transfer_amount and listunspent[k][
                "spendable"]:

            if listunspent[k]["amount"] <= smallestvalidamount:
                smallestvalidamount = listunspent[k]["amount"]
                txid = listunspent[k]["txid"]
                vout = listunspent[k]["vout"]

    if smallestvalidamount < 10000000.0:
        print "         | valid txid found for sending", transfer_amount, " :", listunspent[
            k]["txid"], " ", smallestvalidamount
        # STEP 2. create raw tx
        # format cli: bulwark-cli createrawtransaction '[{"txid" : "000000000...000","vout" : 1}]' '{"bRTw...adres": 101.0, "bGM....adres": 4.41}'
        change = decimal.Decimal(smallestvalidamount) - decimal.Decimal(
            transfer_amount) - decimal.Decimal(0.00001)
        json1 = [{"txid": txid, "vout": vout}]
        json2 = {
            bwkaddress_from: float(change),
            bwkaddress_to: float(transfer_amount)
        }
        #print(json.dumps(json1))
        rawtx_hex = rpc_connection.createrawtransaction(json1, json2)

        # STEP 3. unlock wallet
        if not wallet_manually_unlocked_mode:
            rpc_connection.walletpassphrase(walletpassphrase, 99999999,
                                            wallet_manually_unlocked_mode)

        # STEP 4. sign raw tx
        # format cli: bulwark-cli signrawtransaction 00000...ab23
        rawsigned = rpc_connection.signrawtransaction(rawtx_hex)

        # STEP 5. send raw tx
        # format cli: bulwark-cli sendrawtransaction 00000...gb23
        signed_hex = rawsigned["hex"]
        sendresult = rpc_connection.sendrawtransaction(signed_hex)
        if "{" not in sendresult:  #in case error it gives a {..json error message }
            success = True
            print "         | done sending coins, blockchain txid will be ", sendresult
    return success
Esempio n. 5
0
def create_raw_op_return_transaction(metadata):
    """
    Method used to create a transaction with embedded data through OP_RETURN

    Args:
            metadata (str)

    Returns:
            Raw transaction (hex)
            Author address (str)
    """
    rpc = AuthServiceProxy(
        ("http://%s:%[email protected]:%s/") %
        (config['RPC_USER'], config['RPC_PASS'], config['RPC_PORT']))

    if sys.getsizeof(metadata) > MAX_OP_RETURN_BYTES:
        raise Exception("Metadata size is over MAX_OP_RETURN_BYTES")

    if len(metadata) < 4:
        raise Exception(
            "This tool set does not currently support reading op_return data with less than 4 chars"
        )

    input_tx = get_input()

    init_raw_tx = rpc.createrawtransaction(
        [{
            "txid": input_tx["txid"],
            "vout": input_tx["vout"]
        }], {
            input_tx["address"]:
            TX_BURN_AMOUNT,
            rpc.getnewaddress():
            round(float(input_tx["amount"]) - 1.1 * TX_BURN_AMOUNT, 8)
        })

    oldScriptPubKey = init_raw_tx[len(init_raw_tx) - 60:len(init_raw_tx) - 8]
    newScriptPubKey = b"6a" + hexlify(
        bytes(chr(len(metadata)), encoding='utf-8')) + hexlify(
            bytes(metadata, encoding='utf-8'))
    newScriptPubKey = hexlify(
        bytes(chr(len(unhexlify(newScriptPubKey))),
              encoding='utf-8')) + newScriptPubKey

    if oldScriptPubKey not in init_raw_tx:
        raise Exception("Something broke!")

    op_return_tx = init_raw_tx.replace(oldScriptPubKey,
                                       newScriptPubKey.decode('ascii'))

    print(rpc.decoderawtransaction(op_return_tx)['vout'])

    return op_return_tx, input_tx["address"]
Esempio n. 6
0
class BitcoinRPC:
    def __init__(self):
        self.connection = None
        self.network_info = None
        self.version = None
        self.relay_fee = None
        self.establish_connection()

    def establish_connection(self):
        print('http://' + NETWORK_SETTINGS['DUC']['user'] + ':' +
              NETWORK_SETTINGS['DUC']['password'] + '@' +
              NETWORK_SETTINGS['DUC']['host'] + ':' +
              NETWORK_SETTINGS['DUC']['port'])
        self.connection = AuthServiceProxy(
            'http://' + NETWORK_SETTINGS['DUC']['user'] + ':' +
            NETWORK_SETTINGS['DUC']['password'] + '@' +
            NETWORK_SETTINGS['DUC']['host'] + ':' +
            NETWORK_SETTINGS['DUC']['port'])
        self.network_info = self.connection.getnetworkinfo()
        self.relay_fee = int(self.network_info['relayfee'] * DECIMALS['DUC'])

    def reconnect(self):
        self.establish_connection()

    def create_raw_transaction(self, input_params, output_params):
        self.reconnect()
        return self.connection.createrawtransaction(input_params,
                                                    output_params)

    def sign_raw_transaction(self, tx, private_key):
        self.reconnect()
        return self.connection.signrawtransaction(tx, None, [private_key])

    def send_raw_transaction(self, tx_hex):
        self.reconnect()
        return self.connection.sendrawtransaction(tx_hex)

    def construct_and_send_tx(self, input_params, output_params, private_key):
        tx = self.create_raw_transaction(input_params, output_params)
        print('raw tx', tx, flush=True)

        signed = self.sign_raw_transaction(tx, private_key)
        print('signed tx', signed, flush=True)

        try:
            tx_hash = self.send_raw_transaction(signed['hex'])
            print('tx', tx_hash, flush=True)
            return tx_hash
        except Exception as e:
            print('FAILED SENDING TRANSACTION', flush=True)
            print(e, flush=True)
            return None
Esempio n. 7
0
def send_data(rpc_connection: authproxy.AuthServiceProxy,
              hexdata: str,
              tx_ins: list = ()) -> Transaction:
    """Creates, funds, signs and sends an OP_RETURN transaction including
    hexdata

    Parameters
    ----------
    rpc_connection : bitcoinrpc.authproxy.AuthServiceProxy
        The RPC connection to the bitcoind client

    hexdata : str
        The hex encoded data to be included in the transaction

    tx_ins : list, optional
        List of namedtuples 'Transaction', representing UTXOs to fund the
        transaction

    Returns
    -------
    Transaction
        Change UTXO

    Raises
    ------
    ValueError
        If hexdata is more than MAX_DATA_LENGTH bytes

    RuntimeError
        If the transaction could not be signed
    """

    if len(hexdata) / 2 > MAX_DATA_LENGTH:
        raise ValueError("hexdata too big")

    inputs = [{"txid": tx.txid, "vout": tx.vout} for tx in tx_ins]
    unfinished_tx = rpc_connection.createrawtransaction(
        inputs, {"data": hexdata})
    funded_tx = rpc_connection.fundrawtransaction(unfinished_tx)

    signed_tx = rpc_connection.signrawtransactionwithwallet(funded_tx["hex"])
    if signed_tx["complete"] is False:
        raise RuntimeError("bitcoind could not sign the transaction.")

    txid = rpc_connection.sendrawtransaction(signed_tx["hex"])

    change_utxo = Transaction(txid, funded_tx["changepos"])
    return change_utxo
Esempio n. 8
0
class BitcoinRPC:
    def __init__(self):
        self.connection = None
        self.network_info = None
        self.version = None
        self.relay_fee = None
        self.establish_connection()

    def establish_connection(self):
        self.connection = AuthServiceProxy(NETWORK_SETTINGS['BTC']['endpoint'])
        self.network_info = self.connection.getnetworkinfo()
        self.version = int(str(self.network_info['version'])[:2])
        self.relay_fee = int(self.network_info['relayfee'] * DECIMALS['BTC'])

    def reconnect(self):
        self.establish_connection()

    def create_raw_transaction(self, input_params, output_params):
        self.reconnect()
        return self.connection.createrawtransaction(input_params,
                                                    output_params)

    def sign_raw_transaction(self, tx, private_key):
        self.reconnect()
        if self.version >= 17:
            return self.connection.signrawtransactionwithkey(tx, [private_key])
        else:
            return self.connection.signrawtransaction(tx, None, [private_key])

    def send_raw_transaction(self, tx_hex):
        self.reconnect()
        return self.connection.sendrawtransaction(tx_hex)

    def construct_and_send_tx(self, input_params, output_params, private_key):
        tx = self.create_raw_transaction(input_params, output_params)

        signed = self.sign_raw_transaction(tx, private_key)

        try:
            tx_hash = self.send_raw_transaction(signed['hex'])
            print('tx', tx_hash, flush=True)
            return tx_hash
        except Exception as e:
            print('FAILED SENDING TRANSACTION', flush=True)
            print(e, flush=True)
            return None
Esempio n. 9
0
def main():
    bitcoin = AuthServiceProxy("http://{}:{}@127.0.0.1:{}".format(
        RPCUSER, RPCPASSWORD, RPCPORT))
    address = ADDRESS
    if address is None:
        address = bitcoin.getaddressesbyaccount("")[0]
        print("Using wallet address: ", address)
    parent_txid = "NULL"
    subprotocols = [None, gen_media, gen_pastebin, gen_randomdata]

    # Create nodes...
    for i in range(NUM_NODES_TO_CREATE):
        node = create_node(address, parent_txid)

        # Add subprotocols to node
        for _ in range(5):
            subprotocol = secrets.choice(subprotocols)
            if subprotocol is not None:
                node['subprotocols'].append(subprotocol())

        # Create OP_RETURN data
        data = b'meta' + encode_function(ENCODING)(node)
        assert (len(data) < 100000)  # sanity check for op_return max limit
        data_hex = data.hex()

        # bitcoin rpc commands to create and fund tx with metanet data in OP_RETURN
        rawtx = bitcoin.createrawtransaction([], {'data': data_hex})
        result = bitcoin.fundrawtransaction(rawtx, {'changeAddress': address})
        rawtx = result['hex']
        result = bitcoin.signrawtransaction(rawtx)
        assert (result['complete'])
        signedtx = result['hex']
        txid = bitcoin.sendrawtransaction(signedtx)

        # Prepare for next iteration
        parent_txid = txid
        print("[Node {}]: https://test.whatsonchain.com/tx/{}".format(i, txid))
Esempio n. 10
0
SATOSHI = Decimal("0.00000001")
change_amount = input_amount - Decimal("0.005") - SATOSHI
# Marker address we're going to replace
# Produces a pattern that's easy to search for
mainnet = 0
if mainnet:
    dummy_address = "1111111111111111111114oLvT2"
else:
    dummy_address = "mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8"

# My change address
change_address = "mhZuYnuMCZLjZKeDMnY48xsR5qkjq7bAr9"


tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \
                              {change_address: change_amount, \
                               dummy_address: SATOSHI})

# Pattern to replace
# Represents length of script, then OP_DUP OP_HASH160,
# then length of hash, then 20 bytes of zeros, OP_EQUALVERIFY OP_CHECKSIG
oldScriptPubKey = "1976a914000000000000000000000000000000000000000088ac"

# Data to insert
data = "Melons."
if len(data) > 75:
    raise Exception("Can't contain this much data-use OP_PUSHDATA1")

newScriptPubKey = "6a" + hexlify(chr(len(data))) + hexlify(data)

#Append int of length to start
Esempio n. 11
0
class DucatuscoreInterface:
    endpoint = None
    settings = None

    def __init__(self):

        self.settings = NETWORK_SETTINGS['DUC']
        self.setup_endpoint()
        self.rpc = AuthServiceProxy(self.endpoint)
        self.check_connection()

    def setup_endpoint(self):
        self.endpoint = 'http://{user}:{pwd}@{host}:{port}'.format(
            user=self.settings['user'],
            pwd=self.settings['password'],
            host=self.settings['host'],
            port=self.settings['port'])
        return

    def check_connection(self):
        block = self.rpc.getblockcount()
        if block and block > 0:
            return True
        else:
            raise Exception('Ducatus node not connected')

    def transfer(self, address, amount):
        #try:
        value = int(amount) / DECIMALS['DUC']
        print('try sending {value} DUC to {addr}'.format(value=value,
                                                         addr=address))
        self.rpc.walletpassphrase(self.settings['wallet_password'], 30)
        res = self.rpc.sendtoaddress(address, value)
        print(res)
        return res
        '''except JSONRPCException as e:
            err = 'DUCATUS TRANSFER ERROR: transfer for {amount} DUC for {addr} failed' \
                .format(amount=amount, addr=address)
            print(err, flush=True)
            print(e, flush=True)
            raise DucatuscoreInterfaceException(err)'''

    def validate_address(self, address):
        for attempt in range(10):
            print('attempt', attempt, flush=True)
            try:
                rpc_response = self.rpc.validateaddress(address)
            except RemoteDisconnected as e:
                print(e, flush=True)
                rpc_response = False
            if not isinstance(rpc_response, bool):
                print(rpc_response, flush=True)
                break
        else:
            raise Exception('cannot validate address with 10 attempts')

        return rpc_response['isvalid']

    def get_unspent(self, tx_hash, count):
        return self.rpc.gettxout(tx_hash, count)

    def get_fee(self):
        return self.rpc.getinfo()['relayfee']

    def get_unspent_input(self, tx_hash, payment_address):
        last_response = {}
        count = 0
        while isinstance(last_response, dict):
            rpc_response = self.get_unspent(tx_hash, count)
            last_response = rpc_response

            input_addresses = rpc_response['scriptPubKey']['addresses']
            if payment_address in input_addresses:
                return rpc_response, count

            count += 1

    def internal_transfer(self, tx_list, address_from, address_to, amount,
                          private_key):
        print('start raw tx build', flush=True)
        print('tx_list',
              tx_list,
              'from',
              address_from,
              'to',
              address_to,
              'amount',
              amount,
              flush=True)
        try:
            input_params = []
            for payment_hash in tx_list:
                unspent_input, input_vout_count = self.get_unspent_input(
                    payment_hash, address_from)
                print('unspent input', unspent_input, flush=True)

                input_params.append({
                    'txid': payment_hash,
                    'vout': input_vout_count
                })

            transaction_fee = self.get_fee() * DECIMALS['DUC']
            send_amount = (Decimal(amount) - transaction_fee) / DECIMALS['DUC']

            print('input_params', input_params, flush=True)
            output_params = {address_to: send_amount}
            print('output_params', output_params, flush=True)

            tx = self.rpc.createrawtransaction(input_params, output_params)
            print('raw tx', tx, flush=True)

            signed = self.rpc.signrawtransaction(tx, None, [private_key])
            print('signed tx', signed, flush=True)

            tx_hash = self.rpc.sendrawtransaction(signed['hex'])
            print('tx', tx_hash, flush=True)

            return tx_hash

        except JSONRPCException as e:
            print(
                'DUCATUS TRANSFER ERROR: transfer for {amount} DUC for {addr} failed'
                .format(amount=amount, addr=address_to),
                flush=True)
            print(e, flush=True)
            raise DucatuscoreInterfaceException(e)
Esempio n. 12
0
                raw_input('发送到哪个地址? (例如33hxAeUqNnFs3gdayu7aAaijhTbbfnphq8) '))
            if SendAddress == "33hxAeUqNnFs3gdayu7aAaijhTbbfnphq8":
                print "太感谢了,你选择捐赠给johnson Diao"
            print
            Leftover = int(
                unspent[WhichTrans]["amount"] * 100000000) - HowMuch - SetTxFee
            print "将要发送您的比特币到这个地址:", SendAddress, "账户里会留下来 ", Leftover, " 聪", ",这些币会发送到找零地址:", ChangeAddress
            print "会发送 ", SetTxFee, " 聪的网络手续费给矿工"
            print
            print "将要创建发送单"

            rawtransact = bitcoin.createrawtransaction(
                [{
                    "txid": unspent[WhichTrans]["txid"],
                    "vout": unspent[WhichTrans]["vout"],
                    "scriptPubKey": unspent[WhichTrans]["scriptPubKey"],
                    "redeemScript": unspent[WhichTrans]["redeemScript"]
                }], {
                    SendAddress: HowMuch / 100000000.00,
                    ChangeAddress: Leftover / 100000000.00
                })
            print "发送单为:", rawtransact
            print
            print
            print "现在我们要用私钥进行签名"
            multisigprivkeyone = str(raw_input("请输入第一个私钥:"))
            print
            signedone = bitcoin.signrawtransaction(
                rawtransact,
                [{
                    "txid": unspent[WhichTrans]["txid"],
                    "vout": unspent[WhichTrans]["vout"],
Esempio n. 13
0
class UsdtWallet():
    USDT_BLOCK_NUM = 'http://www.tokenview.com:8088/coin/latest/USDT'
    USDT_TX_API = 'https://api.omniexplorer.info/v1/transaction/address'
    USDT_URL_BALANCE = 'https://api.omniexplorer.info/v1/address/addr/'

    def __init__(self, consul_client=None):
        if consul_client:
            self.init_consul(consul_client)

    def init_consul(self, app, consul_client):
        self.propertyid = 31
        # self.usdt_rpc_user = app.config["USDT_RPC_USER"]
        # self.usdt_rpc_password = app.config["USDT_RPC_PWD"]
        # self.usdt_passphrase = app.config.get('GETH_USDT_PASSPHRASE')
        # self.consul_client = consul_client
        # # self.wallet_url = self.consul_client.getRandomOneAvailableServiceIpPort(ConsulServiceName.USDTEREUM_CLI)
        # self.wallet_url = '47.52.131.71:7332'
        # print(self.wallet_url)
        # self.usdtcoin_cli = AuthServiceProxy(
        #     "http://%s:%s@" % (self.usdt_rpc_user, self.usdt_rpc_password) + self.wallet_url, timeout=10)
        # if not self.is_connected():
        #     logging.error('Connect USDT wallet node fial')
        self.usdtcoin_cli = AuthServiceProxy("http://%s:%[email protected]:7332" %
                                             ('xianda', 'ABQOqmPZ0tr95f5Z'))

    def is_connected(self):
        """获取钱包状态判读是否链接"""
        try:
            if self.usdtcoin_cli.getwalletinfo().get('walletversion'):
                return True
            return False
        except Exception as e:
            return False

    def is_syncing(self):
        """节点是否在同步中"""
        # 注意返回Flase表示节点同步完成
        info = self.usdtcoin_cli.getblockchaininfo()
        # print(info['blocks'], info['headers'])
        if info['blocks'] != info['headers']:
            return False
        else:
            return True

    def accountCreate(self, accountName):
        # 否则,创建账户,并返回账户地址
        address = self.usdtcoin_cli.getaccountaddress(accountName)
        privateKey = self.usdtcoin_cli.dumpprivkey(address)
        return privateKey, address

    # 檢驗賬戶是否有效
    def is_valid_address(self, address):
        if address is None or address == '':
            return False
        else:
            try:
                # print(self.usdtcoin_cli.validateaddress(address))
                return self.usdtcoin_cli.validateaddress(address).get(
                    'isvalid')
            except:
                return False

    # 獲取餘額
    def get_balance(self, address):
        """获取余额,默认最新区块"""
        try:
            balance = str(
                self.usdtcoin_cli.omni_getbalance(address,
                                                  self.propertyid)['balance'])
        except Exception as e:
            logging.error('USDT node get balance error:{}'.format(str(e)))
            raise Exception('USDT node get balance error')
        return Decimal(balance)

    def get_block_num(self):
        """获取最新区块数"""
        try:
            block_num = self.usdtcoin_cli.getblockcount()
        except Exception as e:
            logging.error('Get eth node block number error:{}'.format(str(e)))
            return
        return block_num

    def get_nonce(self, address):
        """获取账户nonce值"""
        try:
            # pending 获得最新已使用的nonce,对nonce进行加1
            nonce = len(
                self.usdtcoin_cli.omni_listpendingtransactions(address))
        except Exception as e:
            logging.error('USDT node get balance error:{}'.format(str(e)))
            raise Exception('USDT node get balance error')
        return nonce

    def get_mian_block_num(self):
        """获取公链上的最新区块数"""
        try:
            header = {
                'User-Agent':
                'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36',
            }
            ret = session_pool.get(self.USDT_BLOCK_NUM,
                                   headers=header,
                                   timeout=30).json()
            if ret is None:
                logging.error('Get usdt main chain block number error')
                return
            block_num = ret.get('data')
        except Exception as e:
            logging.error(
                'Get usdt main chain block number error:{}'.format(e))
            return
        return block_num  # int

    def get_minerFee(self, address):
        data = {'addr': address}
        try:
            balance = None
            rets = session_pool.post(self.USDT_URL_BALANCE,
                                     data=data,
                                     timeout=50).json().get('balance')
            if rets or len(rets) != 0:
                for ret in rets:
                    if ret.get('propertyinfo') and int(
                            ret.get('propertyinfo').get('propertyid')) == 0:
                        balance = ret.get('value')
        except Exception as e:
            logging.error(
                'Request USDT_TX_API error address:{},error:{},url:{}'.format(
                    address, str(e), self.USDT_TX_API))
            raise Exception('USDT node get balance error')
        return Decimal(balance) / 100000000

    def usdt_transaction_record(self,
                                address,
                                last_timestamp,
                                start_block=None,
                                end_block=None):
        """查询账户交易记录"""
        if start_block is None:
            start_block = 0
        if end_block is None:
            end_block = 99999999
        # 可能会有重复记录,使用此方法
        run_function = lambda x, y: x if y in x else x + [y]

        data = {'addr': address, 'page': 0}
        try:
            rets = session_pool.post(self.USDT_TX_API, data=data,
                                     timeout=50).json()
        except Exception as e:
            logging.error(
                'Request USDT_TX_API error address:{},error:{},url:{}'.format(
                    address, str(e), self.USDT_TX_API))
            rets = None

        new_records = []
        ret = rets.get('transactions')
        if ret is None:
            return new_records
        ret_page_num = int(rets.get('pages'))
        if ret_page_num == 1:
            # print(ret_page_num)
            self.query_records(address, ret, new_records, last_timestamp,
                               start_block, end_block)
            return (reduce(run_function, [
                [],
            ] + new_records))
        else:
            for i in range(0, ret_page_num):
                data = {'addr': address, 'page': i}
                try:
                    ret = session_pool.post(
                        self.USDT_TX_API, data=data,
                        timeout=50).json().get('transactions')
                except Exception as e:
                    logging.error(
                        'Request USDT_TX_API error address:{},error:{},url:{}'.
                        format(address, str(e), self.USDT_TX_API))
                    ret = None

                if ret is None:
                    return new_records
                self.query_records(address, ret, new_records, last_timestamp,
                                   start_block, end_block)
            return (reduce(run_function, [
                [],
            ] + new_records))

    def query_records(self, address, records, new_records, last_timestamp,
                      start_block, end_block):
        for record in records:
            propertyid = record.get('propertyid')
            valid = record.get('valid')
            block = record.get('block')
            if valid and int(propertyid) == 31 and int(start_block) <= int(
                    block) and int(block) <= int(end_block):
                to_address = record['referenceaddress']  # 是否为收款记录
                current_timestamp = int(record['blocktime'])  # 当前记录时间戳
                confirmations = int(record['confirmations'])  # 交易记录确认数
                record_hash = record['txid']
                amount = Decimal(record['amount'])
                if to_address.lower() != address.lower():
                    continue
                if int(last_timestamp) > int(current_timestamp):
                    continue
                if Order.hash_is_exist(record_hash):
                    continue
                if amount < Decimal('0.0000001'):
                    continue
                if confirmations < 2:
                    break
                else:
                    new_records.append(record)
            else:
                if records is None:
                    logging.error(
                        'Request USDT_TX_API fail address:{} ret:{}, url:{}'.
                        format(address, str(records), self.USDT_TX_API))
        return new_records

    def hash_get_detail(self, tx_hash):
        """hash获取交易细节,用于确认链外交易是否被确认"""
        # 交易是否被确认.status=1(被确认)
        is_confirm = False  # 是否确认
        is_success = False  # 如果已确认,交易是否成功
        msg = None  # 未被确认返回异常信息(一般超时),确认失败:失败的细节,确认成功:交易详情
        fee = None  # 确认成功交易的手续费
        try:
            ret = self.usdtcoin_cli.omni_gettransaction(tx_hash)  # 获取交易细节
        except Exception as e:
            msg = str(e)
            return is_confirm, is_success, msg, fee

        confirm = ret.get('confirmations')
        if confirm < 1:  # 确认交易失败
            msg = dict(fail_detail=str(ret))
            return is_confirm, is_success, msg, fee
        else:  # 确认交易成功
            is_confirm = True
            is_success = True
            fee = ret.get('fee')
            msg = dict(confirm=str(ret), tx_detail=str(ret))
            return is_confirm, is_success, msg, fee

    def payment(self, addrfrom, addrto, amount):
        """普通付款"""
        # 单位换算
        payload = {'from': addrfrom, 'to': addrto, 'value': str(amount)}
        try:
            # 钱包转账,返回交易哈希值
            tx_hash = self.usdtcoin_cli.omni_send(addrfrom, addrto,
                                                  self.propertyid, str(amount))
            return True, tx_hash
        except Exception as e:
            payload.update(dict(errormsg=str(e)))
            logging.error('usdt payment error:{}'.format(str(payload)))
            return False, str(e)

    def raw_transaction(self, minerfee_address, fromAddr, toAddre, value,
                        miner_minfee):
        # 查询USDT未使用的UTXO
        USDT_unspents = self.usdtcoin_cli.listunspent(1, 9999999, [fromAddr])
        if not USDT_unspents:
            return False, str('No USDT UTXO model available')
        USDT_unspent = USDT_unspents[0]
        # 查询BTC未使用的UTXO(矿工费)
        BTC_unspents = self.usdtcoin_cli.listunspent(1, 9999999,
                                                     [minerfee_address])
        if not BTC_unspents:
            return False, str('No BTC UTXO model available')
        BTC_unspent = BTC_unspents[0]
        # 所用值
        from_txid = USDT_unspent['txid']
        from_scriptPubKey = USDT_unspent['scriptPubKey']
        from_vout = USDT_unspent['vout']
        from_amount = USDT_unspent['amount']
        to_txid = BTC_unspent['txid']
        to_scriptPubKey = BTC_unspent['scriptPubKey']
        to_vout = BTC_unspent['vout']
        to_amount = BTC_unspent['amount']

        rawtransactionparams = [
            dict(txid=from_txid,
                 scriptPubKey=from_scriptPubKey,
                 vout=from_vout),
            dict(txid=to_txid, scriptPubKey=to_scriptPubKey, vout=to_vout),
        ]
        # 创建原生BTC交易获取哈希值
        RawTxChangeparams = [
            # 转出地址必须放在第一个,矿工费地址放在下面
            dict(txid=from_txid,
                 scriptPubKey=from_scriptPubKey,
                 vout=from_vout,
                 value=from_amount),
            dict(txid=to_txid,
                 scriptPubKey=to_scriptPubKey,
                 vout=to_vout,
                 value=to_amount),
        ]

        # 构造发送代币类型和代币数量数据
        payload = self.usdtcoin_cli.omni_createpayload_simplesend(
            self.propertyid, str(value))
        print('usdt交易', payload)

        # 构造交易基本数据
        data = {}
        btc_txid = self.usdtcoin_cli.createrawtransaction(
            rawtransactionparams, data)

        # 在交易上绑定代币数据
        rawtx = self.usdtcoin_cli.omni_createrawtx_opreturn(btc_txid, payload)
        print('usdt交易绑定到btc交易的哈希', rawtx)

        # 在交易上添加接收地址
        rawtx = self.usdtcoin_cli.omni_createrawtx_reference(rawtx, toAddre)
        print('添加接受地址', rawtx)

        # 在交易数据上指定矿工费用
        rawtx = self.usdtcoin_cli.omni_createrawtx_change(
            rawtx, RawTxChangeparams, minerfee_address, Decimal(miner_minfee))
        print('设置手续的哈希', rawtx)

        # 签名
        ret = self.usdtcoin_cli.signrawtransaction(rawtx)
        if not ret['complete']:
            return False, str('Incomplete signature')

        # 广播
        tx_hash = self.usdtcoin_cli.sendrawtransaction(ret['hex'])
        print('交易哈希', tx_hash)

        if tx_hash:
            return True, tx_hash
Esempio n. 14
0
    r['txid'],
    "vout":
    r['vout'],
    "scriptPubKey":
    r['scriptPubKey'],
    "redeemScript":
    "522103133255e240ded2cd1d0b8fa5b659fd7713b74f6ea074f4a80e3cb1f0677df0612103985457b91195038af91c1c7b09c693e9a141681319b683c46871b2dbf1beb09d52ae"
}]

print ""
print "TX", tx
# 2 cents
trans = bitcoin.createrawtransaction(
    tx, {
        multiaddress: 0.004,
        company1: 0.0001,
        company2: 0.0002,
        company3: 0.0003,
        company4: 0.0003
    })
print trans

print ""
print "Signing raw transaction"
signed1 = bitcoin.signrawtransaction(
    trans, tx, ["cRuMbJGz3WN7cVzbUe4iLfT7g5hPZX4eoukYeAwdXsVNjkbRBcJ3"])
print signed1

print ""
print "Signing raw2 transaction"
signed2 = bitcoin.signrawtransaction(
    signed1['hex'], tx,
Esempio n. 15
0
class WalletBase:

    def __init__(self, pay_tx_fee, min_tx_fee,
                 prio_threshold, dust_soft_limit, free_tx_size):
        self.proxy = None
        self.pay_tx_fee = pay_tx_fee
        self.min_tx_fee = min_tx_fee
        self.prio_threshold = prio_threshold
        self.dust_soft_limit = dust_soft_limit
        self.free_tx_size = free_tx_size

    def set_size(self, base_size, input_size, output_size):
        self.base_size = base_size
        self.input_size = input_size
        self.output_size = output_size

    def load_config(self, config_path):
        # trick to load a config file without sections
        con = open(config_path, 'r').read()
        dummy_fp = io.StringIO(("[%s]\n" % TMP_SECTION) + con)
        config = configparser.ConfigParser()
        config.readfp(dummy_fp)

        ## utility function
        def get_conf(key, default=None):
            if config.has_option(TMP_SECTION, key):
                return config.get(TMP_SECTION, key)
            return default

        self.rpc_user = get_conf('rpcuser')
        self.rpc_pass = get_conf('rpcpassword')
        self.rpc_port = int(get_conf('rpcport'))
        self.rpc_host = get_conf('rpcconnect', '127.0.0.1')

        if config.has_option(TMP_SECTION, 'paytxfee'):
            self.pay_tx_fee = int(float(get_conf('paytxfee')) * 10**8)
        if config.has_option(TMP_SECTION, 'mintxfee'):
            self.min_tx_fee = int(float(get_conf('mintxfee')) * 10**8)

    def connect(self):
        self.proxy = AuthServiceProxy('http://%s:%s@%s:%d/' %
                                      (self.rpc_user, self.rpc_pass,
                                       self.rpc_host, self.rpc_port))

    def get_size(self, inputs, outputs):
        raw = self.proxy.createrawtransaction(inputs, outputs)
        return len(raw) / 2

    ## Deprecate after official supports for getrawchangeaddress in major coins
    def get_change_address(self):
        groups = self.proxy.listaddressgroupings()
        for group in groups:
            for entry in group:
                if len(entry) == 3:
                    ## maybe with account
                    continue
                elif len(entry) == 2:
                    res = self.proxy.validateaddress(entry[0])
                    if 'account' not in res:
                        return entry[0]
                else:
                    raise RuntimeError('never reach')
        return self.proxy.getnewaddress()

    ## ref: wallet.cpp CWallet::CreateTransaction
    def calculate(self, inputs, address, amount, chgaddress):
        tmp = {address: float(amount) / 10**8, chgaddress: 1 }
        size = self.get_size(inputs, tmp)

        total = 0
        prio = 0
        for inp in inputs:
            raw = self.proxy.getrawtransaction(inp['txid'])
            tx = self.proxy.decoderawtransaction(raw)
            value = tx['vout'][inp['vout']]['value']
            conf = self.proxy.gettransaction(inp['txid'])['confirmations']

            total += int(value * 10**8)
            prio += int(value * 10**8) * (conf + 1)
        prio = int(prio / size)

        payfee = self.pay_tx_fee * (1 + int(size / 1000))

        minfee = self.min_tx_fee * (1 + int(size / 1000))
        if prio >= self.prio_threshold and size < self.free_tx_size:
            minfee = 0
        if amount < self.dust_soft_limit:
            minfee += self.min_tx_fee
        if total-amount-minfee < self.dust_soft_limit:
            minfee += self.min_tx_fee
        fee = max(payfee, minfee)

        change = total - amount - fee

        if change <= 0:
            raise RuntimeError('Insufficient inputs: change = %f' %
                               (float(change) / 10**8))

        return { 'total': total, 'fee': fee, 'change': change,
                  'size': size, 'prio': prio }

    def send(self, inputs, address, amount):
        chgaddress = self.get_change_address()
        res = self.calculate(inputs, address, amount, chgaddress)
        outputs = { address: float(amount) / 10**8,
                    chgaddress: float(res['change']) / 10**8 }

        raw = self.proxy.createrawtransaction(inputs, outputs)
        signed = self.proxy.signrawtransaction(raw)
        if not signed['complete']:
            raise RuntimeError('signatures are missing')
        return self.proxy.sendrawtransaction(signed['hex'])

    def show_send_info(self, inputs, address, amount):
        chgaddress = self.get_change_address()
        res = self.calculate(inputs, address, amount, chgaddress)

        print('Total amount: %f' % (float(res['total']) / 10**8))
        print('Send: %f to %s' % (float(amount) / 10**8, address))
        print('Change: %f to %s' % (float(res['change']) / 10**8, chgaddress))
        print('Fee: %f' % (float(res['fee']) / 10**8))
        print('Size: %d bytes' % res['size'])
        print('Priority: %d' % res['prio'])

    def unspent_coins(self):
        coins = self.proxy.listunspent(6)
        for c in coins:
            c['amount'] = int(c['amount'] * 10**8)
            c['prio'] = c['amount'] * (c['confirmations'] + 1)
        return coins
    def do(self):
        rpc = AuthServiceProxy('http://' + settings.BITCOIN_RPC_USERNAME + ':' + settings.BITCOIN_RPC_PASSWORD + '@' + settings.BITCOIN_RPC_IP + ':' + str(settings.BITCOIN_RPC_PORT))

        # Send all outgoing transactions that are ready to go
        otxs_to_send = OutgoingTransaction.objects.filter(inputs_selected_at__isnull=False, sent_at=None)
        for otx in otxs_to_send:
            # Gather inputs argument
            inputs = []
            for inpt in otx.inputs.all():
                inputs.append({
                    'txid': inpt.bitcoin_txid,
                    'vout': inpt.bitcoin_vout,
                })
            # Gather outputs argument
            outputs = {}
            for output in otx.outputs.all():
                outputs.setdefault(output.bitcoin_address, Decimal(0))
                outputs[output.bitcoin_address] += output.amount
            # Use arguments to create, sign and send raw transaction
            raw_tx = rpc.createrawtransaction(inputs, outputs)
            signing_result = rpc.signrawtransaction(raw_tx)
            raw_tx_signed = signing_result['hex']
            if signing_result['complete']:
                # Calculate how much fee each wallet needs to pay
                total_fees = otx.calculateFee()
                fees_for_wallets = []
                if total_fees:
                    txs_count = len(otx.txs.all())
                    for tx in otx.txs.all():
                        wallet_found = False
                        for fee_for_wallet in fees_for_wallets:
                            if fee_for_wallet['wallet'] == tx.wallet:
                                fee_for_wallet['amount'] += total_fees / txs_count
                                wallet_found = True
                        if not wallet_found:
                            fees_for_wallets.append({
                                'wallet': tx.wallet,
                                'amount': total_fees / txs_count,
                            })
                for fee_for_wallet in fees_for_wallets:
                    fee_for_wallet['amount'] = fee_for_wallet['amount'].quantize(Decimal('0.00000001'))

                fee_receiving_wallet = getOrCreateChangeWallet()
                fee_receiving_address = fee_receiving_wallet.getOrCreateAddress(0)

                rpc.sendrawtransaction(raw_tx_signed)

                # Atomically mark outgoing transaction as send and reduce fees from wallets.
                with transaction.atomic():
                    otx.sent_at = now()
                    otx.save(update_fields=['sent_at'])

                    total_effective_fee = Decimal(0)
                    sending_addresses = []
                    for fee_for_wallet in fees_for_wallets:
                        wallet = fee_for_wallet['wallet']
                        amount = fee_for_wallet['amount']
                        # Sending transaction
                        Transaction.objects.create(
                            wallet=wallet,
                            amount=-amount,
                            description='Fee from sent Bitcoins',
                            receiving_address=fee_receiving_address,
                        )

                        # Reduce funds
                        wallet = Wallet.objects.get(path=wallet.path)
                        wallet.extra_balance -= amount
                        wallet.save(update_fields=['extra_balance'])

                        # Keep track who sent this
                        sending_addresses.append({
                            'amount': amount,
                        })

                        total_effective_fee += amount

                    # Receiving transaction
                    Transaction.objects.create(
                        wallet=fee_receiving_wallet,
                        amount=total_effective_fee,
                        description='Fee refund from sent Bitcoins',
                        sending_addresses=sending_addresses,
                    )

                    # Add funds
                    fee_receiving_wallet = Wallet.objects.get(path=fee_receiving_wallet.path)
                    fee_receiving_wallet.extra_balance += total_effective_fee
                    fee_receiving_wallet.save(update_fields=['extra_balance'])

        # Get all outgoing transactions that do not have any inputs selected
        otxs_without_inputs = OutgoingTransaction.objects.filter(inputs_selected_at=None)

        # If all outgoing transactions are fine, then do nothing more
        if otxs_without_inputs.count() == 0:
            return

        # TODO: Some lock here might be a good idea, just to be sure!

        # List all unspent outputs that aren't already assigned to some outgoing transaction
        unspent_outputs_raw = rpc.listunspent(settings.CONFIRMED_THRESHOLD)
        unspent_outputs = []
        for unspent_output in unspent_outputs_raw:
            txid = unspent_output['txid']
            vout = unspent_output['vout']

            if unspent_output['spendable']:

                # If there is no existing input, then this output isn't assigned yet
                if OutgoingTransactionInput.objects.filter(bitcoin_txid=txid, bitcoin_vout=vout).count() == 0:
                    unspent_outputs.append(unspent_output)

        # Assign inputs to those transactions that do not have them set
        for otx in otxs_without_inputs:
            # Calculate how much is being sent
            outputs_total = otx.outputs.aggregate(Sum('amount'))['amount__sum'] or Decimal(0)

            # Calculate fee
            tx_size = 148 * otx.inputs.count() + 34 * (otx.outputs.count() + 1) + 10
            fee = settings.TRANSACTION_FEE_PER_KILOBYTE * ((tx_size + 999) / 1000)

            # Now assign inputs until there is enough for outputs
            inputs_total = otx.inputs.aggregate(Sum('amount'))['amount__sum'] or Decimal(0)
            while inputs_total < outputs_total + fee and len(unspent_outputs) > 0:
                # Find unspent output that has most confirmations
                best_unspent_output = None
                best_unspent_output_i = None
                best_unspent_output_confirmations = 0
                for unspent_outputs_i in range(len(unspent_outputs)):
                    unspent_output = unspent_outputs[unspent_outputs_i]
                    if unspent_output['confirmations'] > best_unspent_output_confirmations:
                        best_unspent_output = unspent_output
                        best_unspent_output_i = unspent_outputs_i
                        best_unspent_output_confirmations = unspent_output['confirmations']

                # Assign this unspent output as input
                OutgoingTransactionInput.objects.create(
                    tx=otx,
                    amount=best_unspent_output['amount'],
                    bitcoin_txid=best_unspent_output['txid'],
                    bitcoin_vout=best_unspent_output['vout'],
                )
                inputs_total += best_unspent_output['amount']

                # Recalculate fee
                tx_size += 148
                fee = settings.TRANSACTION_FEE_PER_KILOBYTE * ((tx_size + 999) / 1000)

                # Remove the best output from unspent outputs
                del unspent_outputs[best_unspent_output_i]

            # If there was no suitable unspent outputs, then it means hot wallet does not
            # have enough funds for this transaction. We have to give up. Already assigned
            # inputs are, however, not cleared. Because of this, we have to give up
            # totally, because this transaction wasted rest of the available outputs.
            if inputs_total < outputs_total + fee:
                break

            # Calculate how much extra there is, and send it back to some of the change
            # addresses. If the system fails right after this operation, it doesn't matter,
            # because the inputs and outputs have perfect match, and next runs will do
            # nothing but set the "inputs_selected_at" timestamp.
            extra_amount = inputs_total - (outputs_total + fee)
            if extra_amount > Decimal(0):
                change_wallet = getOrCreateChangeWallet()
                change_address = change_wallet.getOrCreateAddress(0)
                OutgoingTransactionOutput.objects.create(tx=otx, amount=extra_amount, bitcoin_address=change_address.address)

            # Enough inputs was assigned, so marking this transaction fully assigned
            otx.inputs_selected_at = now()
            otx.save(update_fields=['inputs_selected_at'])
Esempio n. 17
0
        amount = min(Decimal(args.max_amt_per_output), na)
        if ((na - amount) < 10):
            amount = na
        addr = b.getnewaddress('consolidate')
        if (Decimal(str(float(amount))) > 0):
            if addr not in out:
                out[addr] = float(0)
            out[addr] += float(amount)
        na -= Decimal(str(float(amount)))
    print 'Paying %s RVN (%s fee) to:' % (sum([
        Decimal(str(out[k])) for k in out.keys()
    ]), amt - sum([Decimal(str(out[k])) for k in out.keys()]))
    for o in out.keys():
        print '  %s %s' % (o, out[o])

    txn = b.createrawtransaction(txouts, out)

    a = raw_input('Sign the transaction? y/[n]: ')
    if a != 'y':
        exit(0)

    signed_txn = b.signrawtransaction(txn)
    print signed_txn
    print 'Bytes: %d Fee: %s' % (len(signed_txn['hex']) / 2, amt - sum(
        [Decimal(str(out[x])) for x in out.keys()]))

    a = raw_input('Send the transaction? y/[n]: ')
    if a != 'y':
        exit(0)

    txid = b.sendrawtransaction(signed_txn['hex'])
Esempio n. 18
0
        # Get Transaction id and output # of unspent transaction
        txid = unspent[i]['txid']
        vout = unspent[i]['vout']

        # Remove the fee from the unspent transaction balance.
        # The remainder is returned to the senders change_address
        amount = amount - tx_fee
        change_address = rpc_connection.getrawchangeaddress()

        # New transaction input
        input = [{"txid": txid, "vout": vout}]
        # New transaction output including amount sent to change_address and the hexadecimal string
        output = {change_address: amount, "data": hex.decode()}

        # Create unsigned transaction
        raw_tx = rpc_connection.createrawtransaction(input, output)

        # Unlock user wallet before signing, assuming the pass[hrase is stored in environment variables as WALLET_PASS (safe?)
        rpc_connection.walletpassphrase(os.environ.get("WALLET_PASS"), 100)

        # Sign transaction and send
        signed_tx = rpc_connection.signrawtransaction(raw_tx)
        status = rpc_connection.sendrawtransaction(signed_tx["hex"])

        # print the decoded transaction
        decoded = rpc_connection.decoderawtransaction(signed_tx["hex"])
        if signed_tx['complete']:
            print("status: complete")
            print("tx info: " + str(decoded))
        else:
            print("error: " + signed_tx['error'])
Esempio n. 19
0
	elif args.command == "send-to-sidechain":
		cht = os.popen("%s %s -g -r %s -d %s" % (contracthashtool_path, testnet_arg, redeem_script, args.p2shSideAddress))
		cht_read = cht.read()
		nonce = cht_read.split("\n")[0 + is_testnet][7:]
		full_contract = cht_read.split("\n")[1 + is_testnet][26:]
		send_address = cht_read.split("\n")[3 + is_testnet][40:]
		assert(cht.close() == None)
		if full_contract[0:8] != "50325348":
			print("You must use a P2SH address")
			exit(1)

		print("Sending %s to %s..." % (args.coinAmt, send_address))
		print("(nonce: %s)" % nonce)

		try:
			tx_hex = bitcoin.createrawtransaction([], {send_address: Decimal(args.coinAmt)})
			tx_hex = bitcoin.fundrawtransaction(tx_hex)['hex']
			tx = bitcoin.signrawtransaction(tx_hex)
			assert(tx['complete'])

			tx_hex = tx['hex']

			total_length  = len(tx_hex)/2
			total_length += 14*32 # maximum length of spv proof 1MB blocks
			total_length += 1000 # len(full_contract) + len(secondScriptPubKey) and rounded up to 1000

			if total_length >= 10000:
				print("Transaction is too large.")
				exit(1)

			txid = bitcoin.sendrawtransaction(tx_hex)
Esempio n. 20
0
print("Vector ID of Output: ", utxo_vout)
print("UTXO Amount........: ", utxo_amt)
print("Tx Amount..........: ", recipient_amt)
print("Recipient Address..: ", recipient_address)
print("Change Address.....: ", change_address)
print("Miner Fee..........: ", miner_fee)
print("Change Amount......: ", change_amt)
print("---------------------------------------------------------------\n")

## 2. Create Raw Transaction
txids_vouts = [{"txid": utxo_txid, "vout": utxo_vout}]
addresses_amts = {
    f"{recipient_address}": recipient_amt,
    f"{change_address}": change_amt
}
unsigned_tx_hex = rpc_client.createrawtransaction(txids_vouts, addresses_amts)
print("---------------------------------------------------------------")
print("Unsigned Transaction Hex: ", unsigned_tx_hex)
print("---------------------------------------------------------------\n")

## 3. Sign Raw Transaction
address_priv_key = []  # list of priv keys of each utxo
address_priv_key.append(rpc_client.dumpprivkey(utxo_address))
signed_tx = rpc_client.signrawtransactionwithkey(unsigned_tx_hex,
                                                 address_priv_key)
print("---------------------------------------------------------------")
print("Signed Transaction: ")
print("----------------------")
pprint(signed_tx)
print("---------------------------------------------------------------\n")
Esempio n. 21
0
    def check_for_stake(self, RPC, log):
        try:
            rpc_connection = AuthServiceProxy("http://%s:%[email protected]:%s"%(RPC['user'], RPC['pw'], RPC['port']))
            # Check integrity of wallet before getting wallet info
            check_wallet = rpc_connection.checkwallet()
        except:
            return "Unable to connect to wallet. Verify that it's running and your RPC settings are correct"

        if 'wallet check passed' not in check_wallet:
            log.info(check_wallet)
            rpc_connection.repairwallet()
            log.info("**Wallet was repaired**")

        try:
            txs = rpc_connection.listunspent(int(RPC['min_conf']), int(RPC['max_conf'])) # Only work with inputs that aren't mature
        except:
            return "Unable to run 'listunspent' over RPC, check that the wallet is still running"
        input_sum = 0
        utxo_size = Decimal(RPC['UTXO_size'])
        input_tx = []
        addresses_to_reuse = []
        for each_tx in txs:
            # Check out each existing transaction for desired size, sum up inputs that aren't
            if each_tx['amount'] != utxo_size:
                input_sum += each_tx['amount']
                input_tx.append({"txid":each_tx['txid'],"vout":each_tx['vout']})
                if 'account' in each_tx and each_tx['account'] == 'stake_script' and each_tx['address'] not in addresses_to_reuse:
                    # reuse input addresses for a new output if they have the label 'stake_script'
                    addresses_to_reuse.append(each_tx['address'])

        if input_sum < utxo_size:
            log.debug("DEBUG: Total coins: {0} is not enough to make a new packet of {1}".format(input_sum, utxo_size))
            return "Total coins: {0} is not enough to make a new packet of {1} :DEBUG".format(input_sum, utxo_size)

        # Reuse or make a new change and stake addresses
        change_address = rpc_connection.getaddressesbyaccount("change")
        if len(change_address) == 0:
            change_address = [rpc_connection.getnewaddress("change")]
        stake_addresses = rpc_connection.getaddressesbyaccount("stake_script")
        for addr in stake_addresses:
            amount = rpc_connection.getreceivedbyaddress(addr)
            if amount == 0 and addr not in addresses_to_reuse:
                # Only reuse addresses with the label stake_script and zero balance for safety
                addresses_to_reuse.append(addr)

        output_addresses = {}
        number_of_splits = int(input_sum / utxo_size)
        if len(addresses_to_reuse) < number_of_splits:
            # Make as many new addresses as needed to split inputs into 'size' outputs
            num_to_make = number_of_splits - len(addresses_to_reuse)
            #if not arg.noconfirm:
                # TODO implement
            #    print("About to make {0} new stake address(es), confirm".format(num_to_make))
            #    get_permission()
            for _ in range(num_to_make):
                addresses_to_reuse.append(rpc_connection.getnewaddress('stake_script'))

        for _ in range(number_of_splits):
            output_addresses[addresses_to_reuse.pop()] = utxo_size

        #print(output_addresses)
        assert(int(input_sum / utxo_size) == len(output_addresses)), "Not enough output addresses for number of UTXO splits!"

        number_of_splits = len(output_addresses)
        numbytes = 181 * len(input_tx) + 34* (number_of_splits+1) + 10
        numKB = math.ceil(numbytes / 1000)
        TX_FEE = Decimal(RPC['transaction_fee']) * numKB
        log.debug("transaction fee is %d : %d bytes, fee multiple is %d"%(TX_FEE, numbytes,numKB))

        change_amount = input_sum - (utxo_size * number_of_splits) - TX_FEE
        output_addresses[change_address[0]] = change_amount
        assert (change_amount > 0), "Change amount cannot be less than zero"
        assert(change_amount + TX_FEE + (utxo_size*number_of_splits) == input_sum), "Coins will be lost if the total output != input"

        log.debug("{0} Inputs {1}".format(len(input_tx),input_tx))
        log.debug("{0} Outputs {1}".format(len(output_addresses), output_addresses))
        log.info("{0} (Input total) = {2} ({1}_UTXO packets) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE))

        # Generate, sign, and send the raw transaction
        raw_tx = rpc_connection.createrawtransaction(input_tx, output_addresses)
        signed_tx = rpc_connection.signrawtransaction(raw_tx)
        if not signed_tx['complete']:
            log.error("Signing failed of raw tranaction: {0}\nInputs: {1}\nOutputs: {2}".format(raw_tx, input_tx, output_addresses))
            return "Signing of raw transaction did not complete successfully, make sure wallet is functioning properly"

        #if not arg.noconfirm:
        #    print("About to send transaction, confirm")
        #    get_permission()

        log.info("Attempting to send: {0} (Total inputs) = {2} ({1} new UTXO) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE))
        try:
            sent = rpc_connection.sendrawtransaction(signed_tx['hex'])
        except Exception as e:
            return "Sending transaction failed (Your wallet might need more time to update): {0}".format(str(e))
        log.info("TX successful: transaction ID: {0}".format(sent))
        now = datetime.datetime.now().strftime("%m-%d %H:%M")
        return "{6} TX {5} successful: {0} (Total inputs) = {2} ({1} new UTXO) + {3} (change) + {4} (fee)".format(input_sum,number_of_splits,utxo_size*number_of_splits,change_amount, TX_FEE, sent, now)
Esempio n. 22
0
def generate_valid_source_tx(
        s: protocol.State,
        con: AuthServiceProxy,
        max_tx: int
    ) -> None:
    # Transmit enough funds to addresses so that we won't need
    # to use coinbase transactions.
    # There are at most MAX many transactions in one step. Hence,
    # we need at most that many different addresses. (We can always
    # use the change addresses because our transactions have nearly
    # no costs)

    num_addr = max_tx // 10  # We want at most 50 advertisements to use the
    # same address
    s.source_tx = []

    start = con.getblockcount() + 1
    con.generate(num_addr + 101)
    top = con.getblockcount()

    interval = range(start, top - 100)
    block_hashes = con.batch_([["getblockhash", h] for h in interval])
    blocks = con.batch_([["getblock", ha, 2] for ha in block_hashes])
    del block_hashes
    txs = [block['tx'][0] for block in blocks]
    del blocks

    sent_txs = []
    i = 0
    value = -1
    txid = -1
    n = -1
    for tx in txs:
        for out in tx['vout']:
            if out['scriptPubKey']['type'] == 'pubkey':
                # The pubkey transactions are coinbase transactions because
                value = out['value']
                txid = tx['txid']
                n = out['n']
        if value == -1 or txid == -1 or n == -1:
            raise RuntimeError("No coinbase transaction found.")
        addr = con.getnewaddress()
        sent_value = float(value) / 2  # create two addresses per transaction
        raw_tx = con.createrawtransaction([{'txid': txid, 'vout': n}], {
            addr: sent_value})  # The - is for the fees
        funded_tx = con.fundrawtransaction(raw_tx)
        signed_tx = con.signrawtransactionwithwallet(funded_tx["hex"])
        if signed_tx["complete"] is False:
            raise RuntimeError(
                "bitcoind could not sign the transaction. (During "
                "Initialization)")
        txid = con.sendrawtransaction(signed_tx["hex"])
        sent_txs.append(txid)

        i += 1

        # Create a block each 100 transactions
        if i == 100:
            con.generate(1)
            i = 0

    con.generate(1)

    txs = con.batch_([['getrawtransaction', txid, 1] for txid in sent_txs])
    for tx in txs:
        for out in tx['vout']:
            vout = out['n']
            s.source_tx.append(opreturn.Transaction(tx['txid'], vout))
    c = 0
    for utxo in s.source_tx:
        if not protocol.is_valid_utxo(utxo):
            c += 1
    print("Found %d invalid utxos." % c)
 else:
     print
     
     SendAddress = str(raw_input('发送到哪个地址? (例如33hxAeUqNnFs3gdayu7aAaijhTbbfnphq8) ')) 
     if SendAddress == "33hxAeUqNnFs3gdayu7aAaijhTbbfnphq8":
         print "太感谢了,你选择捐赠给johnson Diao"
     print
     Leftover = int(unspent[WhichTrans]["amount"]*100000000)-HowMuch-SetTxFee
     print "将要发送您的比特币到这个地址:",SendAddress,"账户里会留下来 ", Leftover," 聪",",这些币会发送到找零地址:",ChangeAddress
     print "会发送 ",SetTxFee," 聪的网络手续费给矿工"
     print
     print "将要创建发送单"
     
     
     rawtransact = bitcoin.createrawtransaction ([{"txid":unspent[WhichTrans]["txid"],
             "vout":unspent[WhichTrans]["vout"],
             "scriptPubKey":unspent[WhichTrans]["scriptPubKey"],
             "redeemScript":unspent[WhichTrans]["redeemScript"]}],{SendAddress:HowMuch/100000000.00,ChangeAddress:Leftover/100000000.00})
     print "发送单为:", rawtransact
     print
     print
     print "现在我们要用私钥进行签名"
     multisigprivkeyone = str(raw_input("请输入第一个私钥:"))
     print
     signedone = bitcoin.signrawtransaction (rawtransact,
             [{"txid":unspent[WhichTrans]["txid"],
             "vout":unspent[WhichTrans]["vout"],"scriptPubKey":unspent[WhichTrans]["scriptPubKey"],
             "redeemScript":unspent[WhichTrans]["redeemScript"]}],
             [multisigprivkeyone])
     print "签名结果"
     print signedone
     print
Esempio n. 24
0
    fee_rate = get_fee_rate()
elif fee_type == "conf_target":
    conf_target = get_conf_target()

# TODO: use a higher amount for pure name transactions?
name_amount = Decimal("0.01")
print("Name amount is ", name_amount, "NMC")

coin_control_enabled, name_new_vin = get_coin_control_inputs()

# TODO: find another way to set the label that doesn't use deprecated "account" field?
name_new_address = rpc_connection.getnewaddress("Name: " + name_to_register)
name_new_vout = {name_new_address: name_amount}

# TODO: set locktime and/or replaceable?
name_new_create = rpc_connection.createrawtransaction(name_new_vin,
                                                      name_new_vout)

print("name_new create:", rpc_connection.decoderawtransaction(name_new_create))

name_new_name_index = rawtx_output_index(name_new_create, name_new_address)

print("name_new_name_index:", name_new_name_index)

name_new_op = {
    "op": "name_new",
    "name": name_to_register,
}

name_new_with_name = rpc_connection.namerawtransaction(name_new_create,
                                                       name_new_name_index,
                                                       name_new_op)
Esempio n. 25
0
                       (contracthashtool_path, testnet_arg, redeem_script,
                        args.p2shSideAddress))
        cht_read = cht.read()
        nonce = cht_read.split("\n")[0 + is_testnet][7:]
        full_contract = cht_read.split("\n")[1 + is_testnet][26:]
        send_address = cht_read.split("\n")[3 + is_testnet][40:]
        assert (cht.close() == None)
        if full_contract[0:8] != "50325348":
            print("You must use a P2SH address")
            exit(1)

        print("Sending %s to %s..." % (args.coinAmt, send_address))
        print("(nonce: %s)" % nonce)

        try:
            tx_hex = bitcoin.createrawtransaction(
                [], {send_address: Decimal(args.coinAmt)})
            tx_hex = bitcoin.fundrawtransaction(tx_hex)['hex']
            tx = bitcoin.signrawtransaction(tx_hex)
            assert (tx['complete'])

            tx_hex = tx['hex']

            total_length = len(tx_hex) / 2
            total_length += 14 * 32  # maximum length of spv proof 1MB blocks
            total_length += 1000  # len(full_contract) + len(secondScriptPubKey) and rounded up to 1000

            if total_length >= 10000:
                print("Transaction is too large.")
                exit(1)

            txid = bitcoin.sendrawtransaction(tx_hex)
Esempio n. 26
0
print("Vector ID of Output: ", utxo_vout)
print("UTXO Amount........: ", utxo_amt)
print("Tx Amount..........: ", recipient_amt)
print("Recipient Address..: ", recipient_address)
print("Change Address.....: ", change_address)
print("Miner Fee..........: ", miner_fee)
print("Change Amount......: ", change_amt)
print("---------------------------------------------------------------\n")

## create a raw transacion
txids_vouts = [{"txid": utxo_txid, "vout": utxo_vout}]
addresses_amts = {
    f"{recipient_address}": recipient_amt,
    f"{change_address}": change_amt
}
create_raw_tx = rpc_client.createrawtransaction(txids_vouts, addresses_amts)
unsigned_tx_hex = create_raw_tx
print("---------------------------------------------------------------")
print("Unsigned Transaction Hex: ", unsigned_tx_hex)
print("---------------------------------------------------------------\n")

## Check details of the Transaction
tx_details = rpc_client.decoderawtransaction(unsigned_tx_hex)
print("---------------------------------------------------------------")
print("New Transaction Details:")
print("-----------------------")
pprint(tx_details)
print("---------------------------------------------------------------\n")

## Sign Transanciton
address_priv_key = []  # list of priv keys of each utxo
Esempio n. 27
0
data = "@rusticbison"

if len(data) > 75:
    print("Data length is {}".format(len(data)))
    raise Exception("Too much data, use OP_PUSHDATA1 instead")

hex_format_data = binascii.hexlify(data)

print(hex_format_data)

hexstring = rpc_connection.createrawtransaction(
    [{
        "txid": txid,
        "vout": vout
    }], {
        "data": hex_format_data,
        new_bitcoin_address: send_amount_string,
        raw_change_address: change_amount_string
    })

print("=" * 20)
print(hexstring)
print("-" * 20)

print("address ==>%s" % address)
privkey = rpc_connection.dumpprivkey(address)
print("/" * 20)

sign_raw_transaction = rpc_connection.signrawtransaction(
    hexstring, [{
Esempio n. 28
0
for u in allUnspent:
    inputsList.append({
        "txid": u["txid"],
        "vout": u["vout"],
        "address": changeAddress
    })
    inputsWithScriptKeysList.append({
        "txid": u["txid"],
        "vout": u["vout"],
        "scriptPubKey": u["scriptPubKey"]
    })

# createrawtransaction [{"txid":txid,"vout":n},...] {address:amount,...}
print()
logger.info("Creating tx hash going to address {}...".format(toAddresses))
createTxHex = rpcConnection.createrawtransaction(inputsList, toAddresses)
createTxJson = rpcConnection.decoderawtransaction(createTxHex)
if len(createTxHex.strip()) > 0:
    # pprint(rpcConnection.decodescript(createTxHex));
    # pprint(rpcConnection.decoderawtransaction(createTxHex));
    createTxID = createTxJson["txid"]
    logger.info(
        "TX was successfulling created. TxID is: {}".format(createTxID))
else:
    logger.error("Failed to create tx. Aborting.")
    exit()

# signrawtransaction <hex string> [{"txid":txid,"vout":n,"scriptPubKey":hex,"redeemScript":hex},...] [<privatekey1>,...] [sighashtype="ALL"]
print()
logger.info("Signing tx...")
signTxResult = rpcConnection.signrawtransaction(createTxHex,
Esempio n. 29
0
class BtcWallet():
    """btc钱包"""
    BTC_BLOCK_API = 'https://blockchain.info/'

    def __init__(self, app=None, consul_client=None):
        if app and consul_client:
            self.init_consul(app, consul_client)

    def init_consul(self, app, consul_client):
        try:
            rpc_user = app.config.get('CONFIG_BITCOIND_RPC_USER')
            rpc_pwd = app.config.get('CONFIG_BITCOIND_RPC_PASSWORD')
            wallet_passphrase = app.config.get('CONFIG_BITCOIND_WALLET_PASSWORD')
            self.ipport = consul_client.getRandomOneAvailableServiceIpPort(ConsulServiceName.BTC_CLI)
            # s = "http://%s:%s@" % (self.user, self.pwd) + self.ipport
            # print(s)

            self.bitcoin_cli = AuthServiceProxy(
                "http://%s:%s@" % (rpc_user, rpc_pwd) + self.ipport, timeout=10)
            print("Succeed to connect to the BTC node")

        except Exception as e:
            print(str(e))
            print("Failed to connect to the BTC node")

    # 是否连接BTC节点
    def is_connected(self):
        try:
            if self.bitcoin_cli.getwalletinfo().get('walletversion'):
                return True
            return False
        except Exception as e:
            print(str(e))
            print("Failed to connect to the BTC node")

    # 节点是否同步
    def is_sync(self):
        ret = self.bitcoin_cli.getblockchaininfo()
        if ret.get('blocks') != ret.get("headers"):
            return False
        else:
            return True

    # btc地址是否有效
    def is_valid_address(self, coin_address):
        if coin_address is None or coin_address == '':
            return False
        else:
            ret = self.bitcoin_cli.validateaddress(coin_address).get('isvalid')
            print('账户检查结果:', ret)
            return ret

            # return self.bitcoin_cli.validateaddress(coin_address).get('isvalid')

    # 获取账户余额, 默认经过6个区块确认
    def get_balance(self, coin_address):

        transaction_lists = self.bitcoin_cli.listunspent(1, 99999999, [coin_address])
        print(transaction_lists)
        current_amount = 0
        for transaction_list in transaction_lists:
            amount = transaction_list.get('amount')
            amount = float(amount)
            current_amount += amount
        return current_amount

    def get_balance_by_account(self, account):
        try:
            ret = self.bitcoin_cli.getbalance(account)
            return ret
        except Exception as e:
            logging.error('get balance error:{}'.format(str(e)))
            return None


    def estimate_fee(self):
        try:
            fee = self.bitcoin_cli.estimatefee(6)
            return fee
        except Exception as e:
            logging.error('get fee error:{}'.format(str(e)))
            return None

    def create_account(self, stellar_account):
        # private = random_key()
        # address = pubtoaddr(privtopub(private))
        # print(address, private)
        # return address, private
        address = self.bitcoin_cli.getnewaddress(stellar_account)
        private_key = self.bitcoin_cli.dumpprivkey(address)
        return address, private_key

    def get_block_num(self):
        """获取最新区块数"""
        try:
            block_num = self.bitcoin_cli.getblockcount()
            return block_num
        except Exception as e:
            logging.error('Get btc node block number error:{}'.format(str(e)))
            return None


    def get_chain_info(self):
        ret = self.bitcoin_cli.getblockchaininfo()
        return ret

    def get_block_info(self, block_num):
        """获取区块的详细信息"""
        param = "block-height/{}?format=json".format(block_num)
        api_url = self.BTC_BLOCK_API + param
        # print(api_url)

        blocks = requests.get(api_url, timeout=500).json()
        # print(type(blocks))
        return blocks

    # 链外转帐,普通交易
    def payment(self, btc_base_account, address_to, amount):
        try:
            txid = self.bitcoin_cli.sendfrom(btc_base_account, address_to, amount)
            return True, txid
        except Exception as e:
            logging.error('btc payment error:{}'.format(str(e)))
            return False, str(e)

    def hash_get_detail(self, tx_id):
        """
        Arguments:
        1. "txid" (string, required) The transaction id
        """
        # 根据txid获取确认链外交易信息
        ret = self.bitcoin_cli.gettransaction(tx_id)
        abandoned = ret.get("details")[0].get("abandoned")  # 获取abandon信息
        confirmation_num = ret.get('confirmations')  # 获取确认数

        # 如果确认数小于1,则未确认
        if confirmation_num < 1:
            msg = dict(confirm=str(ret))
            # msg = ret.get("details")[0]
            return False, False, msg, None
        # 如果确认数大于1,则确认
        else:
            msg = dict(confirm=str(ret))
            # msg = ret
            fee = abs(ret.get("fee"))
            if abandoned:
                return True, False, msg, None
            else:
                return True, True, msg, fee

    def raw_payment(self, address_from, address_to, collect_amount):
        inputs = []
        # 获取地址余额信息
        try:
            unspend_lists = self.bitcoin_cli.listunspent(1, 9999999, [address_from])
            for unspend_list in unspend_lists:
                # if unspend_list.get('amount') <= 0:
                #     continue
                # else:
                txid = unspend_list.get('txid')
                vout = unspend_list.get('vout')
                inputs.append({'txid': txid, 'vout': vout})

            outputs = {address_to: round(collect_amount, 8)}

            # 交易建立和签名时不用连接比特币网络,只有在执行交易时才需要将交易发送到网络
            # 创建裸交易
            transaction_hash = self.bitcoin_cli.createrawtransaction(inputs, outputs)

            # 使用私钥签名,获取16进制信息
            hex = self.bitcoin_cli.signrawtransaction(transaction_hash).get('hex')

            # 广播到p2p网络,返回交易哈希
            trading_hash = self.bitcoin_cli.sendrawtransaction(hex, False)

            return True, trading_hash, ''
        except Exception as e:
            print(e)
            return None, None, ''

    def btc_transaction_record(self, block_num):
        # 获取某一区块信息
        block_info = self.get_block_info(block_num)
        blocks = block_info.get('blocks')
        txs = blocks[0].get('tx')
        records = []
        for tx in txs:
            outs = tx.get('out')
            hash = tx.get('hash')
            inputs = tx.get('inputs')
            p_out = inputs[0].get('prev_out')
            if not p_out:
                continue
            else:
                addr_from = p_out.get('addr')
            for out in outs:
                re = []
                addr_to = out.get('addr')
                value = out.get('value') / (10 ** 8)
                # addr_to与User表中绑定的地址进行对比,如果有,则说明此address_to有冲币记录
                user = User.address_query_user('BTC', addr_to)
                if not user:
                    continue
                else:
                    re.append(addr_from)
                    re.append(addr_to)
                    re.append(value)
                    re.append(hash)
                    records.append(re)
        return records

    def get_accounts(self, addr):
        try:
            ad = self.bitcoin_cli.getaccount(addr)
            return ad
        except Exception as e:
            # logging.error('get btc_account error:{}'.format(str(e)))
            return None

    def get_address_byaccount(self, account):
        re = self.bitcoin_cli.getaddressesbyaccount(account)

        return re

    def test1(self):

        transaction_list = self.bitcoin_cli.listaccounts()
        # transaction_list = self.bitcoin_cli.getwalletinfo()
        print(transaction_list)
Esempio n. 30
0
SATOSHI = Decimal("0.00000001")
change_amount = input_amount - Decimal("0.005") - SATOSHI
# Marker address we're going to replace
# Produces a pattern that's easy to search for
mainnet = 0
if mainnet:
    dummy_address = "1111111111111111111114oLvT2"
else:
    dummy_address = "mfWxJ45yp2SFn7UciZyNpvDKrzbhyfKrY8"

# My change address
change_address = "mhZuYnuMCZLjZKeDMnY48xsR5qkjq7bAr9"


tx = rpc.createrawtransaction([{"txid": txid, "vout": vout}], \
                              {change_address: change_amount, \
                               dummy_address: SATOSHI})

# Pattern to replace
# Represents length of script, then OP_DUP OP_HASH160,
# then length of hash, then 20 bytes of zeros, OP_EQUALVERIFY OP_CHECKSIG
oldScriptPubKey = "1976a914000000000000000000000000000000000000000088ac"

# Data to insert
data = "Melons."
if len(data) > 75:
    raise Exception("Can't contain this much data-use OP_PUSHDATA1")

newScriptPubKey = "6a" + hexlify(chr(len(data))) + hexlify(data)

#Append int of length to start
Esempio n. 31
0
# Create outputs
my_addr = utxo["address"]
change = input_value - burn_amount - fee
op_return = payment_details.outputs[0].script[2:].hex()
outputs = [
    {
        "data": op_return
    },
    {
        my_addr: change  # Change output
    }
]

# Create tx
raw_tx_unsigned = rpc_connection.createrawtransaction(inputs, outputs)
signed_tx = rpc_connection.signrawtransactionwithwallet(raw_tx_unsigned)
signed_raw_tx = bytes.fromhex(signed_tx["hex"])

# Construct payment message
payment = Payment(merchant_data=payment_details.merchant_data,
                  transactions=[signed_raw_tx])
payment_raw = payment.SerializeToString()
print("Sending Payment...")

# Send payment
payment_url = BASE_URL_A + payment_details.payment_url
headers = {
    "Content-Type": "application/bitcoincash-payment",
    "Accept": "application/bitcoincash-paymentack"
}
Esempio n. 32
0
class RawTxn:
    def __init__(self, rpc_user, rpc_password, rpc_port,
                 transfer_info_filepath: str, label: str):
        global network_port_map_g
        #self.rpc_connection = rpc_connection
        self.transfer_info_filepath = transfer_info_filepath
        #                print('rpc_user = %s' % rpc_user)
        #                print('rpc_password = %s' % rpc_password)
        #                print('rpc_port = %d' % rpc_port)
        self.rpc_connection = AuthServiceProxy(
            "http://%s:%[email protected]:%d" % (rpc_user, rpc_password, rpc_port))
        self.inuseAddressMap = None
        self.label = label

    def getInputsForAddress(self, address: str):
        inputs = []

        #                print('address = %s' % address)

        if self.inuseAddressMap == None:
            unspent_list = [
                unspent for unspent in self.rpc_connection.listunspent()
                if unspent['label'] == self.label
            ]
            self.setInuseAddressMap(unspent_list)

#                print('inuse_address_map[%s] = %s' % (address, self.inuse_address_map[address]))

        for txn in self.inuse_address_map[address]:
            #                        print('txn = %s' % txn)
            for vout_amount_map in self.inuse_address_map[address][txn]:
                value = vout_amount_map['amount']
                out_index = vout_amount_map['vout']
                inputs.append({
                    'txid': txn,
                    'vout': out_index,
                    'address': address,
                    'value': value
                })

        return inputs

    def setInuseAddressMap(self, unspent_list: list):
        self.inuse_address_map = {}
        for unspent in unspent_list:
            address = unspent['address']
            if address not in self.inuse_address_map:
                self.inuse_address_map[address] = {}
            txid = unspent['txid']
            if txid not in self.inuse_address_map[address]:
                self.inuse_address_map[address][txid] = []
            vout = unspent['vout']
            amount = unspent['amount']
            self.inuse_address_map[address][txid].append({
                'vout':
                vout,
                'amount':
                float(amount)
            })

    def getNetworkInfo(self):
        networkinfo = self.rpc_connection.getnetworkinfo()
        network_client, version = networkinfo['subversion'].split(
            '/')[1].split(':')
        if network_client == 'Satoshi':
            network = 'bitcoin'
            print('Network = bitcoin')
        elif network_client == 'LitecoinCore':
            network = litecoin
            print('Network = litecoin')
        else:
            print('Network client: %s is not supported' % network_client)
            exit()
        return network, version

    def checkAddressIsReused(self, address: str, network):
        if network == 'bitcoin':
            res = requests.get('https://blockchain.info/rawaddr/' + address)
            jsonobj = json.loads(res.text)
            return (jsonobj['total_sent'] != 0)
        elif network == 'litecoin':
            res = requests.get('https://chain.so/api/v2/address/LTC/' +
                               address)
            jsonobj = json.loads(res.text)
            return (jsonobj['data']['received_value'] !=
                    jsonobj['data']['balance'])
        else:
            print('Network client: %s is not supported' % network_client)
            exit()

    def getInputs(self, amount: float):
        global inuse_address_value_map_g

        #                print('********** target value = %f' % amount)

        if len(inuse_address_value_map_g) == 0:
            unspent_list = [
                unspent for unspent in self.rpc_connection.listunspent()
                if unspent['label'] == self.label
            ]
            self.setInuseAddressMap(unspent_list)

            #                        print('Inuse addresses are 0')
            setInuseAddressValueMap(self.inuse_address_map)

#                print('************* inuse_address_value_map = %s' % inuse_address_value_map_g)

        inputs = []
        value = 0
        address_value_map = [{
            'address': address,
            'amount': address_value
        } for address, address_value in inuse_address_value_map_g.items()]
        network, _ = self.getNetworkInfo()

        allocated_address_value_map = []
        for address_value in address_value_map:
            if self.checkAddressIsReused(address_value['address'],
                                         network) == True:
                allocated_address_value_map.append(address_value)
                amount = amount - address_value['amount']
                address_inputs = self.getInputsForAddress(
                    address_value['address'])
                inputs.extend(address_inputs)

        for allocated_address_value in allocated_address_value_map:
            address_value_map.remove(allocated_address_value)
        address_value_map = sorted(address_value_map,
                                   key=lambda k: k['amount'])
        #                print('sorted address value map = %s' % address_value_map)
        if amount > 0:
            remaining_amount = amount
            for address_value in address_value_map:
                if address_value['amount'] < remaining_amount:
                    address_inputs = self.getInputsForAddress(
                        address_value['address'])
                    inputs.extend(address_inputs)
                    remaining_amount -= address_value['amount']
                else:
                    address_inputs = self.getInputsForAddress(
                        address_value_map[-1]['address'])
                    inputs.extend(address_inputs)
                    remaining_amount -= address_value['amount']
                    break

            if remaining_amount > 0:
                print('Error: Insufficient Balance')
                return None

#                print('inputs = %s' % inputs)
        return inputs

    def getInputsForAddressList(self, address_list: list):
        inputs = []
        for address in address_list:
            address_inputs = self.getInputsForAddress(address)
            inputs.extend(address_inputs)

#                print('inputs = %s' % inputs)
        return inputs

    def getAmountFromInputs(self, inputs: list):
        reduce(lambda x, y: x + y, [inp[amount] for inp in inputs])

    def estimatefee(self, raw_txn: bytes, fee_rate: float):

        vbytes = calculateVBytes(raw_txn)

        #                print('vbytes = %f' % vbytes)

        estimated_fee = round(fee_rate * (vbytes / 1000), 8)

        #                print('vbytes = %f' % vbytes)
        #                print('estimated_fee = %f' % estimated_fee)

        return vbytes, estimated_fee

#        def getRawTransaction(self, inputs: list, outs: list, change_address: str, fee_rate: float, jsonobj: dict):
##                print('fee_rate = %f' % fee_rate)
#
#                tx_ins = [{'txid': inp['txid'], 'vout': inp['vout']} for inp in inputs]
#
#                # first get raw transaction without change
##                print('111111111: tx_ins = %s, outs = %s' % (tx_ins, outs))
#                raw_txn = self.rpc_connection.createrawtransaction(tx_ins, outs)
#
#                vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn), fee_rate)
#                target_value = getTargetValue(outs)
#                #target_addresses = list(outs)
#
#                input_value = getInputValue(inputs)
#
#                change_value = round(input_value - target_value - estimated_fee, 8)
#
#                # if change_value is not 0 then estimated_fee and change_value are wrong
#                if change_value == 0:
#                        jsonobj['Raw Txn'] = raw_txn
#                        jsonobj['Inputs'] = inputs
#
#                        return jsonobj
#
#                new_outs = deepcopy(outs)
#                new_outs.append({change_address: round(change_value, 8)})
##                print('2222222222: tx_ins = %s, new_outs = %s' % (tx_ins, new_outs))
##                print('estimated_fee = %f' % estimated_fee)
#                raw_txn = self.rpc_connection.createrawtransaction(tx_ins, new_outs)
#                vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn), fee_rate)
#                change_value = round(input_value - target_value - estimated_fee, 8)
#                while change_value < 0:
#                        inputs = self.getInputs(round(target_value + estimated_fee, 8))
#                        tx_ins = [{'txid': inp['txid'], 'vout': inp['vout']} for inp in inputs]
##                        print('33333333333: tx_ins = %s, outs = %s' % (tx_ins, outs))
##                        print('estimated_fee = %f' % estimated_fee)
#                        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, new_outs)
#                        vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn), fee_rate)
#                        input_value = getInputValue(inputs)
#
#                        change_value = round(input_value - target_value - estimated_fee, 8)
#                new_outs = deepcopy(outs)
#                new_outs.append({change_address: round(change_value, 8)})
##                print('44444444444444: tx_ins = %s, new_outs = %s' % (tx_ins, new_outs))
##                print('estimated_fee = %f' % estimated_fee)
#                raw_txn = self.rpc_connection.createrawtransaction(tx_ins, new_outs)
##                print('raw txn = %s' % raw_txn)
#
#                jsonobj['Raw Txn'] = raw_txn
#                jsonobj['Inputs'] = inputs
#                jsonobj['VBytes'] = vbytes
#
#                return jsonobj

    def getRawTransaction(self, inputs: list, outs: dict, change_address: str,
                          fee_rate: float, jsonobj: dict):
        #                print('fee_rate = %f' % fee_rate)

        tx_ins = [{'txid': inp['txid'], 'vout': inp['vout']} for inp in inputs]

        # first get raw transaction without change
        #                print('111111111: tx_ins = %s, outs = %s' % (tx_ins, outs))
        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, outs)

        vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn),
                                                 fee_rate)
        target_value = getTargetValue(outs)
        #target_addresses = list(outs)

        input_value = getInputValue(inputs)

        change_value = round(input_value - target_value - estimated_fee, 8)

        # if change_value is not 0 then estimated_fee and change_value are wrong
        if change_value == 0:
            jsonobj['Raw Txn'] = raw_txn
            jsonobj['Inputs'] = inputs

            return jsonobj

        new_outs = deepcopy(outs)
        new_outs[change_address] = round(change_value, 8)
        #                print('2222222222: tx_ins = %s, new_outs = %s' % (tx_ins, new_outs))
        #                print('estimated_fee = %f' % estimated_fee)
        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, new_outs)
        vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn),
                                                 fee_rate)
        change_value = round(input_value - target_value - estimated_fee, 8)
        while change_value < 0:
            inputs = self.getInputs(round(target_value + estimated_fee, 8))
            tx_ins = [{
                'txid': inp['txid'],
                'vout': inp['vout']
            } for inp in inputs]
            #                        print('33333333333: tx_ins = %s, outs = %s' % (tx_ins, outs))
            #                        print('estimated_fee = %f' % estimated_fee)
            raw_txn = self.rpc_connection.createrawtransaction(
                tx_ins, new_outs)
            vbytes, estimated_fee = self.estimatefee(
                binascii.unhexlify(raw_txn), fee_rate)
            input_value = getInputValue(inputs)

            change_value = round(input_value - target_value - estimated_fee, 8)
        new_outs = deepcopy(outs)
        new_outs[change_address] = round(change_value, 8)
        #                print('44444444444444: tx_ins = %s, new_outs = %s' % (tx_ins, new_outs))
        #                print('estimated_fee = %f' % estimated_fee)
        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, new_outs)
        #                print('raw txn = %s' % raw_txn)

        jsonobj['Raw Txn'] = raw_txn
        jsonobj['Inputs'] = inputs
        jsonobj['VBytes'] = vbytes

        return jsonobj

#        def getRawTxnFromOuts(self, txout: list, change_address: str, fee_rate: float, jsonobj: dict):
#                target_value = getTargetValue(txout)
#                inputs = self.getInputs(target_value)
#                return self.getRawTransaction(inputs, txout, change_address, fee_rate, jsonobj)

    def getRawTxnFromOuts(self, txout: dict, change_address: str,
                          fee_rate: float, jsonobj: dict):
        target_value = getTargetValue(txout)
        inputs = self.getInputs(target_value)
        return self.getRawTransaction(inputs, txout, change_address, fee_rate,
                                      jsonobj)

    def getRawTxnToDivideFunds(self, input_addresses: list,
                               out_addresses: list, fee_rate: float,
                               jsonobj: dict):
        #                print('fee_rate = %f' % fee_rate)

        inputs = self.getInputsForAddressList(input_addresses)
        input_value = getInputValue(inputs)

        each_out_value = round(input_value / len(out_addresses), 8)

        outs = dict([(address, each_out_value) for address in out_addresses])

        tx_ins = [{'txid': inp['txid'], 'vout': inp['vout']} for inp in inputs]

        # first get raw transaction without change
        #                print('111111111: tx_ins = %s, outs = %s' % (tx_ins, outs))
        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, outs)

        vbytes, estimated_fee = self.estimatefee(binascii.unhexlify(raw_txn),
                                                 fee_rate)
        each_out_value = round(
            (input_value - estimated_fee) / len(out_addresses), 8)
        outs = dict([(address, each_out_value) for address in out_addresses])

        # second get raw transaction without change
        #                print('22222222: tx_ins = %s, outs = %s' % (tx_ins, outs))
        raw_txn = self.rpc_connection.createrawtransaction(tx_ins, outs)
        #                print('raw txn = %s' % raw_txn)

        jsonobj['Raw Txn'] = raw_txn
        jsonobj['Inputs'] = inputs
        jsonobj['VBytes'] = vbytes

        return jsonobj
Esempio n. 33
0
total_in = 0;

unspent.sort (key=lambda coin: abs(to_satoshi (coin['amount']) - target_in));

for coin in unspent:
  total_in += to_satoshi (coin['amount']);
  donation += donation_per_input;
  inputs.append (dict (txid = coin['txid'], vout = coin['vout']));
  if total_in > target_in:
    break;

if donation < donation_minimum:
  donation = donation_minimum;

# FIND OUTPUTS
outputs = dict ();
outputs[donation_address] = from_satoshi (donation);
total_in -= donation;
while total_in > target_out:
  outputs[service.getnewaddress()] = from_satoshi (target_out);
  total_in -= target_out;
outputs[service.getnewaddress()] = from_satoshi (total_in);

# Make the transaction
print service.createrawtransaction (inputs, outputs);





Esempio n. 34
0
class DucatuscoreInterface:
    endpoint = None
    settings = None

    def __init__(self):

        self.settings = NETWORK_SETTINGS['DUC']
        self.setup_endpoint()
        self.rpc = AuthServiceProxy(self.endpoint)
        self.check_connection()

    def setup_endpoint(self):
        self.endpoint = 'http://{user}:{pwd}@{host}:{port}'.format(
            user=self.settings['user'],
            pwd=self.settings['password'],
            host=self.settings['host'],
            port=self.settings['port'])
        return

    def check_connection(self):
        block = self.rpc.getblockcount()
        if block and block > 0:
            return True
        else:
            raise Exception('Ducatus node not connected')

    def transfer(self, address, amount):
        try:
            value = amount / DECIMALS['DUC']
            logger.info(msg=f'try sending {value} DUC to {address}')
            self.rpc.walletpassphrase(self.settings['wallet_password'], 30)
            res = self.rpc.sendtoaddress(address, value)
            logger.info(msg=res)
            return res
        except JSONRPCException as e:
            err = f'DUCATUS TRANSFER ERROR: transfer for {amount} DUC for {address} failed'
            logger.error(msg=err)
            logger.error(msg=e)
            raise DucatuscoreInterfaceException(err)

    def validate_address(self, address):
        for attempt in range(10):
            logger.info(msg=f'attempt {attempt}')
            try:
                rpc_response = self.rpc.validateaddress(address)
            except RemoteDisconnected as e:
                logger.error(msg=e)
                rpc_response = False
            if not isinstance(rpc_response, bool):
                logger.info(msg=rpc_response)
                break
        else:
            raise Exception('cannot validate address with 10 attempts')

        return rpc_response['isvalid']

    def get_unspent(self, tx_hash, count):
        return self.rpc.gettxout(tx_hash, count)

    def get_fee(self):
        return self.rpc.getinfo()['relayfee']

    def get_unspent_input(self, tx_hash, payment_address):
        last_response = {}
        count = 0
        while isinstance(last_response, dict):
            rpc_response = self.get_unspent(tx_hash, count)
            last_response = rpc_response

            input_addresses = rpc_response['scriptPubKey']['addresses']
            if payment_address in input_addresses:
                return rpc_response, count

            count += 1

    def internal_transfer(self, tx_list, address_from, address_to, amount,
                          private_key):
        logger.info(msg='start raw tx build')
        logger.info(
            msg=
            f'tx_list {tx_list} from {address_from} to {address_to} amount {amount}'
        )
        try:
            input_params = []
            for payment_hash in tx_list:
                unspent_input, input_vout_count = self.get_unspent_input(
                    payment_hash, address_from)
                logger.info(msg=f'unspent input {unspent_input}')

                input_params.append({
                    'txid': payment_hash,
                    'vout': input_vout_count
                })

            transaction_fee = self.get_fee() * DECIMALS['DUC']
            send_amount = (Decimal(amount) - transaction_fee) / DECIMALS['DUC']

            logger.info(msg=f'input_params {input_params}')
            output_params = {address_to: send_amount}
            logger.info(msg=f'output_params {output_params}')

            tx = self.rpc.createrawtransaction(input_params, output_params)
            logger.info(msg=f'raw tx {tx}')

            signed = self.rpc.signrawtransaction(tx, None, [private_key])
            logger.info(msg=f'signed tx {signed}')

            tx_hash = self.rpc.sendrawtransaction(signed['hex'])
            logger.info(msg=f'tx {tx_hash}')

            return tx_hash

        except JSONRPCException as e:
            logger.error(
                msg=
                f'DUCATUS TRANSFER ERROR: transfer for {amount} DUC for {address_to} failed'
            )
            logger.error(msg=e)
            raise DucatuscoreInterfaceException(e)

    def get_balance(self):
        return int(self.rpc.getbalance('') * DECIMALS['DUC'])
Esempio n. 35
0
def submit_raw(rpc_user,
               rpc_password,
               rpc_host,
               send_addr=None,
               recv_addr=None,
               send_amount=None):

    rpc_connection = AuthServiceProxy("http://{}:{}@{}".format(
        rpc_user, rpc_password, rpc_host))
    # ...
    #rpc_connection.walletpassphrase("openos", 10)
    # validate address
    ret = rpc_connection.validateaddress(recv_addr) if recv_addr else {}

    # ...

    first_unspent = rpc_connection.listunspent()[0]
    print(first_unspent)

    address = first_unspent.get("address")
    scriptPubKey = first_unspent.get("scriptPubKey")
    redeemScript = first_unspent.get("redeemScript")
    txid = first_unspent.get("txid")
    vout = first_unspent.get("vout")

    #first_unspent_amount = Decimal(first_unspent.get("amount"))
    #username = rpc_connection.getaccountaddress(send_addr)
    #print(username)
    username = '******'
    first_unspent_amount = Decimal(rpc_connection.getbalance(username))

    raw_change_address = rpc_connection.getrawchangeaddress()
    new_bitcoin_address = recv_addr if recv_addr else rpc_connection.getnewaddress(
    )

    print("raw_change_address [{}]".format(raw_change_address))

    fee_obj = rpc_connection.estimatesmartfee(6)
    fee = fee_obj.get("feerate")

    # check
    if send_amount:
        print(first_unspent_amount, fee, send_amount)
        change_amount = first_unspent_amount - fee - send_amount
    else:
        send_amount = first_unspent_amount / 2
        change_amount = first_unspent_amount / 2 - fee

    if change_amount < 0.00001:
        print(change_amount)
        raise Exception("Insufficient funds")

    change_amount_string = "%.8f" % change_amount
    send_amount_string = "%0.8f" % send_amount

    data = "@landpack"
    if len(data) > 75:
        print("Data length is {}".format(len(data)))
        raise Exception("Too much data, use OP_PUSHDATA1 instead")

    hex_format_data = binascii.hexlify(data)

    hexstring = rpc_connection.createrawtransaction(
        [{
            "txid": txid,
            "vout": vout
        }], {
            "data": hex_format_data,
            new_bitcoin_address: send_amount_string,
            raw_change_address: change_amount_string
        })
    privkey = rpc_connection.dumpprivkey(address)

    sign_raw_transaction = rpc_connection.signrawtransaction(
        hexstring, [{
            "txid": txid,
            "vout": vout,
            "redeemScript": redeemScript,
            "scriptPubKey": scriptPubKey,
            "amount": first_unspent_amount
        }], [privkey])
    raw_hash = sign_raw_transaction.get("hex")
    ret = rpc_connection.sendrawtransaction(raw_hash)
    return ret
Esempio n. 36
0
class CryptoEngineBitcoin(CryptoEngine):
    BITCOIN_FEE = 0.0001
    BITCOIN_FINAL_CONFIRMATIONS = 6

    def __init__(self, url=None, path=None):
        super().__init__()
        self.rpc = AuthServiceProxy(url)

    def certify(self, data: bytes) -> str:
        #if len(data) <1 or len(data) > 32:
        #    raise ValueError("data length must be > 0 and <= 32")

        blockchain_payload = DATA_PREFIX.encode() + data

        avail_coin = self.__get_available_coin()
        if avail_coin is None:
            raise ValueError("No coin available")

        inputs = [{'txid': avail_coin['txid'], 'vout': avail_coin['vout']}]
        outputs = {'data': binascii.hexlify(blockchain_payload).decode(), avail_coin['address']: avail_coin['amount'] - decimal.Decimal(self.BITCOIN_FEE)}
        rawtrans = self.rpc.createrawtransaction(inputs, outputs)
        #print("RAW Transaction: %s" % rawtrans)

        signedtrans = self.rpc.signrawtransaction(rawtrans)
        #print("Signed transaction: %s" % signedtrans)

        if not signedtrans['complete']:
            raise RuntimeError("Error signing transaction: %s" % (signedtrans))

        txid = self.rpc.sendrawtransaction(signedtrans['hex'])
        #print("Transaction sent, TXID: %s" % txid)

        return txid

    def __get_available_coin(self):
        unspent = self.rpc.listunspent()
        target = None
        #print("# of unspent entries: %d" % len(unspent))
        for i in range(0, len(unspent)):
            ue = unspent[i]
            #print("UE: %s" % ue)
            if ue['spendable'] and ue['amount'] >= self.BITCOIN_FEE:
                #print("Spendable entry found: %s" % ue)
                target = ue
                break

        return target

    def __get_fee(self):
        pass

    def check_cert(self, data: bytes):
        return True

    def cert_status(self, txid: str):
        tx = self.rpc.gettransaction(txid)
        if tx is None:
            return self.generate_result(STATUS_NOT_FOUND, "TX not found")

        confirmations = tx['confirmations']

        status = -1
        msg = None

        if confirmations == 0:
            status = STATUS_IN_MEMPOOL
            msg = "In mempool"
        elif confirmations < self.BITCOIN_FINAL_CONFIRMATIONS:
            status = STATUS_PARTIALLY_CONFIRMED
            msg = "Partially confirmed: %d" % confirmations
        else:
            status = STATUS_CONFIRMED
            msg = "Confirmed: %d" % confirmations

        result = super().generate_result(status, msg, confirmations)

        return result

    def unlock(self, password = None, timeout = None) -> bool:
        self.rpc.walletpassphrase(password, timeout)
        return self.is_locked()

    def lock(self):
        return self.rpc.walletlock()

    def is_locked(self) -> bool:
        code = None
        try:
            self.rpc.signmessage("", "")
        except JSONRPCException as err:
            code = err.code

        if code is None or code == -3:
            return False

        return True