'witnessVersion')

    except CfdError as err:
        if not error:
            raise err
        assert_equal(obj, name, case, exp, err.message)


def test_pegged_address_func(obj, name, case, req, exp, error):
    try:
        resp = None

        if name == 'PeginAddress.Create':
            ret = AddressUtil.get_pegin_address(
                req.get('fedpegscript', ''),
                pubkey=req.get('pubkey', ''),
                redeem_script=req.get('redeemScript', ''),
                hash_type=req.get('hashType', 'p2sh-p2wsh'),
                mainchain_network=req.get('network', 'mainnet'))
            resp = {
                'mainchainAddress': ret[0],
                'claimScript': ret[1],
                'tweakFedpegscript': ret[2],
            }

        elif name == 'PegoutAddress.Create':
            ret = AddressUtil.get_pegout_address(
                descriptor=req['descriptor'],
                bip32_counter=req.get('bip32Counter', 0),
                hash_type=req.get('hashType', 'p2pkh'),
                mainchain_network=req.get('network', 'mainnet'),
                elements_network=req.get('elementsNetwork', 'liquidv1'))
def test_pegin(test_obj):
    btc_rpc = test_obj.btcConn.get_rpc()
    elm_rpc = test_obj.elmConn.get_rpc()

    # generate pegin address
    path = '{}/0/0'.format(ROOT_PATH)
    main_ext_sk = test_obj.hdwallet.get_privkey(path=path)
    main_sk = str(main_ext_sk.privkey)
    main_pk = str(main_ext_sk.privkey.pubkey)
    pegin_address, claim_script, _ = AddressUtil.get_pegin_address(
        fedpeg_script=test_obj.fedpegscript,
        pubkey=main_pk,
        mainchain_network=Network.REGTEST)
    pegin_address = str(pegin_address)
    claim_script = claim_script.hex
    # pegin_addr_info = elm_rpc.getpeginaddress()
    # pegin_address = pegin_addr_info['mainchain_address']
    # claim_script = pegin_addr_info['claim_script']

    for i in range(3):
        try:
            blk_cnt = btc_rpc.getblockcount() + 1
            # send bitcoin
            utxos = get_utxo(btc_rpc, [])
            amount = 0
            for utxo in utxos:
                amount += utxo['amount']
            amount -= 1
            if amount > 100:
                amount = 100
            txid = btc_rpc.sendtoaddress(pegin_address, amount)

            # generate bitcoin 100 block
            addr = str(test_obj.addr_dic['btc'])
            btc_rpc.generatetoaddress(101, addr)
            max_blk_cnt = btc_rpc.getblockcount()

            txout_proof = None
            for i in range(max_blk_cnt - blk_cnt):
                blk_hash = btc_rpc.getblockhash(blk_cnt + i)
                block_hex = btc_rpc.getblock(blk_hash, 0)
                block = Block(block_hex)
                if block.exist_txid(txid):
                    tx_data, txout_proof = block.get_tx_data(txid)
                    print(f'pegin block: {str(block)}')
                    break

            if txout_proof is None:
                raise Exception('txoutproof is empty.')

            # pegin transaction for fee address
            # tx_data = btc_rpc.gettransaction(txid)['hex']
            tx = Transaction(tx_data)
            vout = tx.get_txout_index(pegin_address)
            pegged_amount = tx.txout_list[vout].amount
            # txout_proof = btc_rpc.gettxoutproof([txid])
            # pegin_tx = elm_rpc.createrawpegin(
            #     tx_data, txout_proof, claim_script)['hex']
            # pegin_tx = update_pegin_tx(
            #     test_obj, pegin_tx, tx_data, pegin_address, txout_proof)
            pegin_tx = create_pegin_tx(test_obj, tx, pegin_address,
                                       txout_proof, claim_script)
            ct = ConfidentialTransaction(pegin_tx)
            ct.sign_with_privkey(OutPoint(txid, vout), HashType.P2WPKH,
                                 main_sk, pegged_amount)
            pegin_tx = str(ct)
            # broadcast
            print(
                ConfidentialTransaction.parse_to_json(pegin_tx,
                                                      network=NETWORK))
            txid = elm_rpc.sendrawtransaction(pegin_tx)
            test_obj.tx_dic[txid] = pegin_tx
            # generatetoaddress -> gen address
            addr = str(test_obj.addr_dic['gen'])
            elm_rpc.generatetoaddress(2, addr)
            time.sleep(2)
        except Exception as err:
            print('Exception({})'.format(i))
            raise err

    # generatetoaddress -> gen address
    addr = str(test_obj.addr_dic['gen'])
    elm_rpc.generatetoaddress(100, addr)
    elm_rpc.generatetoaddress(5, addr)
    time.sleep(2)
    fee_addr = test_obj.addr_dic['fee']
    utxos = get_utxo(elm_rpc, [str(fee_addr)])
    # utxos = get_utxo(elm_rpc, [])
    print('UTXO: {}'.format(utxos))
def test_elements_dynafed(test_obj):
    btc_rpc = test_obj.btcConn.get_rpc()
    elm_rpc = test_obj.elmConn.get_rpc()

    # generate block
    chaininfo = elm_rpc.getblockchaininfo()
    epoch_length = chaininfo['epoch_length']
    epoch_age = chaininfo['epoch_age']
    gen_num = epoch_length - epoch_age - 1
    addr = str(test_obj.addr_dic['gen'])
    elm_rpc.generatetoaddress(gen_num, addr)
    # generate dynafed block

    block_data = elm_rpc.getnewblockhex(
        0, {
            "signblockscript": WSH_OP_TRUE,
            "max_block_witness": 500,
            "fedpegscript": new_fedpeg_script,
            "extension_space": [pak1],
        })
    elm_rpc.submitblock(block_data)
    elm_rpc.getblockchaininfo()
    elm_rpc.getsidechaininfo()
    elm_rpc.getblock(chaininfo['bestblockhash'])
    generatetoaddress_dynafed(test_obj, epoch_length)
    time.sleep(2)
    chaininfo = elm_rpc.getblockchaininfo()
    sidechaininfo = elm_rpc.getsidechaininfo()

    # generate pegin address
    path = '{}/0/0'.format(ROOT_PATH)
    main_ext_sk = test_obj.hdwallet.get_privkey(path=path)
    main_sk = str(main_ext_sk.privkey)
    main_pk = str(main_ext_sk.privkey.pubkey)
    pegin_address, claim_script, tweaked = AddressUtil.get_pegin_address(
        fedpeg_script=new_fedpeg_script,
        pubkey=main_pk,
        mainchain_network=Network.REGTEST,
        hash_type=HashType.P2WSH)  # TODO: Dynafed mode (need p2wsh)
    pegin_address = str(pegin_address)
    claim_script = claim_script.hex
    print(f'pegin_address[{pegin_address}]')
    print(f'claim_script[{claim_script}]')
    print(f'tweaked_fedpeg_script[{tweaked}]')
    # pegin_addr_info = elm_rpc.getpeginaddress()
    # pegin_address = pegin_addr_info['mainchain_address']
    # claim_script = pegin_addr_info['claim_script']

    for i in range(3):
        try:
            blk_cnt = btc_rpc.getblockcount() + 1
            # send bitcoin
            utxos = get_utxo(btc_rpc, [])
            amount = 0
            for utxo in utxos:
                amount += utxo['amount']
            amount -= 1
            if amount > 100:
                amount = 100
            txid = btc_rpc.sendtoaddress(pegin_address, amount)

            # generate bitcoin 100 block
            addr = str(test_obj.addr_dic['btc'])
            btc_rpc.generatetoaddress(101, addr)
            max_blk_cnt = btc_rpc.getblockcount()

            txout_proof = None
            for i in range(max_blk_cnt - blk_cnt):
                blk_hash = btc_rpc.getblockhash(blk_cnt + i)
                block_hex = btc_rpc.getblock(blk_hash, 0)
                block = Block(block_hex)
                if block.exist_txid(txid):
                    tx_data, txout_proof = block.get_tx_data(txid)
                    print(f'pegin block: {str(block)}')
                    break

            if txout_proof is None:
                raise Exception('txoutproof is empty.')

            # pegin transaction for fee address
            # tx_data = btc_rpc.gettransaction(txid)['hex']
            tx = Transaction(tx_data)
            vout = tx.get_txout_index(pegin_address)
            pegged_amount = tx.txout_list[vout].amount
            # txout_proof = btc_rpc.gettxoutproof([txid])
            # pegin_tx = elm_rpc.createrawpegin(
            #     tx_data, txout_proof, claim_script)['hex']
            # pegin_tx = update_pegin_tx(
            #     test_obj, pegin_tx, tx_data, pegin_address, txout_proof)
            pegin_tx = create_pegin_tx(test_obj, tx, pegin_address,
                                       txout_proof, claim_script)
            ct = ConfidentialTransaction(pegin_tx)
            ct.sign_with_privkey(OutPoint(txid, vout), HashType.P2WPKH,
                                 main_sk, pegged_amount)
            pegin_tx = str(ct)
            # broadcast
            print(
                ConfidentialTransaction.parse_to_json(pegin_tx,
                                                      network=NETWORK))
            txid = elm_rpc.sendrawtransaction(pegin_tx)
            test_obj.tx_dic[txid] = pegin_tx
            # generatetoaddress -> gen address
            addr = str(test_obj.addr_dic['gen'])
            # elm_rpc.generatetoaddress(2, addr)
            generatetoaddress_dynafed(test_obj, 2)
            time.sleep(2)
        except Exception as err:
            print('Exception({})'.format(i))
            raise err

    # generatetoaddress -> gen address
    addr = str(test_obj.addr_dic['gen'])
    # elm_rpc.generatetoaddress(100, addr)
    generatetoaddress_dynafed(test_obj, 100)
    # elm_rpc.generatetoaddress(5, addr)
    generatetoaddress_dynafed(test_obj, 5)
    time.sleep(2)
    fee_addr = test_obj.addr_dic['fee']
    utxos = get_utxo(elm_rpc, [str(fee_addr)])
    # utxos = get_utxo(elm_rpc, [])
    print('UTXO: {}'.format(utxos))

    # pegout
    pegout_amount = 1000000
    counter = 3
    mainchain_bip32 = 'tpubDDbMfNVnS7fmrTyv98A1bPydovdx2GhaxVAfvgPztEw3R3J2bZ7c2yy3oHx1D3ivjEH5tidRdA766QC83omWBtoUN7CBrk6vyogkTEPUb5b'  # noqa: E501
    pegout_descriptor = f'pkh({mainchain_bip32}/0/*)'
    online_key = 'cVSf1dmLm1XjafyXSXn955cyb2uabdtXxjBXx6fHMQLPQKzHCpT7'
    online_pubkey = \
        '024fb0908ea9263bedb5327da23ff914ce1883f851337d71b3ca09b32701003d05'
    whitelist = ''.join(chaininfo['extension_space'])
    txouts = [
        ConfidentialTxOut(100000000,
                          test_obj.ct_addr_dic[str(
                              test_obj.addr_dic['p2wsh'])],
                          asset=test_obj.pegged_asset),
    ]
    tx = ConfidentialTransaction.create(2, 0, [], txouts)
    tx.add_pegout_output(
        asset=test_obj.pegged_asset,
        amount=pegout_amount,
        mainchain_network_type=Network.REGTEST,
        elements_network_type=Network.ELEMENTS_REGTEST,
        mainchain_genesis_block_hash=sidechaininfo['parent_blockhash'],
        online_pubkey=online_pubkey,
        master_online_key=online_key,
        mainchain_output_descriptor=pegout_descriptor,
        bip32_counter=counter,
        whitelist=whitelist,
    )
    # fundrawtransaction
    fee_addr = str(test_obj.addr_dic['fee'])
    fee_desc = test_obj.desc_dic[fee_addr]
    fee_ct_addr = test_obj.ct_addr_dic[fee_addr]
    fee_sk = test_obj.hdwallet.get_privkey(path=FEE_PATH).privkey
    # utxos = get_utxo(elm_rpc, [fee_addr])
    utxo_list = convert_elements_utxos(test_obj, utxos)
    target_list = [
        TargetAmountData(amount=1,
                         asset=test_obj.pegged_asset,
                         reserved_address=fee_ct_addr)
    ]
    tx.fund_raw_transaction([],
                            utxo_list,
                            fee_asset=test_obj.pegged_asset,
                            target_list=target_list,
                            effective_fee_rate=0.1,
                            knapsack_min_change=1)
    # blind
    blind_utxo_list = []
    for txin in tx.txin_list:
        blind_utxo_list.append(search_utxos(test_obj, utxo_list,
                                            txin.outpoint))
    tx.blind_txout(blind_utxo_list)
    # 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,
                             value=utxo.value,
                             sighashtype=SigHashType.ALL)
    # broadcast
    print(ConfidentialTransaction.parse_to_json(str(tx), network=NETWORK))
    elm_rpc.sendrawtransaction(str(tx))
    # generate block
    elm_rpc.generatetoaddress(2, fee_addr)
    time.sleep(2)