def test_successful_reorg():
    node = p.Node(address="")
    alice_node = p.Node(address="")

    # Bob mines height=0,1,2
    b0 = p.mine_genesis_block(node, ids.bob_public_key)
    b1 = mine_block(node, ids.bob_public_key, node.chain[0], [], 1)
    # height=2 contains a bob->alice txn
    bob_to_alice = send_tx(node, ids.bob_private_key, ids.alice_public_key, 10)
    b2 = mine_block(node, ids.bob_public_key, node.chain[1], [bob_to_alice], 2)

    # Alice accepts bob's first two blocks, but not the third
    p.mine_genesis_block(alice_node, ids.bob_public_key)  # FIXME confusing
    alice_node.handle_block(b1)

    # FIXME just borrow everything up until this point from another test
    # Create and handle two blocks atop Alice's chain
    a2 = mine_block(alice_node, ids.alice_public_key, node.chain[1], [], 1)
    node.handle_block(a2)

    # Chains
    assert len(node.chain) == 3
    assert node.chain == [b0, b1, b2]
    assert len(node.branches) == 1
    assert node.branches[0] == [a2]

    # Balances
    assert (bob_to_alice.id, 0) in node.utxo_set
    assert (bob_to_alice.id, 1) in node.utxo_set
    assert node.fetch_balance(ids.alice_public_key) == 10
    assert node.fetch_balance(ids.bob_public_key) == 3 * p.BLOCK_SUBSIDY - 10

    # Use alice's node to assemble this txn b/c she doesn't have any utxos in bob's view of world
    alice_to_bob = send_tx(alice_node, ids.alice_private_key,
                           ids.bob_public_key, 20)
    a3 = mine_block(node, ids.alice_public_key, node.branches[0][0],
                    [alice_to_bob], 2)

    # Chains
    assert len(node.chain) == 4
    assert node.chain == [b0, b1, a2, a3]
    assert len(node.branches) == 1
    assert node.branches[0] == [b2]

    # Balances
    assert (bob_to_alice.id, 0) not in node.utxo_set
    assert (bob_to_alice.id, 1) not in node.utxo_set
    assert (alice_to_bob.id, 0) in node.utxo_set
    assert (alice_to_bob.id, 1) in node.utxo_set
    assert node.fetch_balance(ids.alice_public_key) == 2 * p.BLOCK_SUBSIDY - 20
    assert node.fetch_balance(ids.bob_public_key) == 2 * p.BLOCK_SUBSIDY + 20

    # Mempool
    assert len(node.mempool) == 1
    assert bob_to_alice in node.mempool
def make_node():
    node = p.Node(address="")

    # Bob mines height=0
    p.mine_genesis_block(node, ids.bob_public_key)

    return node
def new_node():
    node = p.Node(address="")

    # Bob mines height=0
    p.mine_genesis_block(node, ids.bob_public_key)

    # Alice mines height=1
    mine_block(node, ids.alice_public_key, node.chain[-1], [], 1)

    bob_balance = node.fetch_balance(ids.bob_public_key)
    alice_balance = node.fetch_balance(ids.alice_public_key)
    print(bob_balance, alice_balance)

    # Bob mines height=2,3,4 including one bob-to-alice txn
    mine_block(node, ids.bob_public_key, node.chain[-1], [], 2)
    bob_to_alice = send_tx(node, ids.bob_private_key, ids.alice_public_key, 10)
    mine_block(node, ids.bob_public_key, node.chain[-1], [bob_to_alice], 3)
    mine_block(node, ids.bob_public_key, node.chain[-1], [], 4)

    # Alice forks off 2 blocks at height=1 including one alice-to-bob txn
    mine_block(node, ids.alice_public_key, node.chain[1], [], 2)
    alice_to_bob = send_tx(node, ids.alice_private_key, ids.bob_public_key, 10)
    mine_block(node, ids.alice_public_key, node.branches[0][-1],
               [alice_to_bob], 3)

    return node
def test_block_forking_fork():
    node = p.Node(address="")

    # Bob mines height=0,1,2
    p.mine_genesis_block(node, ids.bob_public_key)
    mine_block(node, ids.bob_public_key, node.chain[0], [], 1)
    bob_block = mine_block(node, ids.bob_public_key, node.chain[1], [], 2)

    # Alice mines height=1
    first = mine_block(node, ids.alice_public_key, node.chain[0], [], 1)

    # Alice mines 2 separate blocks top of her branch, each at height 2
    second = mine_block(node, ids.alice_public_key, node.branches[0][0], [], 2)
    third = mine_block(node,
                       ids.alice_public_key,
                       node.branches[0][0], [],
                       2,
                       nonce=second.nonce + 1)

    # UTXOs and chain unaffected
    assert node.fetch_balance(ids.alice_public_key) == 0
    assert node.fetch_balance(ids.bob_public_key) == 3 * p.BLOCK_SUBSIDY

    # One more branch added, which contains alice's first block and this one
    assert len(node.chain) == 3
    assert len(node.branches) == 2
    assert node.branches[0] == [first, second]
    assert node.branches[1] == [first, third]
def test_unsuccessful_reorg():
    node = p.Node(address="")
    alice_node = p.Node(address="")

    # Bob mines height=0,1,2
    b0 = p.mine_genesis_block(node, ids.bob_public_key)
    b1 = mine_block(node, ids.bob_public_key, node.chain[0], [], 1)
    b2 = mine_block(node, ids.bob_public_key, node.chain[1], [], 2)

    # Alice accepts bob's first two blocks, but not the third
    p.mine_genesis_block(alice_node, ids.bob_public_key)  # FIXME confusing
    alice_node.handle_block(b1)

    # FIXME just borrow everything up until this point from another test
    # Create one valid block for Alice
    a2 = mine_block(alice_node, ids.alice_public_key, node.chain[1], [], 1)
    node.handle_block(a2)

    # Create one invalid block for Alice
    alice_to_bob = send_tx(alice_node, ids.alice_private_key,
                           ids.bob_public_key, 20)
    # txn invalid b/c changing amount arbitrarily after signing ...
    alice_to_bob.tx_outs[0].amount = 100000

    initial_utxo_set = deepcopy(node.utxo_set)
    initial_chain = deepcopy(node.chain)
    initial_branches = deepcopy(node.branches)

    # This block shouldn't make it into branches or chain
    a3 = mine_block(node, ids.alice_public_key, node.branches[0][0],
                    [alice_to_bob], 2)

    # UTXO, chain, branches unchanged
    assert str(node.utxo_set) == str(initial_utxo_set)  # FIXME
    assert node.chain == initial_chain
    assert node.branches == initial_branches
def test_extend_chain():
    node = p.Node(address="")

    # Bob mines height=0,1
    p.mine_genesis_block(node, ids.bob_public_key)
    block = mine_block(node, ids.bob_public_key, node.chain[0], [], 1)

    # Alice's balance unchanged, Bob received block subsidy
    assert node.fetch_balance(ids.alice_public_key) == 0
    assert node.fetch_balance(ids.bob_public_key) == 2 * p.BLOCK_SUBSIDY

    # Chain extended
    assert len(node.chain) == 2
    assert node.chain[-1] == block

    # Branches empty
    assert node.branches == []
def test_fork_chain():
    node = make_node()
    node = p.Node(address="")

    # Bob mines height=0,1
    p.mine_genesis_block(node, ids.bob_public_key)
    bob_block = mine_block(node, ids.bob_public_key, node.chain[0], [], 1)

    # Alice mines height=1 too
    alice_block = mine_block(node, ids.alice_public_key, node.chain[0], [], 1)

    # UTXO database unchanged
    assert node.fetch_balance(ids.alice_public_key) == 0
    assert node.fetch_balance(ids.bob_public_key) == 2 * p.BLOCK_SUBSIDY

    # Chain unchanged
    assert len(node.chain) == 2
    assert alice_block not in node.chain

    # One more chain with one block on it
    assert len(node.branches) == 1
    assert node.branches[0] == [alice_block]
def test_block_extending_fork():
    node = p.Node(address="")

    # Bob mines height=0,1,2
    p.mine_genesis_block(node, ids.bob_public_key)
    mine_block(node, ids.bob_public_key, node.chain[0], [], 1)
    bob_block = mine_block(node, ids.bob_public_key, node.chain[1], [], 2)

    # Alice mines height=1
    alice_block = mine_block(node, ids.alice_public_key, node.chain[0], [], 1)
    # Alice mines block on top of her branch
    alice_block = mine_block(node, ids.alice_public_key, node.branches[0][0],
                             [], 2)

    # UTXOs
    assert node.fetch_balance(ids.alice_public_key) == 0
    assert node.fetch_balance(ids.bob_public_key) == 3 * p.BLOCK_SUBSIDY

    # Now new branches
    assert len(node.chain) == 3
    assert len(node.branches) == 1
    assert len(node.branches[0]) == 2