def apply_create_message(self): snapshot = self.vm_state.snapshot() # EIP161 nonce incrementation with self.vm_state.state_db() as state_db: state_db.increment_nonce(self.msg.storage_address) computation = self.apply_message() if computation.is_error: self.vm_state.revert(snapshot) return computation else: contract_code = computation.output if contract_code and len(contract_code) >= EIP170_CODE_SIZE_LIMIT: computation._error = OutOfGas( "Contract code size exceeds EIP170 limit of {0}. Got code of " "size: {1}".format( EIP170_CODE_SIZE_LIMIT, len(contract_code), )) self.vm_state.revert(snapshot) elif contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.gas_meter.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation._error = err self.vm_state.revert(snapshot) else: if self.logger: self.logger.debug( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(self.msg.storage_address), len(contract_code), encode_hex(keccak(contract_code))) with self.vm_state.state_db() as state_db: state_db.set_code(self.msg.storage_address, contract_code) self.vm_state.commit(snapshot) else: self.vm_state.commit(snapshot) return computation
def validate_block(self, block): if not block.is_genesis: parent_header = get_parent_header(block.header, self.chaindb) validate_gas_limit(block.header.gas_limit, parent_header.gas_limit) validate_length_lte(block.header.extra_data, 32, title="BlockHeader.extra_data") # timestamp if block.header.timestamp < parent_header.timestamp: raise ValidationError( "`timestamp` is before the parent block's timestamp.\n" "- block : {0}\n" "- parent : {1}. ".format( block.header.timestamp, parent_header.timestamp, )) elif block.header.timestamp == parent_header.timestamp: raise ValidationError( "`timestamp` is equal to the parent block's timestamp\n" "- block : {0}\n" "- parent: {1}. ".format( block.header.timestamp, parent_header.timestamp, )) if len(block.uncles) > MAX_UNCLES: raise ValidationError( "Blocks may have a maximum of {0} uncles. Found " "{1}.".format(MAX_UNCLES, len(block.uncles))) for uncle in block.uncles: self.validate_uncle(block, uncle) if not self.state.is_key_exists(block.header.state_root): raise ValidationError("`state_root` was not found in the db.\n" "- state_root: {0}".format( block.header.state_root, )) local_uncle_hash = keccak(rlp.encode(block.uncles)) if local_uncle_hash != block.header.uncles_hash: raise ValidationError( "`uncles_hash` and block `uncles` do not match.\n" " - num_uncles : {0}\n" " - block uncle_hash : {1}\n" " - header uncle_hash: {2}".format( len(block.uncles), local_uncle_hash, block.header.uncle_hash, ))
def create_auth_message(self, nonce: bytes) -> bytes: ecdh_shared_secret = ecies.ecdh_agree(self.privkey, self.remote.pubkey) secret_xor_nonce = sxor(ecdh_shared_secret, nonce) # S(ephemeral-privk, ecdh-shared-secret ^ nonce) S = self.ephemeral_privkey.sign_msg_hash(secret_xor_nonce).to_bytes() # S || H(ephemeral-pubk) || pubk || nonce || 0x0 return ( S + keccak(self.ephemeral_pubkey.to_bytes()) + self.pubkey.to_bytes() + nonce + b'\x00' )
def sha3(computation): start_position, size = computation.stack.pop(num_items=2, type_hint=constants.UINT256) computation.extend_memory(start_position, size) sha3_bytes = computation.memory.read(start_position, size) word_count = ceil32(len(sha3_bytes)) // 32 gas_cost = constants.GAS_SHA3WORD * word_count computation.gas_meter.consume_gas(gas_cost, reason="SHA3: word gas cost") result = keccak(sha3_bytes) computation.stack.push(result)
def _unpack(message: AnyStr) -> Tuple[datatypes.PublicKey, int, List[Any], AnyStr]: """Unpack a UDP message received from a remote node. Returns the public key used to sign the message, the cmd ID, payload and hash. """ message_hash = message[:MAC_SIZE] if message_hash != keccak(message[MAC_SIZE:]): raise WrongMAC() signature = keys.Signature(message[MAC_SIZE:HEAD_SIZE]) signed_data = message[HEAD_SIZE:] remote_pubkey = signature.recover_public_key_from_msg(signed_data) cmd_id = safe_ord(message[HEAD_SIZE]) cmd = CMD_ID_MAP[cmd_id] payload = rlp.decode(message[HEAD_SIZE + 1:], strict=False) # Ignore excessive list elements as required by EIP-8. payload = payload[:cmd.elem_count] return remote_pubkey, cmd_id, payload, message_hash
def msg_handler(self, peer: BasePeer, cmd: protocol.Command, msg: protocol._DecodedMsgType) -> None: """The callback passed to BasePeer, called for every incoming message.""" peer = cast(ETHPeer, peer) if isinstance(cmd, eth.NodeData): self.logger.debug("Processing NodeData with %d entries" % len(msg)) for node in msg: self._total_processed_nodes += 1 node_key = keccak(node) try: self.scheduler.process([(node_key, node)]) except SyncRequestAlreadyProcessed: # This means we received a node more than once, which can happen when we retry # after a timeout. pass # A node may be received more than once, so pop() with a default value. self._pending_nodes.pop(node_key, None)
def import_block(self, block): self.configure_header( coinbase=block.header.coinbase, gas_limit=block.header.gas_limit, timestamp=block.header.timestamp, extra_data=block.header.extra_data, mix_hash=block.header.mix_hash, nonce=block.header.nonce, uncles_hash=keccak(rlp.encode(block.uncles)), ) # run all of the transactions. for transaction in block.transactions: self.apply_transaction(transaction) # transfer the list of uncles. self.block.uncles = block.uncles return self.mine_block()
def pack_block(self, block, *args, **kwargs): """ Pack block for mining. :param bytes coinbase: 20-byte public address to receive block reward :param bytes uncles_hash: 32 bytes :param bytes state_root: 32 bytes :param bytes transaction_root: 32 bytes :param bytes receipt_root: 32 bytes :param int bloom: :param int gas_used: :param bytes extra_data: 32 bytes :param bytes mix_hash: 32 bytes :param bytes nonce: 8 bytes """ if 'uncles' in kwargs: block.uncles = kwargs.pop('uncles') kwargs.setdefault('uncles_hash', keccak(rlp.encode(block.uncles))) header = block.header provided_fields = set(kwargs.keys()) known_fields = set(tuple(zip(*BlockHeader.fields))[0]) unknown_fields = provided_fields.difference(known_fields) if unknown_fields: raise AttributeError( "Unable to set the field(s) {0} on the `BlockHeader` class. " "Received the following unexpected fields: {1}.".format( ", ".join(known_fields), ", ".join(unknown_fields), ) ) for key, value in kwargs.items(): setattr(header, key, value) # Perform validation self.state.validate_block(block) return block
def apply_create_message(self): snapshot = self.vm_state.snapshot() computation = self.apply_message() if computation.is_error: self.vm_state.revert(snapshot) return computation else: contract_code = computation.output if contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.gas_meter.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation._error = err self.vm_state.revert(snapshot) else: if self.logger: self.logger.debug( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(self.msg.storage_address), len(contract_code), encode_hex(keccak(contract_code))) with self.vm_state.state_db() as state_db: state_db.set_code(self.msg.storage_address, contract_code) self.vm_state.commit(snapshot) else: self.vm_state.commit(snapshot) return computation
def _apply_homestead_create_message(vm, message): snapshot = vm.snapshot() computation = vm.apply_message(message) if computation.error: vm.revert(snapshot) return computation else: contract_code = computation.output if contract_code: contract_code_gas_cost = len( contract_code) * constants.GAS_CODEDEPOSIT try: computation.gas_meter.consume_gas( contract_code_gas_cost, reason="Write contract code for CREATE", ) except OutOfGas as err: # Different from Frontier: reverts state on gas failure while # writing contract code. computation.error = err vm.revert(snapshot) else: if vm.logger: vm.logger.debug( "SETTING CODE: %s -> length: %s | hash: %s", encode_hex(message.storage_address), len(contract_code), encode_hex(keccak(contract_code))) with vm.state_db() as state_db: state_db.set_code(message.storage_address, contract_code) vm.commit(snapshot) else: vm.commit(snapshot) return computation
def mine(self, **kwargs): """ - `coinbase` - `uncles_hash` - `state_root` - `transaction_root` - `receipt_root` - `bloom` - `gas_used` - `extra_data` - `mix_hash` - `nonce` """ if 'uncles' in kwargs: self.uncles = kwargs.pop('uncles') kwargs.setdefault('uncles_hash', keccak(rlp.encode(self.uncles))) header = self.header provided_fields = set(kwargs.keys()) known_fields = set(tuple(zip(*BlockHeader.fields))[0]) unknown_fields = provided_fields.difference(known_fields) if unknown_fields: raise AttributeError( "Unable to set the field(s) {0} on the `BlockHeader` class. " "Received the following unexpected fields: {0}.".format( ", ".join(known_fields), ", ".join(unknown_fields), )) for key, value in kwargs.items(): setattr(header, key, value) # Perform validation self.validate() return self
def __contains__(self, key): return keccak(key) in self._trie
def add_uncle(self, uncle): self.uncles.append(uncle) self.header.uncles_hash = keccak(rlp.encode(self.uncles)) return self
def ecdsa_sign(self, msg, private_key): v, r, s = self.ecdsa_raw_sign(keccak(msg), private_key) signature = encode_signature(v, r, s) return signature
def random_node(): seed = force_bytes("".join(random.sample(string.ascii_lowercase, 10))) priv_key = keys.PrivateKey(keccak(seed)) return kademlia.Node(priv_key.public_key, random_address())
def get_discovery_protocol(seed=b"seed"): privkey = keys.PrivateKey(keccak(seed)) return discovery.DiscoveryProtocol(privkey, random_address(), bootstrap_nodes=[])
def __setitem__(self, key, value): self._trie[keccak(key)] = value
def __getitem__(self, key): return self._trie[keccak(key)]
def _execute_frontier_transaction(vm_state, transaction): # Reusable for other forks # # 1) Pre Computation # # Validate the transaction transaction.validate() vm_state.validate_transaction(transaction) gas_fee = transaction.gas * transaction.gas_price with vm_state.state_db() as state_db: # Buy Gas state_db.delta_balance(transaction.sender, -1 * gas_fee) # Increment Nonce state_db.increment_nonce(transaction.sender) # Setup VM Message message_gas = transaction.gas - transaction.intrinsic_gas if transaction.to == constants.CREATE_CONTRACT_ADDRESS: contract_address = generate_contract_address( transaction.sender, state_db.get_nonce(transaction.sender) - 1, ) data = b'' code = transaction.data else: contract_address = None data = transaction.data code = state_db.get_code(transaction.to) vm_state.logger.info( ("TRANSACTION: sender: %s | to: %s | value: %s | gas: %s | " "gas-price: %s | s: %s | r: %s | v: %s | data-hash: %s"), encode_hex(transaction.sender), encode_hex(transaction.to), transaction.value, transaction.gas, transaction.gas_price, transaction.s, transaction.r, transaction.v, encode_hex(keccak(transaction.data)), ) message = Message( gas=message_gas, to=transaction.to, sender=transaction.sender, value=transaction.value, data=data, code=code, create_address=contract_address, ) transaction_context = vm_state.get_transaction_context_class()( gas_price=transaction.gas_price, origin=transaction.sender, ) # # 2) Apply the message to the VM. # if message.is_create: with vm_state.state_db(read_only=True) as state_db: is_collision = state_db.account_has_code_or_nonce(contract_address) if is_collision: # The address of the newly created contract has *somehow* collided # with an existing contract address. computation = vm_state.get_computation(message, transaction_context) computation._error = ContractCreationCollision( "Address collision while creating contract: {0}".format( encode_hex(contract_address), )) vm_state.logger.debug( "Address collision while creating contract: %s", encode_hex(contract_address), ) else: computation = vm_state.get_computation( message, transaction_context, ).apply_create_message() else: computation = vm_state.get_computation( message, transaction_context).apply_message() # # 2) Post Computation # # Self Destruct Refunds num_deletions = len(computation.get_accounts_for_deletion()) if num_deletions: computation.gas_meter.refund_gas(REFUND_SELFDESTRUCT * num_deletions) # Gas Refunds gas_remaining = computation.get_gas_remaining() gas_refunded = computation.get_gas_refund() gas_used = transaction.gas - gas_remaining gas_refund = min(gas_refunded, gas_used // 2) gas_refund_amount = (gas_refund + gas_remaining) * transaction.gas_price if gas_refund_amount: vm_state.logger.debug( 'TRANSACTION REFUND: %s -> %s', gas_refund_amount, encode_hex(message.sender), ) with vm_state.state_db() as state_db: state_db.delta_balance(message.sender, gas_refund_amount) # Miner Fees transaction_fee = (transaction.gas - gas_remaining - gas_refund) * transaction.gas_price vm_state.logger.debug( 'TRANSACTION FEE: %s -> %s', transaction_fee, encode_hex(vm_state.coinbase), ) with vm_state.state_db() as state_db: state_db.delta_balance(vm_state.coinbase, transaction_fee) # Process Self Destructs with vm_state.state_db() as state_db: for account, beneficiary in computation.get_accounts_for_deletion(): # TODO: need to figure out how we prevent multiple selfdestructs from # the same account and if this is the right place to put this. vm_state.logger.debug('DELETING ACCOUNT: %s', encode_hex(account)) # TODO: this balance setting is likely superflous and can be # removed since `delete_account` does this. state_db.set_balance(account, 0) state_db.delete_account(account) return computation
def hash(self): return keccak(rlp.encode(self))
b'E\xa9\x15\xe4\xd0`\x14\x9e\xb46Y`\xe6\xa7\xa4_3C\x93\t0a\x11k\x19~2@\x06_\xf2\xd8' ) PUBLIC_KEY = ( b'\x04:QAvFo\xa8\x15\xedH\x1f\xfa\xd0\x91\x10\xa2\xd3D\xf6\xc9\xb7\x8c\x1d\x14\xaf\xc3Q\xc3\xa5\x1b\xe3=\x80r\xe7y9\xdc\x03\xbaDy\x07y\xb7\xa1\x02\x5b\xaf0\x03\xf6s$0\xe2\x0c\xd9\xb7m\x953\x91\xb3' # noqa: E501 ) RAW_PUBLIC_KEY = decode_public_key(PUBLIC_KEY) ADDRESS = (b'\xa9OSt\xfc\xe5\xed\xbc\x8e*\x86\x97\xc1S1g~n\xbf\x0b') MSG = b'my message' MSG_HASH = b'#tpO\xbbmDaqK\xcb\xab\xebj\x16\x0c"E\x9ex\x1b\x08\\\x83lI\x08JG\x0e\xd6\xa4' V = 27 R = 54060028713369731575288880898058519584012347418583874062392262086259746767623 S = 41474707565615897636207177895621376369577110960831782659442889110043833138559 assert keccak(MSG) == MSG_HASH assert encode_raw_public_key(decode_public_key(PUBLIC_KEY)) == PUBLIC_KEY def test_raw_signing(): v, r, s = ecdsa_raw_sign(MSG_HASH, PRIVATE_KEY) assert ecdsa_raw_verify(MSG_HASH, (v, r, s), RAW_PUBLIC_KEY) def test_raw_recover(): raw_public_key = ecdsa_raw_recover(MSG_HASH, (V, R, S)) recovered_public_key = encode_raw_public_key(raw_public_key) assert recovered_public_key == PUBLIC_KEY
def __delitem__(self, key): del self._trie[keccak(key)]
def mining_hash(self): return keccak( rlp.encode(self, BlockHeader.exclude(['mix_hash', 'nonce'])))
async def test_lightchain_integration(request, event_loop): """Test LightChain against a local geth instance. This test assumes a geth/ropsten instance is listening on 127.0.0.1:30303 and serving light clients. In order to achieve that, simply run it with the following command line: $ geth -nodekeyhex 45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8 \ -testnet -lightserv 90 """ # TODO: Implement a pytest fixture that runs geth as above, so that we don't need to run it # manually. if not pytest.config.getoption("--integration"): pytest.skip("Not asked to run integration tests") chaindb = ChainDB(MemoryDB()) chaindb.persist_header_to_db(ROPSTEN_GENESIS_HEADER) peer_pool = LocalGethPeerPool(LESPeer, chaindb, ROPSTEN_NETWORK_ID, ecies.generate_privkey()) chain = IntegrationTestLightChain(chaindb, peer_pool) asyncio.ensure_future(peer_pool.run()) asyncio.ensure_future(chain.run()) await asyncio.sleep( 0) # Yield control to give the LightChain a chance to start def finalizer(): event_loop.run_until_complete(peer_pool.stop()) event_loop.run_until_complete(chain.stop()) request.addfinalizer(finalizer) n = 11 # Wait for the chain to sync a few headers. async def wait_for_header_sync(block_number): while chaindb.get_canonical_head().block_number < block_number: await asyncio.sleep(0.1) await asyncio.wait_for(wait_for_header_sync(n), 2) # https://ropsten.etherscan.io/block/11 b = await chain.get_canonical_block_by_number(n) assert isinstance(b, FrontierBlock) assert b.number == 11 assert encode_hex(b.hash) == ( '0xda882aeff30f59eda9da2b3ace3023366ab9d4219b5a83cdd589347baae8678e') assert len(b.transactions) == 15 assert isinstance(b.transactions[0], b.transaction_class) receipts = await chain.get_receipts(b.hash) assert len(receipts) == 15 assert encode_hex(keccak(rlp.encode(receipts[0]))) == ( '0xf709ed2c57efc18a1675e8c740f3294c9e2cb36ba7bb3b89d3ab4c8fef9d8860') assert len(chain.peer_pool.peers) == 1 head_info = chain.peer_pool.peers[0].head_info head = await chain.get_block_by_hash(head_info.block_hash) assert head.number == head_info.block_number # In order to answer queries for contract code, geth needs the state trie entry for the block # we specify in the query, but because of fast sync we can only assume it has that for recent # blocks, so we use the current head to lookup the code for the contract below. # https://ropsten.etherscan.io/address/0x95a48dca999c89e4e284930d9b9af973a7481287 contract_addr = decode_hex('95a48dca999c89e4e284930d9b9af973a7481287') contract_code = await chain.get_contract_code(head.hash, keccak(contract_addr)) assert encode_hex(keccak(contract_code)) == ( '0x1e0b2ad970b365a217c40bcf3582cbb4fcc1642d7a5dd7a82ae1e278e010123e') account = await chain.get_account(head.hash, contract_addr) assert account.code_hash == keccak(contract_code) assert account.balance == 0
def test_persist_header_to_db_unknown_parent(chaindb, header, seed): header.parent_hash = keccak(seed) with pytest.raises(ParentNotFound): chaindb.persist_header_to_db(header)
async def get_account(self, block_hash: bytes, address: bytes) -> Account: key = keccak(address) proof = await self._get_proof(block_hash, account_key=b'', key=key) header = await self.get_block_header_by_hash(block_hash) rlp_account = HexaryTrie.get_from_proof(header.state_root, key, proof) return rlp.decode(rlp_account, sedes=Account)
async def _get_directly_linked_peers_without_handshake(peer1_class=LESPeer, peer1_chaindb=None, peer2_class=LESPeer, peer2_chaindb=None): """See get_directly_linked_peers(). Neither the P2P handshake nor the sub-protocol handshake will be performed here. """ if peer1_chaindb is None: peer1_chaindb = get_fresh_mainnet_chaindb() if peer2_chaindb is None: peer2_chaindb = get_fresh_mainnet_chaindb() peer1_private_key = ecies.generate_privkey() peer2_private_key = ecies.generate_privkey() peer1_remote = kademlia.Node(peer2_private_key.public_key, kademlia.Address('0.0.0.0', 0, 0)) peer2_remote = kademlia.Node(peer1_private_key.public_key, kademlia.Address('0.0.0.0', 0, 0)) initiator = auth.HandshakeInitiator(peer1_remote, peer1_private_key) peer2_reader = asyncio.StreamReader() peer1_reader = asyncio.StreamReader() # Link the peer1's writer to the peer2's reader, and the peer2's writer to the # peer1's reader. peer2_writer = type("mock-streamwriter", (object, ), { "write": peer1_reader.feed_data, "close": lambda: None }) peer1_writer = type("mock-streamwriter", (object, ), { "write": peer2_reader.feed_data, "close": lambda: None }) peer1, peer2 = None, None handshake_finished = asyncio.Event() async def do_handshake(): nonlocal peer1, peer2 aes_secret, mac_secret, egress_mac, ingress_mac = await auth._handshake( initiator, peer1_reader, peer1_writer) # Need to copy those before we pass them on to the Peer constructor because they're # mutable. Also, the 2nd peer's ingress/egress MACs are reversed from the first peer's. peer2_ingress = egress_mac.copy() peer2_egress = ingress_mac.copy() peer1 = peer1_class(remote=peer1_remote, privkey=peer1_private_key, reader=peer1_reader, writer=peer1_writer, aes_secret=aes_secret, mac_secret=mac_secret, egress_mac=egress_mac, ingress_mac=ingress_mac, chaindb=peer1_chaindb, network_id=1) peer2 = peer2_class(remote=peer2_remote, privkey=peer2_private_key, reader=peer2_reader, writer=peer2_writer, aes_secret=aes_secret, mac_secret=mac_secret, egress_mac=peer2_egress, ingress_mac=peer2_ingress, chaindb=peer2_chaindb, network_id=1) handshake_finished.set() asyncio.ensure_future(do_handshake()) responder = auth.HandshakeResponder(peer2_remote, peer2_private_key) auth_msg = await peer2_reader.read(constants.ENCRYPTED_AUTH_MSG_LEN) # Can't assert return values, but checking that the decoder doesn't raise # any exceptions at least. _, _ = responder.decode_authentication(auth_msg) peer2_nonce = keccak(os.urandom(constants.HASH_LEN)) auth_ack_msg = responder.create_auth_ack_message(peer2_nonce) auth_ack_ciphertext = responder.encrypt_auth_ack_message(auth_ack_msg) peer2_writer.write(auth_ack_ciphertext) await handshake_finished.wait() return peer1, peer2
def __init__(self, pubkey, address): self.pubkey = pubkey self.address = address self.id = big_endian_to_int(keccak(pubkey.to_bytes()))
async def get_directly_linked_peers(chaindb1=None, received_msg_callback1=None, chaindb2=None, received_msg_callback2=None): """Create two LESPeers with their readers/writers connected directly. The first peer's reader will write directly to the second's writer, and vice-versa. """ if chaindb1 is None: chaindb1 = BaseChainDB(MemoryDB()) chaindb1.persist_header_to_db(MAINNET_GENESIS_HEADER) if chaindb2 is None: chaindb2 = BaseChainDB(MemoryDB()) chaindb2.persist_header_to_db(MAINNET_GENESIS_HEADER) peer1_private_key = ecies.generate_privkey() peer2_private_key = ecies.generate_privkey() peer1_remote = kademlia.Node( peer2_private_key.public_key, kademlia.Address('0.0.0.0', 0, 0)) peer2_remote = kademlia.Node( peer1_private_key.public_key, kademlia.Address('0.0.0.0', 0, 0)) initiator = auth.HandshakeInitiator(peer1_remote, peer1_private_key) peer2_reader = asyncio.StreamReader() peer1_reader = asyncio.StreamReader() # Link the peer1's writer to the peer2's reader, and the peer2's writer to the # peer1's reader. peer2_writer = type( "mock-streamwriter", (object,), {"write": peer1_reader.feed_data, "close": lambda: None} ) peer1_writer = type( "mock-streamwriter", (object,), {"write": peer2_reader.feed_data, "close": lambda: None} ) peer1, peer2 = None, None handshake_finished = asyncio.Event() async def do_handshake(): nonlocal peer1, peer2 aes_secret, mac_secret, egress_mac, ingress_mac = await auth._handshake( initiator, peer1_reader, peer1_writer) # Need to copy those before we pass them on to the Peer constructor because they're # mutable. Also, the 2nd peer's ingress/egress MACs are reversed from the first peer's. peer2_ingress = egress_mac.copy() peer2_egress = ingress_mac.copy() peer1 = LESPeerServing( remote=peer1_remote, privkey=peer1_private_key, reader=peer1_reader, writer=peer1_writer, aes_secret=aes_secret, mac_secret=mac_secret, egress_mac=egress_mac, ingress_mac=ingress_mac, chaindb=chaindb1, network_id=1, received_msg_callback=received_msg_callback1) peer2 = LESPeerServing( remote=peer2_remote, privkey=peer2_private_key, reader=peer2_reader, writer=peer2_writer, aes_secret=aes_secret, mac_secret=mac_secret, egress_mac=peer2_egress, ingress_mac=peer2_ingress, chaindb=chaindb2, network_id=1, received_msg_callback=received_msg_callback2) handshake_finished.set() asyncio.ensure_future(do_handshake()) responder = auth.HandshakeResponder(peer2_remote, peer2_private_key) auth_msg = await peer2_reader.read(constants.ENCRYPTED_AUTH_MSG_LEN) peer1_ephemeral_pubkey, peer1_nonce = responder.decode_authentication(auth_msg) peer2_nonce = keccak(os.urandom(constants.HASH_LEN)) auth_ack_msg = responder.create_auth_ack_message(peer2_nonce) auth_ack_ciphertext = responder.encrypt_auth_ack_message(auth_ack_msg) peer2_writer.write(auth_ack_ciphertext) await handshake_finished.wait() # Perform the base protocol (P2P) handshake. peer1.base_protocol.send_handshake() peer2.base_protocol.send_handshake() msg1 = await peer1.read_msg() peer1.process_msg(msg1) msg2 = await peer2.read_msg() peer2.process_msg(msg2) # Now send the handshake msg for each enabled sub-protocol. for proto in peer1.enabled_sub_protocols: proto.send_handshake(peer1._local_chain_info) for proto in peer2.enabled_sub_protocols: proto.send_handshake(peer2._local_chain_info) return peer1, peer2
from rlp.utils import decode_hex from evm.utils.keccak import keccak MSG = b'message' MSGHASH = keccak(MSG) # This is a sample of signatures generated with a known-good implementation of the ECDSA # algorithm, which we use to test our ECC backends. If necessary, it can be generated from scratch # with the following code: """ from devp2p import crypto from rlp.utils import encode_hex msg = b'message' msghash = crypto.sha3(b'message') for secret in ['alice', 'bob', 'eve']: print("'{}': dict(".format(secret)) privkey = crypto.mk_privkey(secret) pubkey = crypto.privtopub(privkey) print(" privkey='{}',".format(encode_hex(privkey))) print(" pubkey='{}',".format(encode_hex(crypto.privtopub(privkey)))) ecc = crypto.ECCx(raw_privkey=privkey) sig = ecc.sign(msghash) print(" sig='{}',".format(encode_hex(sig))) print(" raw_sig='{}')".format(crypto._decode_sig(sig))) assert crypto.ecdsa_recover(msghash, sig) == pubkey """ SECRETS = { "alice": dict( privkey=decode_hex(b'9c0257114eb9399a2985f8e75dad7600c5d89fe3824ffa99ec1c3eb8bf3b0501'),