Beispiel #1
0
def init_tx_builders(env, kps, sequences):
    """Initialize transaction builders for each given seed."""
    builders = []
    for i, kp in enumerate(kps):
        client = KinClient(env)
        builder = Builder(env.name, client.horizon, MIN_FEE, kp.secret_seed)
        builder.sequence = sequences[i]
        builders.append(builder)
    return builders
Beispiel #2
0
def next_builder(b: Builder) -> Builder:
    """Reimplementation of kin.blockchain.Builder.next() that returns a new builder."""
    next_builder = Builder(network=b.network,
                           horizon=b.horizon,
                           fee=b.fee,
                           secret=b.keypair.seed().decode(),
                           address=b.address)

    next_builder.keypair = b.keypair
    next_builder.sequence = str(int(b.sequence)+1)

    return next_builder
async def init_channel_builders(channel_seeds_file, passphrase, horizon):
    env = Environment(NETWORK_NAME, (horizon)[0], passphrase)

    channel_kps = load_accounts(channel_seeds_file)
    sequences = await get_sequences_multiple_endpoints(horizon, [kp.public_address for kp in channel_kps])

    channel_builders = []
    for i, kp in enumerate(channel_kps):
        b = Builder(NETWORK_NAME, KinClient(env).horizon, MIN_FEE, kp.secret_seed)
        b.sequence = str(sequences[i])
        channel_builders.append(b)

    return channel_builders
Beispiel #4
0
async def main():
    """Create accounts and print their seeds to stdout."""
    args = parse_args()
    env = Environment(NETWORK_NAME, (args.horizon)[0], args.passphrase)
    builder = Builder(NETWORK_NAME,
                      KinClient(env).horizon, MIN_FEE,
                      root_account_seed(args.passphrase))
    builder.sequence = builder.get_sequence()
    kps = await create_accounts(builder, args.horizon, args.accounts,
                                STARTING_BALANCE)

    for kp in kps:
        print(kp.secret_seed)
Beispiel #5
0
async def generate_builders(kps: List[Keypair], env_name, horizon) -> List[Builder]:
    """Receive Keypair list and return Builder list with updated sequence numbers."""
    # fetch sequence numbers asynchronously for all created accounts
    sequences = await get_sequences_multiple_endpoints([horizon], [kp.public_address for kp in kps])

    # create tx builders with up-to-date sequence number
    builders = []
    for i, kp in enumerate(kps):
        builder = Builder(env_name, horizon, MIN_FEE, kp.secret_seed)
        builder.sequence = sequences[i]
        builders.append(builder)

    for b in builders:
        logging.debug('created builder %s', b.address)

    return builders
Beispiel #6
0
def main():
    """Receive seeds and add them as prioritizers to whitelist account."""
    args = parse_args()
    env = KinEnvironment(NETWORK_NAME, args.horizon, args.passphrase)
    prioritizer_kps = load_accounts(args.prioritizer_seeds_file)
    whitelist_builder = Builder(env.name, KinClient(env).horizon, MIN_FEE, args.whitelist_seed)
    add_prioritizers(whitelist_builder, prioritizer_kps)
Beispiel #7
0
async def main():
    initialize()

    txs = []
    accounts = []

    minimum_fee = clients[0].get_minimum_fee()

    # Creating new test accounts
    accounts.append(Keypair())
    accounts.append(Keypair())
    accounts.append(Keypair())

    print('Creating new test accounts')
    root_account.create_account(accounts[0].public_address, 100000000,
                                minimum_fee)
    root_account.create_account(accounts[1].public_address, 100000000,
                                minimum_fee)
    assert clients[0].does_account_exists(
        accounts[1].public_address) and clients[0].does_account_exists(
            accounts[0].public_address)
    print('2 Test accounts created - Passed')

    for i in range(tx_count):
        # generating transactions using multiple kin-cores
        builder = Builder('LOCAL',
                          clients[i % len(clients)].horizon,
                          fee=minimum_fee,
                          secret=accounts[i % len(accounts)].secret_seed)
        builder.get_sequence()
        builder.append_manage_data_op('test' + str(i), 'test'.encode())
        builder.sign()
        txs.append(builder)

    # waiting for the txs receipts from different cores
    receipts = await send_txs(txs)

    assert len(receipts) == tx_count
    print('All of the transactions approved by different cores - Passed')

    assert len(set([(rec._result['ledger']) for rec in receipts])) == 1
    print('All of the transactions are in the same ledger - Passed')

    cores_hashes = [(rec._result['hash']) for rec in receipts]
    ledger_no = receipts[0]._result['ledger']

    # waiting for the next ledger
    while ledger_no + 1 > get_latest_ledger(clients[0])['sequence']:
        time.sleep(0.5)

    # getting ledger txs from horizon
    ledger_txs = clients[0].horizon.ledger_transactions(
        ledger_no)['_embedded']['records']

    # comparing ledger hashes with the core hashes
    assert set(cores_hashes) & set([t['hash'] for t in ledger_txs])
    print('Multi cores test - Passed')
Beispiel #8
0
async def create_accounts(source: Builder, horizon_endpoints, accounts_num, starting_balance):
    """Asynchronously create accounts and return a Keypair instance for each created account."""
    logging.info('creating %d accounts', accounts_num)

    # generate txs, squeezing as much "create account" ops as possible to each one.
    # when each tx is full with as much ops as it can include, sign and generate
    # that tx's XDR.
    # then, continue creating accounts using a new tx, and so on.
    # we stop when we create all ops required according to given accounts_num.
    def batch(iterable, n=1):
        l = len(iterable)
        for ndx in range(0, l, n):
            yield iterable[ndx:min(ndx + n, l)]

    kps = await generate_keypairs(accounts_num)
    xdrs = []
    for batch_kps in batch(kps, MAX_OPS):
        for kp in batch_kps:
            source.append_create_account_op(source=source.address,
                                            destination=kp.public_address,
                                            starting_balance=str(starting_balance))

        # sign with channel and root account
        source.sign(secret=source.keypair.seed().decode())
        xdrs.append(source.gen_xdr())

        # clean source builder for next transaction
        source.next()

    await send_txs_multiple_endpoints(horizon_endpoints, xdrs, expected_statuses=[200])

    logging.info('created %d accounts', accounts_num)
    return kps
Beispiel #9
0
def create_whitelist_account():
    """Create whitelist account for prioritizing transactions in tests."""
    print('Creating whitelist account')

    env = KinEnvironment('LOCAL', HORIZON_ENDPOINT, PASSPHRASE)
    root_client = KinClient(env)
    root_seed = derive_root_account_seed(PASSPHRASE)
    builder = Builder(env.name, root_client.horizon, 100, root_seed)

    builder.append_create_account_op(WHITELIST_ADDRESS, str(100e5))
    builder.sign()
    builder.submit()
Beispiel #10
0
async def main():
    args = parse_args()

    # setup network
    Environment(NETWORK_NAME, args.horizon[0], args.passphrase)

    logging.info('loading prioritizer accounts')
    prioritizer_kps = [kp for kp in load_accounts(args.prioritizer_seeds_file)]
    logging.info('%d prioritizer accounts loaded', len(prioritizer_kps))

    logging.info('loading spammer accounts')
    spam_kps = load_accounts(args.spammer_seeds_file)
    logging.info('%d spammer accounts loaded', len(spam_kps))

    logging.info('fetching sequence number for spammer accounts')
    spam_sequences = await get_sequences_multiple_endpoints(args.horizon, [kp.public_address for kp in spam_kps])

    logging.info('generating spammer builders')
    spam_builders = []

    # we're not submitting using the builder - just generating the xdr,
    # so each builder's horizon instance is irrelevant
    stub_horizon = args.horizon[0]
    for kp, seq in zip(spam_kps, spam_sequences):
        b = Builder(NETWORK_NAME, stub_horizon, MIN_FEE, kp.secret_seed)
        b.sequence = str(seq)
        spam_builders.append(b)

    logging.info('sleeping for %ds to let horizon cool down after get sequence request surge', COOL_DOWN_AFTER_GET_SEQ)
    time.sleep(COOL_DOWN_AFTER_GET_SEQ)

    logging.info('starting spam')
    results = await spam(args.horizon, prioritizer_kps, spam_builders, args.length, args.txs_per_ledger)
    logging.info('done spamming')

    logging.info('writing transaction results to file')
    with open(args.out, 'w') as f:
        for spam_round in results:
            for tx in spam_round:
                f.write('{}\n'.format(json.dumps(tx)))

    logging.info('done')
Beispiel #11
0
def create_whitelist_account():
    """Create whitelist account for prioritizing transactions in tests."""
    print('Creating whitelist account')

    env = KinEnvironment('LOCAL', 'http://localhost:8000', 'private testnet')
    root_client = KinClient(env)
    root_seed = derive_root_account_seed('private testnet')
    builder = Builder(env.name, root_client.horizon, 100, root_seed)

    builder.append_create_account_op(
        'GBR7K7S6N6C2A4I4URBXM43W7IIOK6ZZD5SAGC7LBRCUCDMICTYMK4LO', str(100e5))
    builder.sign()
    builder.submit()
Beispiel #12
0
async def main():
    args = parse_args()

    # setup network
    Environment(NETWORK_NAME, args.horizon[0], args.passphrase)

    logging.info('loading prioritizer accounts')
    prioritizer_kps = [kp for kp in load_accounts(args.prioritizer_seeds_file)]
    logging.info('%d prioritizer accounts loaded', len(prioritizer_kps))

    logging.info('loading spammer accounts')
    spam_kps = load_accounts(args.spammer_seeds_file)
    logging.info('%d spammer accounts loaded', len(spam_kps))

    logging.info('fetching sequence number for spammer accounts')
    spam_sequences = await get_sequences_multiple_endpoints(args.horizon, [kp.public_address for kp in spam_kps])

    logging.info('generating spammer builders')
    spam_builders = []

    # we're not submitting using the builder - just generating the xdr,
    # so each builder's horizon instance is irrelevant
    stub_horizon = args.horizon[0]
    for kp, seq in zip(spam_kps, spam_sequences):
        b = Builder(NETWORK_NAME, stub_horizon, MIN_FEE, kp.secret_seed)
        b.sequence = str(seq)
        spam_builders.append(b)

    logging.info('generating spam transaction xdrs')
    spam_rounds = await generate_spam_tx_xdrs(prioritizer_kps, spam_builders, args.length, args.txs_per_ledger, args.avg_block_time)
    logging.info('done generating spam transaction xdrs')

    logging.info('writing transaction xdrs to file %s', args.out)
    with open(args.out, 'w') as f:
        for rnd in spam_rounds:
            f.write('{}\n'.format(json.dumps(rnd)))

    logging.info('done')
def add_prioritizers(builder: Builder, kps: List[Keypair]):
    """Add given addresses to whitelist account, making them transaction prioritizers."""
    logging.info('adding %d prioritizers', len(kps))

    for batch_index in range(max(1, math.ceil(len(kps) / MAX_OPS))):
        start = batch_index * MAX_OPS
        end = min((batch_index + 1) * MAX_OPS, len(kps))

        for i, kp in enumerate(kps[start:end], start=1):
            logging.debug('adding manage data op #%d', i)
            builder.append_manage_data_op(kp.public_address, kp._hint)

        builder.sign()

        logging.debug('submitting transaction with %d manage data ops',
                      end - start)
        builder.submit()
        logging.debug('done')

        builder.clear()

    logging.info('%d prioritizers added', len(kps))
Beispiel #14
0
async def main():
    # Create the environment
    local_env = Environment('LOCAL', 'http://localhost:8000', PASSPHRASE,
                            'http://localhost:8001')

    # Create a client
    client = KinClient(local_env)
    print('Client created')

    initial_ledger_size = get_latest_ledger(client)['max_tx_set_size']
    try:
        # Set ledger tx size to 1
        requests.get(
            'http://localhost:11626/upgrades?mode=set&maxtxsize=1&upgradetime=2018-10-15T18:34:00Z'
        )

        # Create the root account object
        root_account = client.kin_account(
            derive_root_account(PASSPHRASE).secret_seed)
        print('Root account object created')

        minimum_fee = client.get_minimum_fee()
        # Create an account with 0 base reserve
        test_account = Keypair()
        root_account.create_account(test_account.public_address, 0,
                                    minimum_fee)
        assert client.does_account_exists(test_account.public_address)
        print('Test account created')

        # Add the account to the whitelist
        if not client.does_account_exists(
                WHITELIST_MANAGER_KEYPAIR.public_address):
            root_account.create_account(
                WHITELIST_MANAGER_KEYPAIR.public_address, 10000, 100)
        print('Created whitelisting account')

        builder = Builder('LOCAL',
                          client.horizon,
                          fee=minimum_fee,
                          secret=WHITELIST_MANAGER_KEYPAIR.secret_seed)
        builder.get_sequence()
        builder.append_manage_data_op(test_account.public_address,
                                      test_account._hint)
        builder.sign()
        builder.submit()

        print('Added account to whitelist')

        for _ in range(5):
            txs = []
            first_builder = Builder('LOCAL',
                                    client.horizon,
                                    fee=minimum_fee,
                                    secret=test_account.secret_seed)
            first_builder.append_manage_data_op('test', 'test'.encode())
            first_builder.get_sequence()
            first_builder.sign()
            txs.append(first_builder)

            second_builder = Builder(
                'LOCAL',
                client.horizon,
                fee=minimum_fee,
                secret=WHITELIST_MANAGER_KEYPAIR.secret_seed)
            second_builder.append_payment_op(test_account.public_address, '1')
            second_builder.get_sequence()
            second_builder.sign()
            txs.append(second_builder)

            initial_ledger = get_latest_ledger(client)['sequence']
            print(f'Initial ledger: {initial_ledger}')
            while initial_ledger == get_latest_ledger(client)['sequence']:
                time.sleep(0.5)

            first_populated_ledger = initial_ledger + 2

            print(f'Sending on ledger: {first_populated_ledger}')

            print(f'Sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')
            await send_txs(txs)
            print(f'Done sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')

            first_ledger_txs = client.horizon.ledger_transactions(
                first_populated_ledger)['_embedded']['records']

            # First ledger should have tx from whitelist_manager
            assert WHITELIST_MANAGER_KEYPAIR.public_address == first_ledger_txs[
                0]['source_account']
            print('Verified tx from whitelist manager got priority')
    except:
        raise
    finally:
        # Set tx size to what it was before
        requests.get(
            f'http://localhost:11626/upgrades?mode=set&maxtxsize={initial_ledger_size}&upgradetime=2018-10-15T18:34:00Z'
        )
Beispiel #15
0
def main():
    # Create the environment
    local_env = Environment('LOCAL', 'http://localhost:8000', PASSPHRASE,
                            'http://localhost:8001')

    # Create a client
    client = KinClient(local_env)
    print('Client created')

    # Create the root account object
    root_account = client.kin_account(
        derive_root_account(PASSPHRASE).secret_seed)
    print('Root account object created')

    minimum_fee = client.get_minimum_fee()
    # Create an account with 0 base reserve
    test_account = Keypair()
    root_account.create_account(test_account.public_address, 0, minimum_fee)
    assert client.does_account_exists(test_account.public_address)
    print('Test account created')

    # Send a tx that does not require spending kin
    builder = Builder('LOCAL',
                      client.horizon,
                      fee=0,
                      secret=test_account.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op('test', 'test'.encode())
    builder.sign()

    try:
        builder.submit()
    except KinErrors.HorizonError as e:
        # Tx should fail since the fee is under minimum fee
        assert e.extras.result_codes.transaction == KinErrors.TransactionResultCode.INSUFFICIENT_FEE
        print('Sending under minimum fee - Passed')

    builder = Builder('LOCAL',
                      client.horizon,
                      fee=minimum_fee,
                      secret=test_account.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op('test', 'test'.encode())
    builder.sign()

    try:
        builder.submit()
    except KinErrors.HorizonError as e:
        # Tx should fail since the account cant pay the fee
        assert e.extras.result_codes.transaction == KinErrors.TransactionResultCode.INSUFFICIENT_BALANCE
        print('Sending with no fee to pay - Passed')

    # Add the account to the whitelist
    if not client.does_account_exists(
            WHITELIST_MANAGER_KEYPAIR.public_address):
        root_account.create_account(WHITELIST_MANAGER_KEYPAIR.public_address,
                                    10000, 100)
    print('Created whitelisting account')

    builder = Builder('LOCAL',
                      client.horizon,
                      fee=minimum_fee,
                      secret=WHITELIST_MANAGER_KEYPAIR.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op(test_account.public_address,
                                  test_account._hint)
    builder.sign()
    builder.submit()

    print('Added account to whitelist')

    # test_account is now a whitelister, so the fee should be ignored
    builder = Builder('LOCAL',
                      client.horizon,
                      fee=0,
                      secret=test_account.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op('test2', 'test2'.encode())
    builder.sign()
    builder.submit()

    print('Sending prioritized tx under minimum fee - Passed')

    builder = Builder('LOCAL',
                      client.horizon,
                      fee=999999,
                      secret=test_account.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op('test3', 'test3'.encode())
    builder.sign()
    builder.submit()

    print('Sending prioritized tx with fee > balance - Passed')

    # Try the same if the account is not a whitelister, but the tx is whitelisted
    test_account2 = Keypair()
    root_account.create_account(test_account2.public_address, 0, minimum_fee)

    builder = Builder('LOCAL',
                      client.horizon,
                      fee=999999,
                      secret=test_account2.secret_seed)
    builder.get_sequence()
    builder.append_manage_data_op('test', 'test'.encode())
    builder.sign()
    # sign with the whitelister as well to prioritize the tx
    builder.sign(secret=test_account.secret_seed)
    builder.submit()

    print('Sending prioritized tx2 with fee > balance - Passed')
async def main():
    # Create the environment
    local_env = Environment('LOCAL', 'http://localhost:8000', PASSPHRASE,
                            'http://localhost:8001')

    # Create a client
    client = KinClient(local_env)
    print('Client created')

    initial_ledger_size = get_latest_ledger(client)['max_tx_set_size']
    try:
        # Set ledger tx size to 3
        requests.get(
            'http://localhost:11626/upgrades?mode=set&maxtxsize=3&upgradetime=2018-10-15T18:34:00Z'
        )

        # Create the root account object
        root_account = client.kin_account(
            derive_root_account(PASSPHRASE).secret_seed)
        print('Root account object created')

        minimum_fee = client.get_minimum_fee()
        # Create an account with 0 base reserve
        test_account = Keypair()
        root_account.create_account(test_account.public_address, 0,
                                    minimum_fee)
        assert client.does_account_exists(test_account.public_address)
        print('Test account created')

        accounts = [Keypair() for _ in range(5)]
        builder = Builder('LOCAL',
                          client.horizon,
                          fee=minimum_fee,
                          secret=root_account.keypair.secret_seed)
        for keypair in accounts:
            builder.append_create_account_op(keypair.public_address, '100')

        builder.get_sequence()
        builder.sign()
        builder.submit()

        print('Created 5 accounts')

        txs = []
        for index, account in enumerate(accounts, start=1):
            builder = Builder('LOCAL',
                              client.horizon,
                              fee=minimum_fee * index,
                              secret=account.secret_seed)
            builder.append_manage_data_op('test', 'test'.encode())
            builder.get_sequence()
            builder.sign()
            txs.append(builder)

        initial_ledger = get_latest_ledger(client)['sequence']
        print(f'Initial ledger: {initial_ledger}')
        while initial_ledger == get_latest_ledger(client)['sequence']:
            time.sleep(0.5)

        first_populated_ledger = initial_ledger + 2
        second_populated_ledger = initial_ledger + 3

        print(f'Sending on ledger: {first_populated_ledger}')

        print(f'Sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')
        await send_txs(txs)
        print(f'Done sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')

        first_ledger_txs = client.horizon.ledger_transactions(
            first_populated_ledger)['_embedded']['records']
        second_ledger_txs = client.horizon.ledger_transactions(
            second_populated_ledger)['_embedded']['records']

        # First ledger should have txs where fee>=300
        first_txs = sum(1 for tx in first_ledger_txs if tx['fee_paid'] >= 300)
        assert first_txs == 3

        print('Verified first ledger')

        # Second ledger should have txs where fee<=200
        second_txs = sum(1 for tx in second_ledger_txs
                         if tx['fee_paid'] <= 200)
        assert second_txs == 2

        print('Verified seconds ledger')
    except:
        raise
    finally:
        # Set tx size to what it was before
        requests.get(
            f'http://localhost:11626/upgrades?mode=set&maxtxsize={initial_ledger_size}&upgradetime=2018-10-15T18:34:00Z'
        )
async def main():
    # Create the environment
    local_env = Environment('LOCAL', 'http://localhost:8000', PASSPHRASE,
                            'http://localhost:8001')

    # Create a client
    client = KinClient(local_env)
    print('Client created')

    initial_ledger_size = get_latest_ledger(client)['max_tx_set_size']
    try:
        # Set ledger tx size to 3
        requests.get(
            'http://localhost:11626/upgrades?mode=set&maxtxsize=3&upgradetime=2018-10-15T18:34:00Z'
        )

        # Create the root account object
        root_account = client.kin_account(
            derive_root_account(PASSPHRASE).secret_seed)
        print('Root account object created')

        minimum_fee = client.get_minimum_fee()
        # Create an account with 0 base reserve
        test_account = Keypair()
        root_account.create_account(test_account.public_address, 0,
                                    minimum_fee)
        assert client.does_account_exists(test_account.public_address)
        print('Test account created')

        # Add the account to the whitelist
        if not client.does_account_exists(
                WHITELIST_MANAGER_KEYPAIR.public_address):
            root_account.create_account(
                WHITELIST_MANAGER_KEYPAIR.public_address, 10000, 100)
        print('Created whitelisting account')

        builder = Builder('LOCAL',
                          client.horizon,
                          fee=minimum_fee,
                          secret=WHITELIST_MANAGER_KEYPAIR.secret_seed)
        builder.get_sequence()
        builder.append_manage_data_op(test_account.public_address,
                                      test_account._hint)
        builder.sign()
        builder.submit()

        print('Added account to whitelist')

        accounts = [Keypair() for _ in range(5)]
        builder = Builder('LOCAL',
                          client.horizon,
                          fee=minimum_fee,
                          secret=root_account.keypair.secret_seed)
        for keypair in accounts:
            builder.append_create_account_op(keypair.public_address, '100')

        builder.get_sequence()
        builder.sign()
        builder.submit()

        print('Created 5 accounts')

        txs = []
        for account in accounts:
            builder = Builder('LOCAL',
                              client.horizon,
                              fee=minimum_fee,
                              secret=account.secret_seed)
            builder.append_manage_data_op('test', 'test'.encode())
            builder.get_sequence()
            builder.sign()
            txs.append(builder)

        for tx in txs[2:]:
            tx.sign(test_account.secret_seed)

        print('Whitelisted 3 transactions')

        initial_ledger = get_latest_ledger(client)['sequence']
        print(f'Initial ledger: {initial_ledger}')
        while initial_ledger == get_latest_ledger(client)['sequence']:
            time.sleep(0.5)

        first_populated_ledger = initial_ledger + 2
        second_populated_ledger = initial_ledger + 3

        print(f'Sending on ledger: {first_populated_ledger}')

        print(f'Sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')
        await send_txs(txs)
        print(f'Done sending txs at {time.strftime("%d/%m/%Y %H:%M:%S")}')

        first_ledger_txs = client.horizon.ledger_transactions(
            first_populated_ledger)['_embedded']['records']
        second_ledger_txs = client.horizon.ledger_transactions(
            second_populated_ledger)['_embedded']['records']

        # First ledger should have 2 whitelisted txs, and 1 non-whitelisted
        whitelisted_amount = sum(1 for tx in first_ledger_txs
                                 if len(tx['signatures']) == 2)
        assert whitelisted_amount == 2

        regular_amount = sum(1 for tx in first_ledger_txs
                             if len(tx['signatures']) == 1)
        assert regular_amount == 1

        # # Second ledger should have 1 whitelisted tx, and 1 non-whitelisted
        whitelisted_amount = sum(1 for tx in second_ledger_txs
                                 if len(tx['signatures']) == 2)
        assert whitelisted_amount == 1

        regular_amount = sum(1 for tx in second_ledger_txs
                             if len(tx['signatures']) == 1)
        assert regular_amount == 1

    except:
        raise
    finally:
        # Set tx size to what it was before
        requests.get(
            f'http://localhost:11626/upgrades?mode=set&maxtxsize={initial_ledger_size}&upgradetime=2018-10-15T18:34:00Z'
        )
async def main():
    # Create the environment
    local_env = Environment('LOCAL', 'http://localhost:8000', PASSPHRASE,
                            'http://localhost:8001')

    # Create a client
    client = KinClient(local_env)
    print('Client created')

    initial_ledger_size = get_latest_ledger(client)['max_tx_set_size']
    try:
        # Set ledger tx size to 1
        requests.get(
            'http://localhost:11626/upgrades?mode=set&maxtxsize=1&upgradetime=2018-10-15T18:34:00Z'
        )

        # Create the root account object
        root_account = client.kin_account(
            derive_root_account(PASSPHRASE).secret_seed)
        print('Root account object created')

        minimum_fee = client.get_minimum_fee()
        # Create an account with 0 base reserve
        test_account = Keypair()
        root_account.create_account(test_account.public_address, 0,
                                    minimum_fee)
        assert client.does_account_exists(test_account.public_address)
        print('Test account created')

        # Add the account to the whitelist
        if not client.does_account_exists(
                WHITELIST_MANAGER_KEYPAIR.public_address):
            root_account.create_account(
                WHITELIST_MANAGER_KEYPAIR.public_address, 10000, 100)
        print('Created whitelisting account')

        initial_ledger = get_latest_ledger(client)['sequence']

        print(f'Adding account to whitelist on ledger: {initial_ledger + 2}')

        builder = Builder('LOCAL',
                          client.horizon,
                          fee=minimum_fee,
                          secret=WHITELIST_MANAGER_KEYPAIR.secret_seed)
        builder.get_sequence()
        builder.append_manage_data_op(test_account.public_address,
                                      test_account._hint)
        builder.sign()
        builder.submit()

        print('Added account to whitelist')

        while initial_ledger + 1 == get_latest_ledger(client)['sequence']:
            time.sleep(0.5)

        print(
            f'Submitting tx from test account on ledger: {initial_ledger + 3}')

        builder = Builder('LOCAL',
                          client.horizon,
                          fee=0,
                          secret=test_account.secret_seed)
        builder.append_manage_data_op('test', 'test'.encode())
        builder.get_sequence()
        builder.sign()
        builder.submit()

        while initial_ledger + 2 == get_latest_ledger(client)['sequence']:
            time.sleep(0.5)

        populated_ledger_txs = client.horizon.ledger_transactions(
            initial_ledger + 3)['_embedded']['records']
        assert len(populated_ledger_txs) == 1
        assert populated_ledger_txs[0]['fee_paid'] == 0

    except:
        raise
    finally:
        # Set tx size to what it was before
        requests.get(
            f'http://localhost:11626/upgrades?mode=set&maxtxsize={initial_ledger_size}&upgradetime=2018-10-15T18:34:00Z'
        )