def _load_or_create_node_key(self) -> KeyPair: if self.boot_info.args.beacon_nodekey: privkey = Secp256k1PrivateKey.new( decode_hex(self.boot_info.args.beacon_nodekey) ) key_pair = KeyPair(private_key=privkey, public_key=privkey.get_public_key()) return key_pair else: config = self.boot_info.trinity_config beacon_nodekey_path = f"{config.nodekey_path}-beacon" if os.path.isfile(beacon_nodekey_path): with open(beacon_nodekey_path, "rb") as f: key_data = f.read() private_key = Secp256k1PrivateKey.new(key_data) key_pair = KeyPair( private_key=private_key, public_key=private_key.get_public_key() ) return key_pair else: key_pair = create_new_key_pair() private_key_bytes = key_pair.private_key.to_bytes() with open(beacon_nodekey_path, "wb") as f: f.write(private_key_bytes) return key_pair
async def run(port: int, destination: str, localhost: bool, seed: int = None) -> None: if localhost: ip = "127.0.0.1" else: ip = urllib.request.urlopen("https://v4.ident.me/").read().decode( "utf8") transport_opt = f"/ip4/{ip}/tcp/{port}" if seed: import random random.seed(seed) secret_number = random.getrandbits(32 * 8) secret = secret_number.to_bytes(length=32, byteorder="big") else: import secrets secret = secrets.token_bytes(32) host = await new_node(key_pair=create_new_key_pair(secret), transport_opt=[transport_opt]) print(f"I am {host.get_id().to_string()}") await host.get_network().listen(multiaddr.Multiaddr(transport_opt)) if not destination: # its the server host.set_stream_handler(PROTOCOL_ID, _echo_stream_handler) localhost_opt = " --localhost" if localhost else "" print( f"Run 'python ./examples/echo/echo.py" + localhost_opt + f" -p {int(port) + 1} -d /ip4/{ip}/tcp/{port}/p2p/{host.get_id().pretty()}'" + " on another console.") print("Waiting for incoming connections...") else: # its the client maddr = multiaddr.Multiaddr(destination) info = info_from_p2p_addr(maddr) # Associate the peer with local ip address await host.connect(info) # Start a stream with the destination. # Multiaddress of the destination peer is fetched from the peerstore using 'peerId'. stream = await host.new_stream(info.peer_id, [PROTOCOL_ID]) msg = b"hi, there!\n" await stream.write(msg) # Notify the other side about EOF await stream.close() response = await stream.read() print(f"Sent: {msg}") print(f"Got: {response}")
def test_public_key_serialize_deserialize_round_trip(): key_pair = create_new_key_pair() public_key = key_pair.public_key public_key_bytes = public_key.serialize() another_public_key = deserialize_public_key(public_key_bytes) assert public_key == another_public_key
async def run(port: int, destination: str, seed: int = None) -> None: localhost_ip = "127.0.0.1" listen_addr = multiaddr.Multiaddr(f"/ip4/0.0.0.0/tcp/{port}") if seed: import random random.seed(seed) secret_number = random.getrandbits(32 * 8) secret = secret_number.to_bytes(length=32, byteorder="big") else: import secrets secret = secrets.token_bytes(32) host = new_host(key_pair=create_new_key_pair(secret)) async with host.run(listen_addrs=[listen_addr]): print(f"I am {host.get_id().to_string()}") if not destination: # its the server host.set_stream_handler(PROTOCOL_ID, _echo_stream_handler) print( f"Run 'python ./examples/echo/echo.py " f"-p {int(port) + 1} " f"-d /ip4/{localhost_ip}/tcp/{port}/p2p/{host.get_id().pretty()}' " "on another console.") print("Waiting for incoming connections...") await trio.sleep_forever() else: # its the client maddr = multiaddr.Multiaddr(destination) info = info_from_p2p_addr(maddr) # Associate the peer with local ip address await host.connect(info) # Start a stream with the destination. # Multiaddress of the destination peer is fetched from the peerstore using 'peerId'. stream = await host.new_stream(info.peer_id, [PROTOCOL_ID]) msg = b"hi, there!\n" await stream.write(msg) # Notify the other side about EOF await stream.close() response = await stream.read() print(f"Sent: {msg}") print(f"Got: {response}")
async def test_create_secure_session(nursery): local_nonce = b"\x01" * NONCE_SIZE local_key_pair = create_new_key_pair(b"a") local_peer = ID.from_pubkey(local_key_pair.public_key) remote_nonce = b"\x02" * NONCE_SIZE remote_key_pair = create_new_key_pair(b"b") remote_peer = ID.from_pubkey(remote_key_pair.public_key) async with raw_conn_factory(nursery) as conns: local_conn, remote_conn = conns local_secure_conn, remote_secure_conn = None, None async def local_create_secure_session(): nonlocal local_secure_conn local_secure_conn = await create_secure_session( local_nonce, local_peer, local_key_pair.private_key, local_conn, remote_peer, ) async def remote_create_secure_session(): nonlocal remote_secure_conn remote_secure_conn = await create_secure_session( remote_nonce, remote_peer, remote_key_pair.private_key, remote_conn) async with trio.open_nursery() as nursery_1: nursery_1.start_soon(local_create_secure_session) nursery_1.start_soon(remote_create_secure_session) msg = b"abc" await local_secure_conn.write(msg) received_msg = await remote_secure_conn.read(MAX_READ_LEN) assert received_msg == msg
async def libp2p_node(chain, event_bus): key_pair = create_new_key_pair() libp2p_node = Node( key_pair=key_pair, listen_ip="0.0.0.0", listen_port=40000, preferred_nodes=(), chain=chain, subnets=(), event_bus=event_bus, ) asyncio.ensure_future(libp2p_node.run()) await asyncio.sleep(0.01) return libp2p_node
async def test_create_secure_session(): local_nonce = b"\x01" * NONCE_SIZE local_key_pair = create_new_key_pair(b"a") local_peer = ID.from_pubkey(local_key_pair.public_key) remote_nonce = b"\x02" * NONCE_SIZE remote_key_pair = create_new_key_pair(b"b") remote_peer = ID.from_pubkey(remote_key_pair.public_key) local_conn = InMemoryConnection(local_peer, is_initiator=True) remote_conn = InMemoryConnection(remote_peer) local_pipe_task = asyncio.ensure_future( create_pipe(local_conn, remote_conn)) remote_pipe_task = asyncio.ensure_future( create_pipe(remote_conn, local_conn)) local_session_builder = create_secure_session(local_nonce, local_peer, local_key_pair.private_key, local_conn, remote_peer) remote_session_builder = create_secure_session(remote_nonce, remote_peer, remote_key_pair.private_key, remote_conn) local_secure_conn, remote_secure_conn = await asyncio.gather( local_session_builder, remote_session_builder) msg = b"abc" await local_secure_conn.write(msg) received_msg = await remote_secure_conn.read() assert received_msg == msg await asyncio.gather(local_secure_conn.close(), remote_secure_conn.close()) local_pipe_task.cancel() remote_pipe_task.cancel() await local_pipe_task await remote_pipe_task
def __init__( self, local_node_key: PrivateKey, eth2_config: Eth2Config, chain_config: BeaconChainConfig, database_dir: Path, chain_class: Type[BaseBeaconChain], time_provider: TimeProvider = get_unix_time, ) -> None: self._local_key_pair = create_new_key_pair(local_node_key.to_bytes()) self._eth2_config = eth2_config self._clock = _mk_clock(eth2_config, chain_config.genesis_time, time_provider) self._base_db = LevelDB(db_path=database_dir) self._chain_db = BeaconChainDB(self._base_db, eth2_config) if not is_beacon_database_initialized(self._chain_db): initialize_beacon_database(chain_config, self._chain_db, self._base_db) self._chain = chain_class(self._base_db, eth2_config)
def do_start(self) -> None: trinity_config = self.boot_info.trinity_config beacon_app_config = trinity_config.get_app_config(BeaconAppConfig) base_db = DBClient.connect(trinity_config.database_ipc_path) chain_config = beacon_app_config.get_chain_config() attestation_pool = AttestationPool() chain = chain_config.beacon_chain_class(base_db, attestation_pool, chain_config.genesis_config) key_pair: KeyPair if self.boot_info.args.beacon_nodekey: privkey = Secp256k1PrivateKey( bytes.fromhex(self.boot_info.args.beacon_nodekey)) key_pair = KeyPair(private_key=privkey, public_key=privkey.get_public_key()) else: key_pair = create_new_key_pair() # TODO: Handle `bootstrap_nodes`. libp2p_node = Node( key_pair=key_pair, listen_ip="127.0.0.1", # FIXME: Should be configurable listen_port=self.boot_info.args.port, preferred_nodes=trinity_config.preferred_nodes, chain=chain, ) state = chain.get_state_by_slot( chain_config.genesis_config.GENESIS_SLOT) registry_pubkeys = [v_record.pubkey for v_record in state.validators] validator_privkeys = {} validator_keymap = chain_config.genesis_data.validator_keymap for pubkey in validator_keymap: validator_index = cast(ValidatorIndex, registry_pubkeys.index(pubkey)) validator_privkeys[validator_index] = validator_keymap[pubkey] def fake_get_ready_attestations_fn() -> Tuple[Attestation, ...]: return tuple() validator = Validator( chain=chain, p2p_node=libp2p_node, validator_privkeys=validator_privkeys, event_bus=self.event_bus, token=libp2p_node.cancel_token, get_ready_attestations_fn= fake_get_ready_attestations_fn, # FIXME: BCCReceiveServer.get_ready_attestations # noqa: E501 ) slot_ticker = SlotTicker( genesis_slot=chain_config.genesis_config.GENESIS_SLOT, genesis_time=chain_config.genesis_data.genesis_time, seconds_per_slot=chain_config.genesis_config.SECONDS_PER_SLOT, event_bus=self.event_bus, token=libp2p_node.cancel_token, ) asyncio.ensure_future( exit_with_services( self._event_bus_service, libp2p_node, slot_ticker, validator, )) asyncio.ensure_future(libp2p_node.run()) asyncio.ensure_future(slot_ticker.run()) asyncio.ensure_future(validator.run())
def node_key_pair(seed=b""): if isinstance(seed, str): seed = seed.encode() return create_new_key_pair(seed.rjust(32, b"\x00"))
def __init__( self, local_node_key: PrivateKey, eth2_config: Eth2Config, clock: Clock, chain: BaseBeaconChain, validator_api_port: int, client_identifier: str, p2p_maddr: Multiaddr, preferred_nodes: Collection[Multiaddr], bootstrap_nodes: Collection[Multiaddr], ) -> None: self._local_key_pair = create_new_key_pair(local_node_key.to_bytes()) self._eth2_config = eth2_config self._clock = clock self._chain = chain self._block_pool: Set[SignedBeaconBlock] = set() self._slashable_block_pool: Set[SignedBeaconBlock] = set() # FIXME: can we provide `p2p_maddr` as a default listening interface for `_mk_host`? peer_id = PeerID.from_pubkey(self._local_key_pair.public_key) if "p2p" in p2p_maddr: existing_peer_id = p2p_maddr.value_for_protocol("p2p") existing_p2p_maddr = Multiaddr(f"/p2p/{existing_peer_id}") self.logger.warning( "peer identity derived from local key pair %s overriding given identity %s", peer_id, existing_peer_id, ) p2p_maddr = p2p_maddr.decapsulate(existing_p2p_maddr) self._p2p_maddr = p2p_maddr.encapsulate(Multiaddr(f"/p2p/{peer_id}")) # TODO: persist metadata and handle updates... self._metadata_provider = lambda: MetaData.create() self._peer_updater, self._peer_updates = trio.open_memory_channel[ Tuple[PeerID, Any]](0) self._host = Host( self._local_key_pair, peer_id, self._accept_peer_updates, self._get_status, self._get_finalized_root_by_epoch, self._get_block_by_slot, self._get_block_by_root, self._metadata_provider, self._get_fork_digest, self._eth2_config, ) self._preferred_nodes = preferred_nodes self._bootstrap_nodes = bootstrap_nodes self._sync_notifier, self._sync_requests = trio.open_memory_channel[ SyncRequest](0) self._syncer = _mk_syncer() api_context = Context( client_identifier, eth2_config, self._syncer, self._chain, self._clock, _mk_block_broadcaster(self), ) self.validator_api_port = validator_api_port self._validator_api_server = _mk_validator_api_server( self.validator_api_port, api_context)
def _load_secp256k1_key_pair_from(trinity_config: TrinityConfig) -> KeyPair: return create_new_key_pair(trinity_config.nodekey.to_bytes())