The Parity Light Protocol is a variation of LES designed and implemented by Parity Tech for the Parity Ethereum client. Please refer to the LES specification for information on the purpose of the light client protocol.
Like LES, PIP adopts a flow-control mechanism closely analogous to a token-bucket rate limiter where the client is expected to mirror the server token-bucket state (as exceeding the 'burstiness' depth is a violation that results in disconnection). PIP utilises Canonical Hash Tries (CHTs), which are also described in the LES documentation. Unlike LES, a PIP CHT is generated once every 2048 blocks. One 32-byte trie root is stored for every range of 2048 blocks.
The current version is pip/1. This specification was derived from the official
specification at https://wiki.parity.io
. However, the official specification has since
been deleted.
Throughout this document, and in accordance with other devp2p documents, when referring to wire message formats the following symbols apply:
[ .. , .. , .. ]
means an RLP list
a || b
means concatenation of a
and b
...
means additional list elements
After the initial RLPx handshake, the first message that must be communicated is from the server to the light peer and is a status message. Updates to information in the status message are supplied with announcements.
[[key0, value0], [key1, value1], ...]
Keys are strings. Mandatory keys and values are as follows:
"protocol_version"
1 for this PIP/1 protocol version."network_id"
0 for testnet, 1 for mainnet"total_difficulty"
integer total difficulty of the best chain as found in the block header."head_blockhash"
the hash of the best (i.e. highest total difficulty) known block."head_blocknum"
the number of the best (i.e. highest total difficulty) known block."genesisHash""
the hash of the genesis block.
Optional keys and values are as follows:
"serve_headers"
any value and key-pair present if the peer can serve header chain downloads."serve_chain_since"
present if the peer can serve Body/Receipts ODR requests starting from the given block number."serve_state_since"
present if the peer can serve Proof/Code ODR requests starting from the given block number."tx_relay"
present if the peer can relay transactions to the network."flow_control_bl"
max credits (positive integer describing the burst-depth of the token bucket),"flow_control_mrc"
the initial cost table (see below)"flow_control_mrr"
rate of recharge (positive integer of credits recharged per second)
The cost table includes a mapping of individual PIP Request/Response Messages to costs, which are applied in the token-bucket rate limiter. The Headers and Execution request messages are special cases where the cost is multiplied by the maximum number of requested header or gas requested, respectively. The table also includes a base cost, which is applied for every Request Batch.
cost_table = [base_cost, [id,cost],...]
base_cost = positive integer cost applied to a request batch.
id = identifier of an individual PIP message type
cost = positive integer to apply to cost calculations for this message type
[head_blockhash, head_blocknum, total_difficulty, reorg_depth, [key0, value0], [key1, value1], ...]
reorg_depth
is positive integer containing the reorganization depth to the common ancestor of the new head and the last announced head.- Other elements have the same meaning as in the Status message with the exception of
reorg_depth
.
[request-id, [req1, ...]]
where
request-id
is a unique scalar request identifier for request-reply correlation.[req1, ...]
is the list of request messages, as described in the PIP Request/Response Messages section.
This message, sent from client to server, requests that the given request messages should be executed. The server responds with a Response Batch.
[request-id, cr, [resp1, ...]]
where
request-id1
is the unique scalar correlating with a previously received request message.cr
is an updated amount of request credits prior to recharge events at the time of processing on the server (please see throttling below).[resp1, ...]
is the list of response messages.
There must be a response message for each request contained in the corresponding request batch. The individual responses must supply all elements of the response message specifications. The PIP protocol considers messages missing any of these elements incomplete.
[max, recharge, cost_table]
where
max
is a positive integer, the new maximum credit depth for the token bucket.recharge
a positive integer, the new recharge rate in credits per second.cost_table
is the updated Cost Table.
The server may periodically update the token-bucket parameters, such as depth, message cost and recharge rate, for the particular client. Received updates must be acknowledged with an AcknowledgeUpdate message.
This message acknowledges receipt of updated credit parameters and has no payload.
[tx1, tx2, ...]
where
tx1
, tx2
are RLP encoded transactions as per ETH documentation.
This message requests that the given transactions should be relayed to the to the eth network.
PIP request and response messages are batched and cannot be sent individually. Unlike LES, PIP batches may contain multiple messages of different types. The Request Batch is used to send messages of the types described below to the server.
Each message type also specifies its corresponding response message (referred to as outputs). Response messages are sent as a Response Batch by the server when requests have executed.
PIP tries to further optimise client-server round trips by allowing the individual requests in the batch to include references to what their responses would contain if processed sequentially. For clarification, an example PIP batch request could contain two request messages in order, where the second message specifies that an input is a specific 'output' of the first message, where 'output' means the server response to that request.
Referencing a field in a response to a batched request is achieved with loose inputs and
reusable outputs. Response message fields are documented as being reusable as n
where n
is an identifier labelling the field in the response message body.
Loose inputs may be a back-reference to a reusable output or may be hard data.
loose_input = [raw_flag, input]
raw_flag = is 0 or 1 (a.k.a. 'discriminant')
input = if raw_flag is 0, this is the RLP encoded value
if raw_flag is 1, this is back_reference
back_reference = [request_message_index, reusable_output]
request_message_index = the 0-based position of a prior message in the request batch
reusable_output = the unsigned integer identifying the corresponding response message field
The following are the individual messages, paired as requests and their responses.
Request and retrieve block headers from the server.
[message-id, [start, skip, max, reverse]]
start
Loose, of type either 32byte hash (block hash), or unsigned integer block numberskip
unsigned integer N, specifying the server should return every Nth blockmax
unsinged integer, the maximum number of blocks to returnreverse
0 if the block numbers should be increasing, 1 to return in reverse order
[message-id, [header1, header2, ...]]
header1, header2, ...
the requested block headers
Request for a header proof.
[message-id, [block]]
block
Loose, of type unsigned integer, referring to the block number
[message-id, [cht_inclusion_proof, block_hash, total_difficulty]]
cht_inclusion_proof
is[[node1, node2, ...], ...]
node1
merkle tree node as byte arrayblock_hash
hash of the requested block reusable as 0total_difficulty
unsigned integer, the requested block total difficulty
Request for transaction inclusion information by transaction hash.
[message-id, [hash]]
hash
Loose, of type 32 byte hash, referring to the transaction hash.
[message-id, [block_number, block_hash, index]]
block_number
the block number of the block containing the transaction reusable as 0block_hash
hash of the requested block reusable as 1index
index in the block
Request for a block's receipts.
[message-id, [hash]]
hash
Loose, of type 32 byte hash, referring to the block hash.
[message-id, [receipts]]
receipts
is[receipt1, receipt2, ...]
receipt1
a receipt, as per ETH spec.
Request for a block's transactions.
[message-id, [hash]]
hash
Loose, of type 32 byte hash, referring to the transaction hash
[message-id, [transactions, uncles]]
transactions
is[tx1, tx2, ...]
tx1
a transaction, as per ETH specuncles
is[header1, header2,...]
header1
an uncle block header as per ETH spec
Request for proof of specific account in the state.
[message-id , [block_hash, address_hash]]
block_hash
Loose, of type 32 byte hash, referring to the block hashaddress_hash
Loose, of type 32 byte hash, referring to the account address hash
[message-id, [cht_inclusion_proof, nonce, balance, code_hash, storage_root]]
cht_inclusion_proof
is[[node1, node2, ...], ...]
node1
merkle tree node as byte arraynonce
the block nonce (unsigned integer)balance
the account balance (unsigned integer)code_hash
32 byte hash reusable as 0storage_root
32 byte storage root hash reusable as 1
Request for a proof of contract storage.
[message-id, [block_hash, address_hash, storage_key_hash]]
block_hash
Loose, of type 32 byte hash, referring to the block hashaddress_hash
Loose, of type 32 byte hash, referring to the account address hashstorage_key_hash
Loose, of type 32 byte hash, referring to the storage key
[message-id, [cht_inclusion_proof, storage_value]]
cht_inclusion_proof
is[[node1, node2, ...], ...]
node1
merkle tree node as byte arraystorage_value
32 byte hash reusable as 0
Request for contract code.
[message-id, [block_hash, code_hash]]
block_hash
Loose, of type 32 byte hash, identifying the block.code_hash
Loose, of type 32 byte hash, identifying the code.
[message-id, [bytecode]]
bytecode
byte array of the contract code
Request for Merkle proofs of a contract execution.
[message-id, [block_hash, from_address, call_or_create_address, gas_to_prove, gas_price, value, data]]
block_hash
Loose, of type 32 byte hash, identifying the blockfrom_address
Type 32 byte hash, referring to the caller account address hashcall_or_create_address
32 byte hash, call contract if address, otherwise create contract if emptygas_to_prove
32 byte unsigned integer of gas to provegas_price
32 byte unsigned integer of gas pricevalue
32 byte unsigned integer of value to transferdata
byte array of relevant data
[message-id, [proof]]
proof
is[[node1, node2, ...], ...]
, the necessary execution proofnode1
merkle tree node as byte array