예제 #1
0
def test_key_store_can_import_private_key(tmp_path, sample_bls_key_pairs):
    public_key, private_key = tuple(sample_bls_key_pairs.items())[0]
    encoded_private_key = private_key.to_bytes(32, "little").hex()

    key_store = KeyStore(sample_bls_key_pairs)
    key_store.import_private_key(encoded_private_key)
    assert key_store.private_key_for(public_key) == private_key
예제 #2
0
def test_key_store_can_persist_key_files(tmp_path, sample_bls_key_pairs,
                                         has_key_pairs):
    some_password = b"password"
    public_key, private_key = tuple(sample_bls_key_pairs.items())[0]
    private_key_bytes = private_key.to_bytes(32, "little")
    encoded_private_key = private_key_bytes.hex()

    if has_key_pairs:
        key_pairs = sample_bls_key_pairs
    else:
        key_pairs = {}
    key_store = KeyStore(
        key_pairs=key_pairs,
        key_store_dir=tmp_path,
        password_provider=lambda _public_key: some_password,
    )

    with key_store.persistence():
        assert not tuple(key_store._key_store_dir.iterdir())
        key_store.import_private_key(encoded_private_key)

    key_files = tuple(key_store._key_store_dir.iterdir())
    assert len(key_files) == 1

    key_file = key_files[0]
    with open(key_file) as key_file_handle:
        key_file_json = json.load(key_file_handle)
        assert decode_hex(key_file_json["public_key"]) == public_key
        assert private_key_bytes == eth_keyfile.decode_keyfile_json(
            key_file_json, some_password)
예제 #3
0
async def _import_key(logger: logging.Logger, config: Config,
                      arguments: argparse.Namespace) -> None:
    logger.info("importing private key...")
    try:
        key_store = KeyStore(
            key_store_dir=config.key_store_dir,
            password_provider=terminal_password_provider,
        )
        with key_store.persistence(should_load_existing_key_pairs=False):
            key_store.import_private_key(arguments.private_key)
    except Exception:
        logger.exception("error importing key")
예제 #4
0
파일: cli_parser.py 프로젝트: onyb/trinity
async def _main(
    logger: logging.Logger, config: Config, arguments: argparse.Namespace
) -> None:
    key_store = KeyStore.from_config(config)
    clock = Clock.from_config(config)
    beacon_node = BeaconNode.from_config(config)

    # with key_store.persistence():
    async with beacon_node:
        client = Client(key_store, clock, beacon_node)
        async with background_trio_service(client):
            await _wait_for_interrupts()
            logger.info("received interrupt; shutting down...")
예제 #5
0
async def test_beacon_node_and_validator_client_can_talk(
    autojump_clock,
    clock,
    beacon_node,
    eth2_config,
    chain_config,
    seconds_per_epoch,
    sample_bls_key_pairs,
    client_id,
    # NOTE: temporarily disable BLS while it standardizes
    no_op_bls,
):
    starting_head_slot = beacon_node._chain.get_canonical_head().slot
    assert starting_head_slot == GENESIS_SLOT

    async with trio.open_nursery() as nursery:
        await nursery.start(beacon_node.run)

        api_client = BeaconNodeClient(
            chain_config.genesis_time,
            f"http://{local_host_name}:{beacon_node.validator_api_port}",
            eth2_config.SECONDS_PER_SLOT,
        )
        async with api_client:
            # sanity check
            assert api_client.client_version == client_id

            key_store = KeyStore(sample_bls_key_pairs)
            validator = ValidatorClient(key_store, clock, api_client)

            with trio.move_on_after(seconds_per_epoch):
                async with background_trio_service(validator):
                    await trio.sleep(seconds_per_epoch * 2)
            nursery.cancel_scope.cancel()
    sent_operations_for_broadcast = api_client._broadcast_operations
    received_operations_for_broadcast = (
        beacon_node._validator_api_server.context._broadcast_operations)

    # temporary until we update to the new API
    # NOTE: with new API, remove assertion and deletion
    assert validator._duty_store._store[((1 << 64) - 1, 0)]
    del validator._duty_store._store[((1 << 64) - 1, 0)]

    # NOTE: this is the easiest condition to pass while suggesting this is working
    # As the other parts of the project shore up, we should do stricter testing to ensure
    # the operations we expect (and that they exist...) get across the gap from
    # validator to beacon node
    assert received_operations_for_broadcast.issubset(
        sent_operations_for_broadcast)
    assert beacon_node._chain.get_canonical_head().slot > starting_head_slot
예제 #6
0
def test_key_store_can_persist_key_files(tmp_path, sample_bls_key_pair):
    config = Config(
        key_store_constructor=lambda config: KeyStore.from_config(config),
        root_data_dir=tmp_path,
    )
    some_password = b"password"
    public_key, private_key = sample_bls_key_pair
    private_key_bytes = private_key.to_bytes(length=32, byteorder="big")
    encoded_private_key = private_key_bytes.hex()

    with config.key_store as key_store:
        assert not tuple(key_store._location.iterdir())
        key_store.import_private_key(encoded_private_key, some_password)

    key_files = tuple(key_store._location.iterdir())
    assert len(key_files) == 1

    key_file = key_files[0]
    with open(key_file) as key_file_handle:
        key_file_json = json.load(key_file_handle)
        assert decode_hex(key_file_json["public_key"]) == public_key
        assert private_key_bytes == eth_keyfile.decode_keyfile_json(
            key_file_json, some_password)
예제 #7
0
async def test_client_works(
    autojump_clock, sample_bls_key_pairs, seconds_per_slot, slots_per_epoch
):
    """
    This test constructs a ``Client`` with enough known inputs to compute an expected set of
    signatures after running for a given amount of time. The test fails if the expected signatures
    are not observed as outputs of the client.
    """
    slots_per_epoch = 4
    # NOTE: start 2 epochs ahead of genesis to emulate the client
    # waiting to the time it can start polling the beacon node
    # and the getting duties in the first epoch in the epoch prior to genesis
    total_epochs_to_run = 4
    epochs_before_genesis_to_start = 2
    epochs_after_genesis_to_end = total_epochs_to_run - epochs_before_genesis_to_start
    # Set genesis so that we aren't aligned with a slot, which could hide some
    # bugs we will otherwise see...
    non_aligned_time = trio.current_time() + seconds_per_slot / 3
    seconds_per_epoch = seconds_per_slot * slots_per_epoch
    genesis_time = int(
        non_aligned_time + epochs_before_genesis_to_start * seconds_per_epoch
    )

    public_key = tuple(sample_bls_key_pairs.keys())[0]
    key_store = KeyStore(sample_bls_key_pairs)
    beacon_node = MockBeaconNode(
        slots_per_epoch,
        seconds_per_slot,
        duty_fetcher=_mk_duty_fetcher(public_key, slots_per_epoch, seconds_per_slot),
    )

    clock = Clock(
        seconds_per_slot,
        genesis_time,
        slots_per_epoch,
        seconds_per_epoch,
        trio.current_time,
    )
    client = Client(key_store, clock, beacon_node)

    try:
        async with background_trio_service(client):
            await trio.sleep(total_epochs_to_run * seconds_per_epoch)
    except DaemonTaskExit:
        # NOTE: there is a race condition in ``async_service`` that will
        # trigger ``DaemonTaskExit`` when the test would otherwise pass.
        # See: https://github.com/ethereum/async-service/issues/54
        pass

    fulfilled_duties = tuple(
        filter(
            lambda duty: duty.tick_for_execution.epoch < epochs_after_genesis_to_end,
            beacon_node.given_duties,
        )
    )
    assert len(beacon_node.published_signatures) == len(fulfilled_duties)
    randao_provider = mk_randao_provider(key_store.private_key_for)
    for duty in fulfilled_duties:
        if duty.duty_type == DutyType.Attestation:
            operation = await beacon_node.fetch_attestation(
                duty.validator_public_key,
                duty.tick_for_execution.slot,
                duty.committee_index,
            )
        else:
            randao_reveal = randao_provider(
                duty.validator_public_key, duty.tick_for_execution.epoch
            )
            operation = await beacon_node.fetch_block_proposal(
                duty.tick_for_execution.slot, randao_reveal
            )

        observed_signature = beacon_node.published_signatures[duty]
        expected_signature = sign(duty, operation, key_store.private_key_for)
        assert observed_signature == expected_signature