3535
3636from p2p .exceptions import (
3737 BadLESResponse ,
38+ NoEligiblePeers ,
3839)
3940from p2p .cancel_token import CancelToken
4041from p2p import protocol
@@ -160,6 +161,15 @@ async def get_contract_code(self, block_hash: Hash32, address: Address) -> bytes
160161 :return: bytecode of the contract, ``b''`` if no code is set
161162 """
162163 peer = cast (LESPeer , self .peer_pool .highest_td_peer )
164+
165+ # get account for later verification, and
166+ # to confirm that our highest total difficulty peer has the info
167+ try :
168+ account = await self .get_account (block_hash , address )
169+ except HeaderNotFound as exc :
170+ raise NoEligiblePeers ("Our best peer does not have header %s" % block_hash ) from exc
171+
172+ # request contract code
163173 request_id = gen_request_id ()
164174 peer .sub_proto .send_get_contract_code (block_hash , keccak (address ), request_id )
165175 reply = await self ._wait_for_reply (request_id )
@@ -170,12 +180,15 @@ async def get_contract_code(self, block_hash: Hash32, address: Address) -> bytes
170180 bytecode = reply ['codes' ][0 ]
171181
172182 # validate bytecode against a proven account
173- account = await self .get_account (block_hash , address )
174-
175183 if account .code_hash == keccak (bytecode ):
176184 return bytecode
185+ elif bytecode == b'' :
186+ # TODO disambiguate failure types here, and raise the appropriate exception
187+ # An (incorrectly) empty bytecode might indicate a bad-acting peer, or it might not
188+ raise NoEligiblePeers ("Our best peer incorrectly responded with an empty code value" )
177189 else :
178- # disconnect from this bad peer
190+ # a bad-acting peer sent an invalid non-empty bytecode
191+ # disconnect from the peer
179192 await self .disconnect_peer (peer , DisconnectReason .subprotocol_error )
180193 # try again with another peer
181194 return await self .get_contract_code (block_hash , address )
0 commit comments