resp = AddressUtil.p2wpkh(req['keyData']['hex'],
                                          network=_network)
            elif _hash_type == HashType.P2SH_P2WPKH:
                resp = AddressUtil.p2sh_p2wpkh(req['keyData']['hex'],
                                               network=_network)
            elif _hash_type == HashType.P2SH:
                resp = AddressUtil.p2sh(req['keyData']['hex'],
                                        network=_network)
            elif _hash_type == HashType.P2WSH:
                resp = AddressUtil.p2wsh(req['keyData']['hex'],
                                         network=_network)
            elif _hash_type == HashType.P2SH_P2WSH:
                resp = AddressUtil.p2sh_p2wsh(req['keyData']['hex'],
                                              network=_network)
            elif _hash_type == HashType.TAPROOT:
                resp = AddressUtil.taproot(req['keyData']['hex'],
                                           network=_network)
        elif name == 'Address.GetInfo':
            resp = AddressUtil.parse(req['address'])
        elif name == 'Address.MultisigAddresses':
            resp = AddressUtil.get_multisig_address_list(req['redeemScript'],
                                                         req['hashType'],
                                                         network=_network)
        elif name == 'Address.CreateMultisig':
            resp = AddressUtil.multisig(req['nrequired'],
                                        req['keys'],
                                        req['hashType'],
                                        network=_network)

        elif name == 'Address.FromLockingScript':
            resp = AddressUtil.from_locking_script(req['lockingScript'],
                                                   network=_network)
Example #2
0
def test_taproot_tapscript(test_obj: 'TestBitcoin'):
    btc_rpc = test_obj.conn.get_rpc()
    main_addr = test_obj.addr_dic['main']
    main_pk, _ = SchnorrPubkey.from_pubkey(str(main_addr.pubkey))
    pkh_addr = test_obj.addr_dic['p2pkh']
    spk1, _ = SchnorrPubkey.from_pubkey(str(pkh_addr.pubkey))
    wpkh_addr = test_obj.addr_dic['p2wpkh']
    spk2, _ = SchnorrPubkey.from_pubkey(str(wpkh_addr.pubkey))
    main_path = str(test_obj.path_dic[str(main_addr)])
    main_sk = test_obj.hdwallet.get_privkey(path=main_path).privkey
    pkh_path = str(test_obj.path_dic[str(pkh_addr)])
    sk1 = test_obj.hdwallet.get_privkey(path=pkh_path).privkey
    # wpkh_path = str(test_obj.path_dic[str(wpkh_addr)])
    # sk2 = test_obj.hdwallet.get_privkey(path=wpkh_path).privkey

    script1 = Script.from_asm([str(spk1), 'OP_CHECKSIG'])
    script2 = Script.from_asm([str(spk2), 'OP_CHECKSIG'])
    op_true_script = Script('51')
    op_true_sub_tree1 = TaprootScriptTree(op_true_script)
    op_true_sub_tree1.add_branch(script1)

    script1_tree = TaprootScriptTree(script1)
    script1_tree.add_branches([op_true_script, script2])
    script1_tree.internal_pubkey = main_pk

    op_true_tree = TaprootScriptTree(op_true_script)
    op_true_tree.add_branches([script1, script2])
    op_true_tree.internal_pubkey = main_pk

    script2_tree = TaprootScriptTree(script2)
    script2_tree.add_branch(op_true_sub_tree1)
    script2_tree.internal_pubkey = main_pk

    tr_addr1 = AddressUtil.taproot(script1_tree, network=NETWORK)
    tr_addr2 = AddressUtil.taproot(op_true_tree, network=NETWORK)
    tr_addr3 = AddressUtil.taproot(script2_tree, network=NETWORK)

    txouts = [
        TxOut(100000, str(tr_addr1)),
        TxOut(150000, str(tr_addr2)),
        TxOut(200000, str(tr_addr3)),
    ]
    tx = Transaction.create(2, 0, [], txouts)
    # fundrawtransaction
    fee_addr = str(test_obj.addr_dic['fee'])
    fee_desc = test_obj.desc_dic[fee_addr]
    fee_sk = test_obj.hdwallet.get_privkey(path=FEE_PATH).privkey
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx.fund_raw_transaction([],
                            utxo_list,
                            fee_addr,
                            target_amount=0,
                            effective_fee_rate=2.0,
                            knapsack_min_change=0)
    # add sign
    for txin in tx.txin_list:
        utxo = search_utxos(test_obj, utxo_list, txin.outpoint)
        tx.sign_with_privkey(txin.outpoint,
                             fee_desc.data.hash_type,
                             fee_sk,
                             amount=utxo.amount,
                             sighashtype=SigHashType.ALL)
    # broadcast
    print(Transaction.parse_to_json(str(tx), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    txid = tx.txid
    utxo1 = UtxoData(txid=txid,
                     vout=0,
                     amount=txouts[0].amount,
                     descriptor=f'raw({str(tr_addr1.locking_script)})')
    utxo2 = UtxoData(txid=txid,
                     vout=1,
                     amount=txouts[1].amount,
                     descriptor=f'raw({str(tr_addr2.locking_script)})')
    utxo3 = UtxoData(txid=txid,
                     vout=2,
                     amount=txouts[2].amount,
                     descriptor=f'raw({str(tr_addr3.locking_script)})')

    # send tapscript script1
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=0))
    txin_utxo_list.append(utxo1)
    txouts2 = [
        TxOut(txouts[0].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list: List['UtxoData'] = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sk = sk1
            sighash = tx2.get_sighash(txin.outpoint,
                                      HashType.TAPROOT,
                                      redeem_script=script1,
                                      sighashtype=SigHashType.DEFAULT,
                                      utxos=join_utxo_list)
            sig = SchnorrUtil.sign(sighash, sk1)
            sign_param = SignParameter(sig, sighashtype=SigHashType.DEFAULT)
            _, _, _, control_block = script1_tree.get_taproot_data()
            tx2.add_tapscript_sign(txin.outpoint, [sign_param], script1,
                                   control_block)
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
            tx2.sign_with_privkey(txin.outpoint,
                                  hash_type,
                                  sk,
                                  amount=utxo.amount,
                                  sighashtype=SigHashType.ALL,
                                  utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    # send tapscript OP_TRUE
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=1))
    txin_utxo_list.append(utxo2)
    txouts2 = [
        TxOut(txouts[1].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            _, _, _, control_block = op_true_tree.get_taproot_data()
            tx2.add_tapscript_sign(txin.outpoint, [], op_true_script,
                                   control_block)
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
            tx2.sign_with_privkey(txin.outpoint,
                                  hash_type,
                                  sk,
                                  amount=utxo.amount,
                                  sighashtype=SigHashType.ALL,
                                  utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    # send tapscript internal_pubkey
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=2))
    txin_utxo_list.append(utxo3)
    txouts2 = [
        TxOut(txouts[2].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sk = script2_tree.get_privkey(main_sk)
            hash_type = tr_addr3.hash_type
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
        tx2.sign_with_privkey(txin.outpoint,
                              hash_type,
                              sk,
                              amount=utxo.amount,
                              sighashtype=SigHashType.ALL,
                              utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    utxos = get_utxo(btc_rpc, [str(main_addr)])
    print('UTXO: {}'.format(utxos))
Example #3
0
def test_taproot_single_key(test_obj: 'TestBitcoin'):
    btc_rpc = test_obj.conn.get_rpc()
    main_addr = test_obj.addr_dic['main']
    main_pk, _ = SchnorrPubkey.from_pubkey(str(main_addr.pubkey))
    pkh_addr = test_obj.addr_dic['p2pkh']
    spk1, _ = SchnorrPubkey.from_pubkey(str(pkh_addr.pubkey))
    wpkh_addr = test_obj.addr_dic['p2wpkh']
    spk2, _ = SchnorrPubkey.from_pubkey(str(wpkh_addr.pubkey))
    main_path = str(test_obj.path_dic[str(main_addr)])
    main_sk = test_obj.hdwallet.get_privkey(path=main_path).privkey
    pkh_path = str(test_obj.path_dic[str(pkh_addr)])
    sk1 = test_obj.hdwallet.get_privkey(path=pkh_path).privkey
    wpkh_path = str(test_obj.path_dic[str(wpkh_addr)])
    sk2 = test_obj.hdwallet.get_privkey(path=wpkh_path).privkey

    branch = TapBranch()
    tr_addr1 = AddressUtil.taproot(main_pk,
                                   script_tree=branch,
                                   network=NETWORK)
    tr_sk1 = branch.get_privkey(main_sk)
    tr_addr2 = AddressUtil.taproot(spk1, script_tree=branch, network=NETWORK)
    tr_sk2 = branch.get_privkey(sk1)
    tr_addr3 = AddressUtil.taproot(spk2, script_tree=branch, network=NETWORK)
    tr_sk3 = branch.get_privkey(sk2)

    txouts = [
        TxOut(100000, str(tr_addr1)),
        TxOut(150000, str(tr_addr2)),
        TxOut(200000, str(tr_addr3)),
    ]
    tx = Transaction.create(2, 0, [], txouts)
    # fundrawtransaction
    fee_addr = str(test_obj.addr_dic['fee'])
    fee_desc = test_obj.desc_dic[fee_addr]
    fee_sk = test_obj.hdwallet.get_privkey(path=FEE_PATH).privkey
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx.fund_raw_transaction([],
                            utxo_list,
                            fee_addr,
                            target_amount=0,
                            effective_fee_rate=2.0,
                            knapsack_min_change=0)
    # add sign
    for txin in tx.txin_list:
        utxo = search_utxos(test_obj, utxo_list, txin.outpoint)
        tx.sign_with_privkey(txin.outpoint,
                             fee_desc.data.hash_type,
                             fee_sk,
                             amount=utxo.amount,
                             sighashtype=SigHashType.ALL)
    # broadcast
    print(Transaction.parse_to_json(str(tx), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    txid = tx.txid
    utxo1 = UtxoData(txid=txid,
                     vout=0,
                     amount=txouts[0].amount,
                     descriptor=f'raw({str(tr_addr1.locking_script)})')
    utxo2 = UtxoData(txid=txid,
                     vout=1,
                     amount=txouts[1].amount,
                     descriptor=f'raw({str(tr_addr2.locking_script)})')
    utxo3 = UtxoData(txid=txid,
                     vout=2,
                     amount=txouts[2].amount,
                     descriptor=f'raw({str(tr_addr3.locking_script)})')

    # send taproot singleKey1
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=0))
    txin_utxo_list.append(utxo1)
    txouts2 = [
        TxOut(txouts[0].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list: List['UtxoData'] = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sighash = tx2.get_sighash(txin.outpoint,
                                      HashType.TAPROOT,
                                      pubkey=tr_addr1.pubkey,
                                      sighashtype=SigHashType.DEFAULT,
                                      utxos=join_utxo_list)
            sig = SchnorrUtil.sign(sighash, tr_sk1)
            sign_param = SignParameter(sig, sighashtype=SigHashType.DEFAULT)
            tx2.add_taproot_sign(txin.outpoint, sign_param)
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
            tx2.sign_with_privkey(txin.outpoint,
                                  hash_type,
                                  sk,
                                  amount=utxo.amount,
                                  sighashtype=SigHashType.ALL,
                                  utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    # send taproot singleKey2
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=1))
    txin_utxo_list.append(utxo2)
    txouts2 = [
        TxOut(txouts[1].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sighash = tx2.get_sighash(txin.outpoint,
                                      HashType.TAPROOT,
                                      pubkey=tr_addr2.pubkey,
                                      sighashtype=SigHashType.DEFAULT,
                                      utxos=join_utxo_list)
            sig = SchnorrUtil.sign(sighash, tr_sk2)
            sign_param = SignParameter(sig, sighashtype=SigHashType.DEFAULT)
            tx2.add_taproot_sign(txin.outpoint, sign_param)
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
            tx2.sign_with_privkey(txin.outpoint,
                                  hash_type,
                                  sk,
                                  amount=utxo.amount,
                                  sighashtype=SigHashType.ALL,
                                  utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    # send taproot singleKey3
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=2))
    txin_utxo_list.append(utxo3)
    txouts2 = [
        TxOut(txouts[2].amount, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=2.0,
                             knapsack_min_change=0)
    # add sign
    join_utxo_list = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sighash = tx2.get_sighash(txin.outpoint,
                                      HashType.TAPROOT,
                                      pubkey=tr_addr3.pubkey,
                                      sighashtype=SigHashType.DEFAULT,
                                      utxos=join_utxo_list)
            sig = SchnorrUtil.sign(sighash, tr_sk3)
            sign_param = SignParameter(sig, sighashtype=SigHashType.DEFAULT)
            tx2.add_taproot_sign(txin.outpoint, sign_param)
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
            tx2.sign_with_privkey(txin.outpoint,
                                  hash_type,
                                  sk,
                                  amount=utxo.amount,
                                  sighashtype=SigHashType.ALL,
                                  utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    utxos = get_utxo(btc_rpc, [str(main_addr)])
    print('UTXO: {}'.format(utxos))
Example #4
0
def test_taproot_schnorr(test_obj: 'TestBitcoin'):
    btc_rpc = test_obj.conn.get_rpc()
    main_addr = test_obj.addr_dic['main']
    main_pk, _ = SchnorrPubkey.from_pubkey(str(main_addr.pubkey))
    tr_addr = AddressUtil.taproot(main_pk, network=NETWORK)
    main_path = str(test_obj.path_dic[str(main_addr)])
    main_sk = test_obj.hdwallet.get_privkey(path=main_path).privkey

    txouts = [
        TxOut(100000000, str(tr_addr)),
    ]
    tx = Transaction.create(2, 0, [], txouts)
    # fundrawtransaction
    fee_addr = str(test_obj.addr_dic['fee'])
    fee_desc = test_obj.desc_dic[fee_addr]
    fee_sk = test_obj.hdwallet.get_privkey(path=FEE_PATH).privkey
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx.fund_raw_transaction([],
                            utxo_list,
                            fee_addr,
                            target_amount=0,
                            effective_fee_rate=2.0,
                            knapsack_min_change=0)
    # add sign
    for txin in tx.txin_list:
        utxo = search_utxos(test_obj, utxo_list, txin.outpoint)
        tx.sign_with_privkey(txin.outpoint,
                             fee_desc.data.hash_type,
                             fee_sk,
                             amount=utxo.amount,
                             sighashtype=SigHashType.ALL)
    # broadcast
    print(Transaction.parse_to_json(str(tx), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    # create tx (output wpkh only, input tx1-3)
    txid = tx.txid
    txin_list = []
    txin_utxo_list = []
    txin_list.append(TxIn(txid=txid, vout=0))
    desc = f'raw({str(tr_addr.locking_script)})'
    txin_utxo_list.append(
        UtxoData(txid=txid, vout=0, amount=txouts[0].amount, descriptor=desc))
    txouts2 = [
        TxOut(100000000, str(test_obj.addr_dic['main'])),
    ]
    tx2 = Transaction.create(2, 0, txin_list, txouts2)
    main_addr = test_obj.addr_dic['main']
    utxos = get_utxo(btc_rpc, [fee_addr])
    utxo_list = convert_bitcoin_utxos(test_obj, utxos)
    tx2.fund_raw_transaction(txin_utxo_list,
                             utxo_list,
                             fee_addr,
                             target_amount=0,
                             effective_fee_rate=20.0,
                             knapsack_min_change=1)
    # add sign
    join_utxo_list: List['UtxoData'] = []
    join_utxo_list[len(join_utxo_list):len(join_utxo_list)] = txin_utxo_list
    for txin in tx2.txin_list:
        for utxo in utxo_list:
            if utxo.outpoint == txin.outpoint:
                join_utxo_list.append(utxo)
    for index, txin in enumerate(tx2.txin_list):
        utxo = search_utxos(test_obj, join_utxo_list, txin.outpoint)
        if index == 0:
            sk = main_sk
            hash_type = main_addr.hash_type
        else:
            path = str(test_obj.path_dic[str(utxo.descriptor.data.address)])
            sk = test_obj.hdwallet.get_privkey(path=path).privkey
            hash_type = utxo.descriptor.data.hash_type
        tx2.sign_with_privkey(txin.outpoint,
                              hash_type,
                              sk,
                              amount=utxo.amount,
                              sighashtype=SigHashType.ALL,
                              utxos=join_utxo_list)
    # broadcast
    print(Transaction.parse_to_json(str(tx2), network=NETWORK))
    btc_rpc.sendrawtransaction(str(tx2))
    # generate block
    btc_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)

    utxos = get_utxo(btc_rpc, [str(main_addr)])
    print('UTXO: {}'.format(utxos))