Ejemplo n.º 1
0
 def _mk_wallet(name: str, sk: ZethAddressPriv) -> Wallet:
     wallet_dir = join(mock.TEST_NOTE_DIR, name + "-erc")
     if exists(wallet_dir):
         # Note: symlink-attack resistance
         #   https://docs.python.org/3/library/shutil.html#shutil.rmtree.avoids_symlink_attacks
         shutil.rmtree(wallet_dir)
     return Wallet(mixer_instance, name, wallet_dir, sk)
Ejemplo n.º 2
0
def open_wallet(mixer_instance: Any, js_secret: ZethAddressPriv, username: str,
                mids: List[int], next_addrs: List[int]) -> Wallet:
    """
    Load a wallet using a secret key.
    """
    wallet_dir = "{}/{}/{}".format(USER_DIR, username, WALLET_DIR_DEFAULT)
    return Wallet(mixer_instance, username, wallet_dir, js_secret, mids,
                  next_addrs)
Ejemplo n.º 3
0
def open_wallet(
        mixer_instance: Any,
        js_secret: ZethAddressPriv,
        ctx: ClientConfig) -> Wallet:
    """
    Load a wallet using a secret key.
    """
    wallet_dir = ctx.wallet_dir
    return Wallet(mixer_instance, WALLET_USERNAME, wallet_dir, js_secret)
Ejemplo n.º 4
0
def make_wallet(mid: int, next_addr: int) -> List[Wallet]:
    '''
    Return all the wallet in local server
    '''
    wallet_list = []
    for username in os.listdir(USER_DIR):
        wallet_dir = "{}/{}/{}".format(USER_DIR, username, WALLET_DIR_DEFAULT)
        zeth_address = load_zeth_address(username)
        wallet_list.append(
            Wallet(None, username, wallet_dir, zeth_address.addr_sk, mid,
                   next_addr))
    return wallet_list
Ejemplo n.º 5
0
def main() -> None:
    zksnark = zeth.zksnark.get_zksnark_provider(zeth.utils.parse_zksnark_arg())

    # Zeth addresses
    keystore = mock.init_test_keystore()
    # Depth of the merkle tree (need to match the one used in the cpp prover)
    mk_tree_depth = constants.ZETH_MERKLE_TREE_DEPTH
    # Ethereum addresses
    deployer_eth_address = eth.accounts[0]
    bob_eth_address = eth.accounts[1]
    alice_eth_address = eth.accounts[2]
    charlie_eth_address = eth.accounts[3]

    prover_client = ProverClient(TEST_GRPC_ENDPOINT)

    coinstore_dir = os.environ['ZETH_COINSTORE']

    # Keys and wallets
    k_sk_alice = keystore["Alice"].addr_sk.k_sk
    k_sk_bob = keystore["Bob"].addr_sk.k_sk
    k_sk_charlie = keystore["Charlie"].addr_sk.k_sk

    alice_wallet = Wallet("alice", coinstore_dir, k_sk_alice)
    bob_wallet = Wallet("bob", coinstore_dir, k_sk_bob)
    charlie_wallet = Wallet("charlie", coinstore_dir, k_sk_charlie)

    print("[INFO] 1. Fetching the verification key from the proving server")
    vk = prover_client.get_verification_key()

    print("[INFO] 2. Received VK, writing the key...")
    zeth.joinsplit.write_verification_key(vk, zksnark)

    print("[INFO] 3. VK written, deploying the smart contracts...")
    (proof_verifier_interface, otsig_verifier_interface, mixer_interface) = \
        zeth.contracts.compile_contracts(zksnark)
    hasher_interface, _ = zeth.contracts.compile_util_contracts()
    (mixer_instance, initial_root) = zeth.contracts.deploy_contracts(
        mk_tree_depth,
        proof_verifier_interface,
        otsig_verifier_interface,
        mixer_interface,
        hasher_interface,
        deployer_eth_address,
        4000000,
        # We mix Ether in this test, so we set the addr of the ERC20 contract
        # to be 0x0
        "0x0000000000000000000000000000000000000000",
        zksnark
    )

    zeth_client = zeth.joinsplit.ZethClient(
        prover_client, mixer_instance, zksnark)

    print("[INFO] 4. Running tests (asset mixed: Ether)...")
    print("- Initial balances: ")
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address)

    # Bob deposits ETH, split in 2 notes on the mixer
    result_deposit_bob_to_bob = scenario.bob_deposit(
        zeth_client,
        initial_root,
        bob_eth_address,
        keystore,
        mk_tree_depth
    )
    new_merkle_root_bob_to_bob = result_deposit_bob_to_bob.new_merkle_root

    print("- Balances after Bob's deposit: ")
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address
    )

    # Alice sees a deposit and tries to decrypt the ciphertexts to see if she
    # was the recipient but she wasn't the recipient (Bob was), so she fails to
    # decrypt
    recovered_notes_alice = alice_wallet.receive_notes(
        result_deposit_bob_to_bob.encrypted_notes,
        result_deposit_bob_to_bob.sender_k_pk)
    assert(len(recovered_notes_alice) == 0), \
        "Alice decrypted a ciphertext that was not encrypted with her key!"

    # Bob does a transfer to Charlie on the mixer

    # Bob decrypts one of the note he previously received (useless here but
    # useful if the payment came from someone else)
    recovered_notes_bob = bob_wallet.receive_notes(
        result_deposit_bob_to_bob.encrypted_notes,
        result_deposit_bob_to_bob.sender_k_pk)
    assert(len(recovered_notes_bob) == 2), \
        f"Bob recovered {len(recovered_notes_bob)} notes from deposit, expected 2"
    bob_to_charlie = recovered_notes_bob[0]

    # Execution of the transfer
    result_transfer_bob_to_charlie = scenario.bob_to_charlie(
        zeth_client,
        new_merkle_root_bob_to_bob,
        bob_to_charlie,
        bob_eth_address,
        keystore,
        mk_tree_depth)

    new_merkle_root_bob_to_charlie = \
        result_transfer_bob_to_charlie.new_merkle_root

    # Bob tries to spend `input_note_bob_to_charlie` twice
    result_double_spending = None
    try:
        result_double_spending = scenario.bob_to_charlie(
            zeth_client,
            new_merkle_root_bob_to_bob,
            bob_to_charlie,
            bob_eth_address,
            keystore,
            mk_tree_depth)
    except Exception as e:
        print(f"Bob's double spending successfully rejected! (msg: {e})")
    assert(result_double_spending is None), \
        "Bob managed to spend the same note twice!"

    print("- Balances after Bob's transfer to Charlie: ")
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address
    )

    # Charlie recovers his notes and attempts to withdraw them.
    notes_charlie = charlie_wallet.receive_notes(
        result_transfer_bob_to_charlie.encrypted_notes,
        result_transfer_bob_to_charlie.sender_k_pk)
    assert(len(notes_charlie) == 1), \
        f"Charlie decrypted {len(notes_charlie)}.  Expected 1!"

    input_charlie_withdraw = notes_charlie[0]
    assert input_charlie_withdraw[0] == \
        result_transfer_bob_to_charlie.encrypted_notes[1][0]

    result_charlie_withdrawal = scenario.charlie_withdraw(
        zeth_client,
        new_merkle_root_bob_to_charlie,
        input_charlie_withdraw,
        charlie_eth_address,
        keystore,
        mk_tree_depth)
    new_merkle_root_charlie_withdrawal = result_charlie_withdrawal.new_merkle_root
    print("Balances after Charlie's withdrawal: ")
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address
    )

    # Charlie tries to double-spend by withdrawing twice the same note
    result_double_spending = None
    try:
        # New commitments are added in the tree at each withdraw so we
        # recompiute the path to have the updated nodes
        result_double_spending = scenario.charlie_double_withdraw(
            zeth_client,
            new_merkle_root_charlie_withdrawal,
            input_charlie_withdraw,
            charlie_eth_address,
            keystore,
            mk_tree_depth)
    except Exception as e:
        print(f"Charlie's double spending successfully rejected! (msg: {e})")
    print("Balances after Charlie's double withdrawal attempt: ")
    assert(result_double_spending is None), \
        "Charlie managed to withdraw the same note twice!"
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address
    )

    # Bob deposits once again ETH, split in 2 notes on the mixer
    # But Charlie attempts to corrupt the transaction (malleability attack)
    result_deposit_bob_to_bob = scenario.charlie_corrupt_bob_deposit(
        zeth_client,
        new_merkle_root_charlie_withdrawal,
        bob_eth_address,
        charlie_eth_address,
        keystore,
        mk_tree_depth)

    # Bob decrypts one of the note he previously received (should fail if
    # Charlie's attack succeeded)
    recovered_notes_bob = bob_wallet.receive_notes(
        result_deposit_bob_to_bob.encrypted_notes,
        result_deposit_bob_to_bob.sender_k_pk)
    assert(len(recovered_notes_bob) == 2), \
        f"Bob recovered {len(recovered_notes_bob)} notes from deposit, expected 2"

    print("- Balances after Bob's last deposit: ")
    print_balances(
        bob_eth_address,
        alice_eth_address,
        charlie_eth_address,
        mixer_instance.address
    )