Protocol Documentation

Table of Contents

Top

churner/churner.proto

ChurnReply

FieldTypeLabelDescription
signature_with_salt_and_expirySignatureWithSaltAndExpiryThe signature signed by the Churner.
operators_to_churnOperatorToChurnrepeatedA list of existing operators that get churned out. This list will contain all quorums specified in the ChurnRequest even if some quorums may not have any churned out operators. If a quorum has available space, OperatorToChurn object will contain the quorum ID and empty operator and pubkey. The smart contract should only churn out the operators for quorums that are full.

For example, if the ChurnRequest specifies quorums 0 and 1 where quorum 0 is full and quorum 1 has available space, the ChurnReply will contain two OperatorToChurn objects with the respective quorums. OperatorToChurn for quorum 0 will contain the operator to churn out and OperatorToChurn for quorum 1 will contain empty operator (zero address) and pubkey. The smart contract should only churn out the operators for quorum 0 because quorum 1 has available space without having any operators churned. Note: it's possible an operator gets churned out just for one or more quorums (rather than entirely churned out for all quorums). |

ChurnRequest

FieldTypeLabelDescription
operator_addressstringThe Ethereum address (in hex like "0x123abcdef...") of the operator.
operator_to_register_pubkey_g1bytesThe operator making the churn request.
operator_to_register_pubkey_g2bytes
operator_request_signaturebytesThe operator's BLS signature signed on the keccak256 hash of concat("ChurnRequest", operator address, g1, g2, salt).
saltbytesThe salt used as part of the message to sign on for operator_request_signature.
quorum_idsuint32repeatedThe quorums to register for. Note: - If any of the quorum here has already been registered, this entire request will fail to proceed. - If any of the quorum fails to register, this entire request will fail. - Regardless of whether the specified quorums are full or not, the Churner will return parameters for all quorums specified here. The smart contract will determine whether it needs to churn out existing operators based on whether the quorums have available space. The IDs must be in range [0, 254].

OperatorToChurn

This describes an operator to churn out for a quorum.

FieldTypeLabelDescription
quorum_iduint32The ID of the quorum of the operator to churn out.
operatorbytesThe address of the operator.
pubkeybytesBLS pubkey (G1 point) of the operator.

SignatureWithSaltAndExpiry

FieldTypeLabelDescription
signaturebytesChurner's signature on the Operator's attributes.
saltbytesSalt is the keccak256 hash of concat("churn", time.Now(), operatorToChurn's OperatorID, Churner's ECDSA private key)
expiryint64When this churn decision will expire.

Churner

The Churner is a service that handles churn requests from new operators trying to join the EigenDA network. When the EigenDA network reaches the maximum number of operators, any new operator trying to join will have to make a churn request to this Churner, which acts as the sole decision maker to decide whether this new operator could join, and if so, which existing operator will be churned out (so the max number of operators won't be exceeded). The max number of operators, as well as the rules to make churn decisions, are defined onchain, see details in OperatorSetParam at: https://github.com/Layr-Labs/eigenlayer-middleware/blob/master/src/interfaces/IBLSRegistryCoordinatorWithIndices.sol#L24.

Method NameRequest TypeResponse TypeDescription
ChurnChurnRequestChurnReply

Top

common/common.proto

BlobCommitment

BlobCommitment represents commitment of a specific blob, containing its KZG commitment, degree proof, the actual degree, and data length in number of symbols.

FieldTypeLabelDescription
commitmentbytesA commitment to the blob data.
length_commitmentbytesA commitment to the blob data with G2 SRS, used to work with length_proof such that the claimed length below is verifiable.
length_proofbytesA proof that the degree of the polynomial used to generate the blob commitment is valid. It is computed such that the coefficient of the polynomial is committing with the G2 SRS at the end of the highest order.
lengthuint32The length specifies the degree of the polynomial used to generate the blob commitment. The length must equal to the degree + 1, and it must be a power of 2.

G1Commitment

A KZG commitment

FieldTypeLabelDescription
xbytesThe X coordinate of the KZG commitment. This is the raw byte representation of the field element.
ybytesThe Y coordinate of the KZG commitment. This is the raw byte representation of the field element.

Top

common/v2/common_v2.proto

Batch

Batch is a batch of blob certificates

FieldTypeLabelDescription
headerBatchHeaderheader contains metadata about the batch
blob_certificatesBlobCertificaterepeatedblob_certificates is the list of blob certificates in the batch

BatchHeader

BatchHeader is the header of a batch of blobs

FieldTypeLabelDescription
batch_rootbytesbatch_root is the root of the merkle tree of the hashes of blob certificates in the batch
reference_block_numberuint64reference_block_number is the block number that the state of the batch is based on for attestation

BlobCertificate

BlobCertificate contains a full description of a blob and how it is dispersed. Part of the certificate is provided by the blob submitter (i.e. the blob header), and part is provided by the disperser (i.e. the relays). Validator nodes eventually sign the blob certificate once they are in custody of the required chunks (note that the signature is indirect; validators sign the hash of a Batch, which contains the blob certificate).

FieldTypeLabelDescription
blob_headerBlobHeaderblob_header contains data about the blob.
signaturebytessignature is an ECDSA signature signed by the blob request signer's account ID over the BlobHeader's blobKey, which is a keccak hash of the serialized BlobHeader, and used to verify against blob dispersal request's account ID
relay_keysuint32repeatedrelay_keys is the list of relay keys that are in custody of the blob. The relays custodying the data are chosen by the Disperser to which the DisperseBlob request was submitted. It needs to contain at least 1 relay number. To retrieve a blob from the relay, one can find that relay's URL in the EigenDARelayRegistry contract: https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/core/EigenDARelayRegistry.sol

BlobHeader

BlobHeader contains the information describing a blob and the way it is to be dispersed.

FieldTypeLabelDescription
versionuint32The blob version. Blob versions are pushed onchain by EigenDA governance in an append only fashion and store the maximum number of operators, number of chunks, and coding rate for a blob. On blob verification, these values are checked against supplied or default security thresholds to validate the security assumptions of the blob's availability.
quorum_numbersuint32repeatedquorum_numbers is the list of quorum numbers that the blob is part of. Each quorum will store the data, hence adding quorum numbers adds redundancy, making the blob more likely to be retrievable. Each quorum requires separate payment.

On-demand dispersal is currently limited to using a subset of the following quorums: - 0: ETH - 1: EIGEN

Reserved-bandwidth dispersal is free to use multiple quorums, however those must be reserved ahead of time. The quorum_numbers specified here must be a subset of the ones allowed by the on-chain reservation. Check the allowed quorum numbers by looking up reservation struct: https://github.com/Layr-Labs/eigenda/blob/1430d56258b4e814b388e497320fd76354bfb478/contracts/src/interfaces/IPaymentVault.sol#L10 | | commitment | common.BlobCommitment | | commitment is the KZG commitment to the blob | | payment_header | PaymentHeader | | payment_header contains payment information for the blob |

PaymentHeader

PaymentHeader contains payment information for a blob. At least one of reservation_period or cumulative_payment must be set, and reservation_period is always considered before cumulative_payment. If reservation_period is set but not valid, the server will reject the request and not proceed with dispersal. If reservation_period is not set and cumulative_payment is set but not valid, the server will reject the request and not proceed with dispersal. Once the server has accepted the payment header, a client cannot cancel or rollback the payment. Every dispersal request will be charged by a multiple of minNumSymbols field defined by the payment vault contract. If the request blob size is smaller or not a multiple of minNumSymbols, the server will charge the user for the next multiple of minNumSymbols (https://github.com/Layr-Labs/eigenda/blob/1430d56258b4e814b388e497320fd76354bfb478/contracts/src/payments/PaymentVaultStorage.sol#L9).

FieldTypeLabelDescription
account_idstringThe account ID of the disperser client. This account ID is an eth wallet address of the user, corresponding to the key used by the client to sign the BlobHeader.
timestampint64The timestamp should be set as the UNIX timestamp in units of nanoseconds at the time of the dispersal request, and will be used to determine the reservation period, and compared against the reservation active start and end timestamps On-chain reservation timestamps are in units of seconds, while the payment header timestamp is in nanoseconds for greater precision. If the timestamp is not set or is not part of the previous or current reservation period, the request will be rejected. The reservation period of the dispersal request is used for rate-limiting the user's account against their dedicated bandwidth. This method requires users to set up reservation accounts with EigenDA team, and the team will set up an on-chain record of reserved bandwidth for the user for some period of time. The dispersal client's accountant will set this value to the current timestamp in nanoseconds. The disperser server will find the corresponding reservation period by taking the nearest lower multiple of the on-chain configured reservation period interval, mapping each request to a time-based window and is serialized and parsed as a uint32. The disperser server then validates that it matches either the current or the previous period, and check against the user's reserved bandwidth.

Example Usage Flow: 1. The user sets up a reservation with the EigenDA team, including throughput (symbolsPerSecond), startTimestamp, endTimestamp, and reservationPeriodInterval. 2. When sending a dispersal request at time t, the client fill in the timestamp field with t. 3. The disperser take timestamp t and checks the reservation period and the user's bandwidth capacity: - If the reservation is active (t >= startTimestamp and t < endTimestamp). - After rounding up to the nearest multiple of minNumSymbols defined by the payment vault contract, the user still has enough bandwidth capacity (hasn’t exceeded symbolsPerSecond * reservationPeriodInterval). - The request is ratelimited against the current reservation period, and calculated as reservation_period = floor(t / reservationPeriodInterval) * reservationPeriodInterval. the request's reservation period must either be the disperser server's current reservation period or the previous reservation period. 4. Server always go ahead with recording the received request in the current reservation period, and then categorize the scenarios - If the remaining bandwidth is sufficient for the request, the dispersal request proceeds. - If the remaining bandwidth is not enough for the request, server fills up the current bin and overflowing the extra to a future bin. - If the bandwidth has already been exhausted, the request is rejected. 5. Once the dispersal request signature has been verified, the server will not roll back the payment or the usage records. Users should be aware of this when planning their usage. The dispersal client written by EigenDA team takes account of this. 6. When the reservation ends or usage is exhausted, the client must wait for the next reservation period or switch to on-demand. | | cumulative_payment | bytes | | Cumulative payment is the total amount of tokens paid by the requesting account, including the current request. This value is serialized as an uint256 and parsed as a big integer, and must match the user’s on-chain deposit limits as well as the recorded payments for all previous requests. Because it is a cumulative (not incremental) total, requests can arrive out of order and still unambiguously declare how much of the on-chain deposit can be deducted.

Example Decision Flow: 1. In the set up phase, the user must deposit tokens into the EigenDA PaymentVault contract. The payment vault contract specifies the minimum number of symbols charged per dispersal, the pricing per symbol, and the maximum global rate for on-demand dispersals. The user should calculate the amount of tokens they would like to deposit based on their usage. The first time a user make a request, server will immediate read the contract for the on-chain balance. When user runs out of on-chain balance, the server will reject the request and not proceed with dispersal. When a user top up on-chain, the server will only refresh every few minutes for the top-up to take effect. 2. The disperser client accounts how many tokens they’ve already paid (previousCumPmt). 3. They should calculate the payment by rounding up blob size to the nearest multiple of minNumSymbols defined by the payment vault contract, and calculate the incremental amount of tokens needed for the current request needs based on protocol defined pricing. 4. They take the sum of previousCumPmt + new incremental payment and place it in the “cumulative_payment” field. 5. The disperser checks this new cumulative total against on-chain deposits and prior records (largest previous payment and smallest later payment if exists). 6. If the payment number is valid, the request is confirmed and disperser proceeds with dispersal; otherwise it’s rejected. |

Top

disperser/disperser.proto

AuthenticatedReply

FieldTypeLabelDescription
blob_auth_headerBlobAuthHeader
disperse_replyDisperseBlobReply

AuthenticatedRequest

FieldTypeLabelDescription
disperse_requestDisperseBlobRequest
authentication_dataAuthenticationData

AuthenticationData

AuthenticationData contains the signature of the BlobAuthHeader.

FieldTypeLabelDescription
authentication_databytes

BatchHeader

FieldTypeLabelDescription
batch_rootbytesThe root of the merkle tree with the hashes of blob headers as leaves.
quorum_numbersbytesAll quorums associated with blobs in this batch. Sorted in ascending order. Ex. [0, 2, 1] => 0x000102
quorum_signed_percentagesbytesThe percentage of stake that has signed for this batch. The quorum_signed_percentages[i] is percentage for the quorum_numbers[i].
reference_block_numberuint32The Ethereum block number at which the batch was created. The Disperser will encode and disperse the blobs based on the onchain info (e.g. operator stakes) at this block number.

BatchMetadata

FieldTypeLabelDescription
batch_headerBatchHeader
signatory_record_hashbytesThe hash of all public keys of the operators that did not sign the batch.
feebytesThe fee payment paid by users for dispersing this batch. It's the bytes representation of a big.Int value.
confirmation_block_numberuint32The Ethereum block number at which the batch is confirmed onchain.
batch_header_hashbytesThis is the hash of the ReducedBatchHeader defined onchain, see: https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/interfaces/IEigenDAServiceManager.sol#L43 The is the message that the operators will sign their signatures on.

BlobAuthHeader

BlobAuthHeader contains information about the blob for the client to verify and sign.

  • Once payments are enabled, the BlobAuthHeader will contain the KZG commitment to the blob, which the client will verify and sign. Having the client verify the KZG commitment instead of calculating it avoids the need for the client to have the KZG structured reference string (SRS), which can be large. The signed KZG commitment prevents the disperser from sending a different blob to the DA Nodes than the one the client sent.
  • In the meantime, the BlobAuthHeader contains a simple challenge parameter is used to prevent replay attacks in the event that a signature is leaked.
FieldTypeLabelDescription
challenge_parameteruint32

BlobHeader

FieldTypeLabelDescription
commitmentcommon.G1CommitmentKZG commitment of the blob.
data_lengthuint32The length of the blob in symbols (each symbol is 32 bytes).
blob_quorum_paramsBlobQuorumParamrepeatedThe params of the quorums that this blob participates in.

BlobInfo

BlobInfo contains information needed to confirm the blob against the EigenDA contracts

FieldTypeLabelDescription
blob_headerBlobHeader
blob_verification_proofBlobVerificationProof

BlobQuorumParam

FieldTypeLabelDescription
quorum_numberuint32The ID of the quorum.
adversary_threshold_percentageuint32The max percentage of stake within the quorum that can be held by or delegated to adversarial operators. Currently, this and the next parameter are standardized across the quorum using values read from the EigenDA contracts.
confirmation_threshold_percentageuint32The min percentage of stake that must attest in order to consider the dispersal is successful.
chunk_lengthuint32The length of each chunk.

BlobStatusReply

FieldTypeLabelDescription
statusBlobStatusThe status of the blob.
infoBlobInfoThe blob info needed for clients to confirm the blob against the EigenDA contracts.

BlobStatusRequest

BlobStatusRequest is used to query the status of a blob.

FieldTypeLabelDescription
request_idbytesRefer to the documentation for DisperseBlobReply.request_id. Note that because the request_id depends on the timestamp at which the disperser received the request, it is not possible to compute it locally from the cert and blob. Clients should thus store this request_id if they plan on requerying the status of the blob in the future.

BlobVerificationProof

FieldTypeLabelDescription
batch_iduint32batch_id is an incremental ID assigned to a batch by EigenDAServiceManager
blob_indexuint32The index of the blob in the batch (which is logically an ordered list of blobs).
batch_metadataBatchMetadata
inclusion_proofbytesinclusion_proof is a merkle proof for a blob header's inclusion in a batch
quorum_indexesbytesindexes of quorums in BatchHeader.quorum_numbers that match the quorums in BlobHeader.blob_quorum_params Ex. BlobHeader.blob_quorum_params = [ { quorum_number = 0, ... }, { quorum_number = 3, ... }, { quorum_number = 5, ... }, ] BatchHeader.quorum_numbers = [0, 5, 3] => 0x000503 Then, quorum_indexes = [0, 2, 1] => 0x000201

DisperseBlobReply

FieldTypeLabelDescription
resultBlobStatusThe status of the blob associated with the request_id. Will always be PROCESSING.
request_idbytesThe request ID generated by the disperser.

Once a request is accepted, a unique request ID is generated. request_id = string(blob_key) = (hash(blob), hash(metadata)) where metadata contains a requestedAt timestamp and the requested quorum numbers and their adversarial thresholds. BlobKey definition: https://github.com/Layr-Labs/eigenda/blob/6b02bf966afa2b9bf2385db8dd01f66f17334e17/disperser/disperser.go#L87 BlobKey computation: https://github.com/Layr-Labs/eigenda/blob/6b02bf966afa2b9bf2385db8dd01f66f17334e17/disperser/common/blobstore/shared_storage.go#L83-L84

Different DisperseBlobRequests have different IDs, including two identical DisperseBlobRequests sent at different times. Clients should thus store this ID and use it to query the processing status of the request via the GetBlobStatus API. |

DisperseBlobRequest

FieldTypeLabelDescription
databytesThe data to be dispersed. The size of data must be <= 16MiB. Every 32 bytes of data is interpreted as an integer in big endian format where the lower address has more significant bits. The integer must stay in the valid range to be interpreted as a field element on the bn254 curve. The valid range is 0 <= x < 21888242871839275222246405745257275088548364400416034343698204186575808495617 If any one of the 32 bytes elements is outside the range, the whole request is deemed as invalid, and rejected.
custom_quorum_numbersuint32repeatedThe quorums to which the blob will be sent, in addition to the required quorums which are configured on the EigenDA smart contract. If required quorums are included here, an error will be returned. The disperser will ensure that the encoded blobs for each quorum are all processed within the same batch.
account_idstringThe account ID of the client. This should be a hex-encoded string of the ECSDA public key corresponding to the key used by the client to sign the BlobAuthHeader.

RetrieveBlobReply

RetrieveBlobReply contains the retrieved blob data

FieldTypeLabelDescription
databytes

RetrieveBlobRequest

RetrieveBlobRequest contains parameters to retrieve the blob.

FieldTypeLabelDescription
batch_header_hashbytes
blob_indexuint32

BlobStatus

BlobStatus represents the status of a blob. The status of a blob is updated as the blob is processed by the disperser. The status of a blob can be queried by the client using the GetBlobStatus API. Intermediate states are states that the blob can be in while being processed, and it can be updated to a different state:

  • PROCESSING
  • DISPERSING
  • CONFIRMED Terminal states are states that will not be updated to a different state:
  • FAILED
  • FINALIZED
  • INSUFFICIENT_SIGNATURES
NameNumberDescription
UNKNOWN0
PROCESSING1PROCESSING means that the blob is currently being processed by the disperser
CONFIRMED2CONFIRMED means that the blob has been dispersed to DA Nodes and the dispersed batch containing the blob has been confirmed onchain
FAILED3FAILED means that the blob has failed permanently (for reasons other than insufficient signatures, which is a separate state). This status is somewhat of a catch-all category, containing (but not necessarily exclusively as errors can be added in the future): - blob has expired - internal logic error while requesting encoding - blob retry has exceeded its limit while waiting for blob finalization after confirmation. Most likely triggered by a chain reorg: see https://github.com/Layr-Labs/eigenda/blob/master/disperser/batcher/finalizer.go#L179-L189.
FINALIZED4FINALIZED means that the block containing the blob's confirmation transaction has been finalized on Ethereum
INSUFFICIENT_SIGNATURES5INSUFFICIENT_SIGNATURES means that the confirmation threshold for the blob was not met for at least one quorum.
DISPERSING6The DISPERSING state is comprised of two separate phases: - Dispersing to DA nodes and collecting signature - Submitting the transaction on chain and waiting for tx receipt

Disperser

Disperser defines the public APIs for dispersing blobs.

Method NameRequest TypeResponse TypeDescription
DisperseBlobDisperseBlobRequestDisperseBlobReplyDisperseBlob accepts a single blob to be dispersed. This executes the dispersal async, i.e. it returns once the request is accepted. The client should use GetBlobStatus() API to poll the processing status of the blob.

If DisperseBlob returns the following error codes: INVALID_ARGUMENT (400): request is invalid for a reason specified in the error msg. RESOURCE_EXHAUSTED (429): request is rate limited for the quorum specified in the error msg. user should retry after the specified duration. INTERNAL (500): serious error, user should NOT retry. | | DisperseBlobAuthenticated | AuthenticatedRequest stream | AuthenticatedReply stream | DisperseBlobAuthenticated is similar to DisperseBlob, except that it requires the client to authenticate itself via the AuthenticationData message. The protocol is as follows: 1. The client sends a DisperseBlobAuthenticated request with the DisperseBlobRequest message 2. The Disperser sends back a BlobAuthHeader message containing information for the client to verify and sign. 3. The client verifies the BlobAuthHeader and sends back the signed BlobAuthHeader in an AuthenticationData message. 4. The Disperser verifies the signature and returns a DisperseBlobReply message. | | GetBlobStatus | BlobStatusRequest | BlobStatusReply | This API is meant to be polled for the blob status. | | RetrieveBlob | RetrieveBlobRequest | RetrieveBlobReply | This retrieves the requested blob from the Disperser's backend. This is a more efficient way to retrieve blobs than directly retrieving from the DA Nodes (see detail about this approach in api/proto/retriever/retriever.proto). The blob should have been initially dispersed via this Disperser service for this API to work. |

Top

disperser/v2/disperser_v2.proto

Attestation

FieldTypeLabelDescription
non_signer_pubkeysbytesrepeatedSerialized bytes of non signer public keys (G1 points)
apk_g2bytesSerialized bytes of G2 point that represents aggregate public key of all signers
quorum_apksbytesrepeatedSerialized bytes of aggregate public keys (G1 points) from all nodes for each quorum The order of the quorum_apks should match the order of the quorum_numbers
sigmabytesSerialized bytes of aggregate signature
quorum_numbersuint32repeatedRelevant quorum numbers for the attestation
quorum_signed_percentagesbytesThe attestation rate for each quorum. Each quorum's signing percentage is represented by an 8 bit unsigned integer. The integer is the fraction of the quorum that has signed, with 100 representing 100% of the quorum signing, and 0 representing 0% of the quorum signing. The first byte in the byte array corresponds to the first quorum in the quorum_numbers array, the second byte corresponds to the second quorum, and so on.

BlobCommitmentReply

The result of a BlobCommitmentRequest().

FieldTypeLabelDescription
blob_commitmentcommon.BlobCommitmentThe commitment of the blob.

BlobCommitmentRequest

The input for a BlobCommitmentRequest(). This can be used to construct a BlobHeader.commitment.

FieldTypeLabelDescription
blobbytesThe blob data to compute the commitment for.

BlobInclusionInfo

BlobInclusionInfo is the information needed to verify the inclusion of a blob in a batch.

FieldTypeLabelDescription
blob_certificatecommon.v2.BlobCertificate
blob_indexuint32blob_index is the index of the blob in the batch
inclusion_proofbytesinclusion_proof is the inclusion proof of the blob in the batch

BlobStatusReply

BlobStatusReply is the reply to a BlobStatusRequest.

FieldTypeLabelDescription
statusBlobStatusThe status of the blob.
signed_batchSignedBatchThe signed batch. Only set if the blob status is GATHERING_SIGNATURES or COMPLETE. signed_batch and blob_inclusion_info are only set if the blob status is GATHERING_SIGNATURES or COMPLETE. When blob is in GATHERING_SIGNATURES status, the attestation object in signed_batch contains attestation information at the point in time. As it gathers more signatures, attestation object will be updated according to the latest attestation status. The client can use this intermediate attestation to verify a blob if it has gathered enough signatures. Otherwise, it should should poll the GetBlobStatus API until the desired level of attestation has been gathered or status is COMPLETE. When blob is in COMPLETE status, the attestation object in signed_batch contains the final attestation information. If the final attestation does not meet the client's requirement, the client should try a new dispersal.
blob_inclusion_infoBlobInclusionInfoBlobInclusionInfo is the information needed to verify the inclusion of a blob in a batch. Only set if the blob status is GATHERING_SIGNATURES or COMPLETE.

BlobStatusRequest

BlobStatusRequest is used to query the status of a blob.

FieldTypeLabelDescription
blob_keybytesThe unique identifier for the blob.

DisperseBlobReply

A reply to a DisperseBlob request.

FieldTypeLabelDescription
resultBlobStatusThe status of the blob associated with the blob key.
blob_keybytesThe unique 32 byte identifier for the blob.

The blob_key is the keccak hash of the rlp serialization of the BlobHeader, as computed here: https://github.com/Layr-Labs/eigenda/blob/0f14d1c90b86d29c30ff7e92cbadf2762c47f402/core/v2/serialization.go#L30 The blob_key must thus be unique for every request, even if the same blob is being dispersed. Meaning the blob_header must be different for each request.

Note that attempting to disperse a blob with the same blob key as a previously dispersed blob may cause the disperser to reject the blob (DisperseBlob() RPC will return an error). |

DisperseBlobRequest

A request to disperse a blob.

FieldTypeLabelDescription
blobbytesThe blob to be dispersed.

The size of this byte array may be any size as long as it does not exceed the maximum length of 16MiB. While the data being dispersed is only required to be greater than 0 bytes, the blob size charged against the payment method will be rounded up to the nearest multiple of minNumSymbols defined by the payment vault contract (https://github.com/Layr-Labs/eigenda/blob/1430d56258b4e814b388e497320fd76354bfb478/contracts/src/payments/PaymentVaultStorage.sol#L9).

Every 32 bytes of data is interpreted as an integer in big endian format where the lower address has more significant bits. The integer must stay in the valid range to be interpreted as a field element on the bn254 curve. The valid range is 0 <= x < 21888242871839275222246405745257275088548364400416034343698204186575808495617. If any one of the 32 bytes elements is outside the range, the whole request is deemed as invalid, and rejected. | | blob_header | common.v2.BlobHeader | | The header contains metadata about the blob.

This header can be thought of as an "eigenDA tx", in that it plays a purpose similar to an eth_tx to disperse a 4844 blob. Note that a call to DisperseBlob requires the blob and the blobHeader, which is similar to how dispersing a blob to ethereum requires sending a tx whose data contains the hash of the kzg commit of the blob, which is dispersed separately. | | signature | bytes | | signature over keccak hash of the blob_header that can be verified by blob_header.payment_header.account_id |

GetPaymentStateReply

GetPaymentStateReply contains the payment state of an account.

FieldTypeLabelDescription
payment_global_paramsPaymentGlobalParamsglobal payment vault parameters
period_recordsPeriodRecordrepeatedoff-chain account reservation usage records
reservationReservationon-chain account reservation setting
cumulative_paymentbytesoff-chain on-demand payment usage
onchain_cumulative_paymentbyteson-chain on-demand payment deposited

GetPaymentStateRequest

GetPaymentStateRequest contains parameters to query the payment state of an account.

FieldTypeLabelDescription
account_idstringThe ID of the account being queried. This account ID is an eth wallet address of the user.
signaturebytesSignature over the account ID

PaymentGlobalParams

Global constant parameters defined by the payment vault.

FieldTypeLabelDescription
global_symbols_per_seconduint64Global ratelimit for on-demand dispersals
min_num_symbolsuint64Minimum number of symbols accounted for all dispersals
price_per_symboluint64Price charged per symbol for on-demand dispersals
reservation_windowuint64Reservation window for all reservations
on_demand_quorum_numbersuint32repeatedquorums allowed to make on-demand dispersals

PeriodRecord

PeriodRecord is the usage record of an account in a bin. The API should return the active bin record and the subsequent two records that contains potential overflows.

FieldTypeLabelDescription
indexuint32Period index of the reservation
usageuint64symbol usage recorded

Reservation

Reservation parameters of an account, used to determine the rate limit for the account.

FieldTypeLabelDescription
symbols_per_seconduint64rate limit for the account
start_timestampuint32start timestamp of the reservation
end_timestampuint32end timestamp of the reservation
quorum_numbersuint32repeatedquorums allowed to make reserved dispersals
quorum_splitsuint32repeatedquorum splits describes how the payment is split among the quorums

SignedBatch

SignedBatch is a batch of blobs with a signature.

FieldTypeLabelDescription
headercommon.v2.BatchHeaderheader contains metadata about the batch
attestationAttestationattestation on the batch

BlobStatus

BlobStatus represents the status of a blob. The status of a blob is updated as the blob is processed by the disperser. The status of a blob can be queried by the client using the GetBlobStatus API. Intermediate states are states that the blob can be in while being processed, and it can be updated to a different state:

  • QUEUED
  • ENCODED
  • GATHERING_SIGNATURES Terminal states are states that will not be updated to a different state:
  • UNKNOWN
  • COMPLETE
  • FAILED
NameNumberDescription
UNKNOWN0UNKNOWN means that the status of the blob is unknown. This is a catch all and should not be encountered absent a bug.

This status is functionally equivalent to FAILED, but is used to indicate that the failure is due to an unanticipated bug. | | QUEUED | 1 | QUEUED means that the blob has been queued by the disperser for processing. The DisperseBlob API is asynchronous, meaning that after request validation, but before any processing, the blob is stored in a queue of some sort, and a response immediately returned to the client. | | ENCODED | 2 | ENCODED means that the blob has been Reed-Solomon encoded into chunks and is ready to be dispersed to DA Nodes. | | GATHERING_SIGNATURES | 3 | GATHERING_SIGNATURES means that the blob chunks are currently actively being transmitted to validators, and in doing so requesting that the validators sign to acknowledge receipt of the blob. Requests that timeout or receive errors are resubmitted to DA nodes for some period of time set by the disperser, after which the BlobStatus becomes COMPLETE. | | COMPLETE | 4 | COMPLETE means the blob has been dispersed to DA nodes, and the GATHERING_SIGNATURES period of time has completed. This status does not guarantee any signer percentage, so a client should check that the signature has met its required threshold, and resubmit a new blob dispersal request if not. | | FAILED | 5 | FAILED means that the blob has failed permanently. Note that this is a terminal state, and in order to retry the blob, the client must submit the blob again (blob key is required to be unique). |

Disperser

Disperser defines the public APIs for dispersing blobs.

Method NameRequest TypeResponse TypeDescription
DisperseBlobDisperseBlobRequestDisperseBlobReplyDisperseBlob accepts blob to disperse from clients. This executes the dispersal asynchronously, i.e. it returns once the request is accepted. The client could use GetBlobStatus() API to poll the the processing status of the blob.
GetBlobStatusBlobStatusRequestBlobStatusReplyGetBlobStatus is meant to be polled for the blob status.
GetBlobCommitmentBlobCommitmentRequestBlobCommitmentReplyGetBlobCommitment is a utility method that calculates commitment for a blob payload.
GetPaymentStateGetPaymentStateRequestGetPaymentStateReplyGetPaymentState is a utility method to get the payment state of a given account.

Top

node/node.proto

AttestBatchReply

FieldTypeLabelDescription
signaturebytes

AttestBatchRequest

FieldTypeLabelDescription
batch_headerBatchHeaderheader of the batch
blob_header_hashesbytesrepeatedthe header hashes of all blobs in the batch

BatchHeader

BatchHeader (see core/data.go#BatchHeader)

FieldTypeLabelDescription
batch_rootbytesThe root of the merkle tree with hashes of blob headers as leaves.
reference_block_numberuint32The Ethereum block number at which the batch is dispersed.

Blob

In EigenDA, the original blob to disperse is encoded as a polynomial via taking taking different point evaluations (i.e. erasure coding). These points are split into disjoint subsets which are assigned to different operator nodes in the EigenDA network. The data in this message is a subset of these points that are assigned to a single operator node.

FieldTypeLabelDescription
headerBlobHeaderWhich (original) blob this is for.
bundlesBundlerepeatedEach bundle contains all chunks for a single quorum of the blob. The number of bundles must be equal to the total number of quorums associated with the blob, and the ordering must be the same as BlobHeader.quorum_headers. Note: an operator may be in some but not all of the quorums; in that case the bundle corresponding to that quorum will be empty.

BlobHeader

FieldTypeLabelDescription
commitmentcommon.G1CommitmentThe KZG commitment to the polynomial representing the blob.
length_commitmentG2CommitmentThe KZG commitment to the polynomial representing the blob on G2, it is used for proving the degree of the polynomial
length_proofG2CommitmentThe low degree proof. It's the KZG commitment to the polynomial shifted to the largest SRS degree.
lengthuint32The length of the original blob in number of symbols (in the field where the polynomial is defined).
quorum_headersBlobQuorumInforepeatedThe params of the quorums that this blob participates in.
account_idstringThe ID of the user who is dispersing this blob to EigenDA.
reference_block_numberuint32The reference block number whose state is used to encode the blob

BlobQuorumInfo

See BlobQuorumParam as defined in api/proto/disperser/disperser.proto

FieldTypeLabelDescription
quorum_iduint32
adversary_thresholduint32
confirmation_thresholduint32
chunk_lengthuint32
ratelimituint32

Bundle

A Bundle is the collection of chunks associated with a single blob, for a single operator and a single quorum.

FieldTypeLabelDescription
chunksbytesrepeatedEach chunk corresponds to a collection of points on the polynomial. Each chunk has same number of points.
bundlebytesAll chunks of the bundle encoded in a byte array.

G2Commitment

FieldTypeLabelDescription
x_a0bytesThe A0 element of the X coordinate of G2 point.
x_a1bytesThe A1 element of the X coordinate of G2 point.
y_a0bytesThe A0 element of the Y coordinate of G2 point.
y_a1bytesThe A1 element of the Y coordinate of G2 point.

GetBlobHeaderReply

FieldTypeLabelDescription
blob_headerBlobHeaderThe header of the blob requested per GetBlobHeaderRequest.
proofMerkleProofMerkle proof that returned blob header belongs to the batch and is the batch's MerkleProof.index-th blob. This can be checked against the batch root on chain.

GetBlobHeaderRequest

See RetrieveChunksRequest for documentation of each parameter of GetBlobHeaderRequest.

FieldTypeLabelDescription
batch_header_hashbytes
blob_indexuint32
quorum_iduint32

MerkleProof

FieldTypeLabelDescription
hashesbytesrepeatedThe proof itself.
indexuint32Which index (the leaf of the Merkle tree) this proof is for.

NodeInfoReply

Node info reply

FieldTypeLabelDescription
semverstring
archstring
osstring
num_cpuuint32
mem_bytesuint64

NodeInfoRequest

Node info request

RetrieveChunksReply

FieldTypeLabelDescription
chunksbytesrepeatedAll chunks the Node is storing for the requested blob per RetrieveChunksRequest.
chunk_encoding_formatChunkEncodingFormatHow the above chunks are encoded.

RetrieveChunksRequest

FieldTypeLabelDescription
batch_header_hashbytesThe hash of the ReducedBatchHeader defined onchain, see: https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/interfaces/IEigenDAServiceManager.sol#L43 This identifies which batch to retrieve for.
blob_indexuint32Which blob in the batch to retrieve for (note: a batch is logically an ordered list of blobs).
quorum_iduint32Which quorum of the blob to retrieve for (note: a blob can have multiple quorums and the chunks for different quorums at a Node can be different). The ID must be in range [0, 254].

StoreBlobsReply

FieldTypeLabelDescription
signaturesgoogle.protobuf.BytesValuerepeatedThe operator's BLS sgnature signed on the blob header hashes. The ordering of the signatures must match the ordering of the blobs sent in the request, with empty signatures in the places for discarded blobs.

StoreBlobsRequest

FieldTypeLabelDescription
blobsBlobrepeatedBlobs to store
reference_block_numberuint32The reference block number whose state is used to encode the blobs

StoreChunksReply

FieldTypeLabelDescription
signaturebytesThe operator's BLS signature signed on the batch header hash.

StoreChunksRequest

FieldTypeLabelDescription
batch_headerBatchHeaderWhich batch this request is for.
blobsBlobrepeatedThe chunks for each blob in the batch to be stored in an EigenDA Node.

ChunkEncodingFormat

This describes how the chunks returned in RetrieveChunksReply are encoded. Used to facilitate the decoding of chunks.

NameNumberDescription
UNKNOWN0
GNARK1
GOB2

Dispersal

Method NameRequest TypeResponse TypeDescription
StoreChunksStoreChunksRequestStoreChunksReplyStoreChunks validates that the chunks match what the Node is supposed to receive ( different Nodes are responsible for different chunks, as EigenDA is horizontally sharded) and is correctly coded (e.g. each chunk must be a valid KZG multiproof) according to the EigenDA protocol. It also stores the chunks along with metadata for the protocol-defined length of custody. It will return a signature at the end to attest to the data in this request it has processed.
StoreBlobsStoreBlobsRequestStoreBlobsReplyStoreBlobs is similar to StoreChunks, but it stores the blobs using a different storage schema so that the stored blobs can later be aggregated by AttestBatch method to a bigger batch. StoreBlobs + AttestBatch will eventually replace and deprecate StoreChunks method. DEPRECATED: StoreBlobs method is not used
AttestBatchAttestBatchRequestAttestBatchReplyAttestBatch is used to aggregate the batches stored by StoreBlobs method to a bigger batch. It will return a signature at the end to attest to the aggregated batch. DEPRECATED: AttestBatch method is not used
NodeInfoNodeInfoRequestNodeInfoReplyRetrieve node info metadata

Retrieval

Method NameRequest TypeResponse TypeDescription
RetrieveChunksRetrieveChunksRequestRetrieveChunksReplyRetrieveChunks retrieves the chunks for a blob custodied at the Node.
GetBlobHeaderGetBlobHeaderRequestGetBlobHeaderReplyGetBlobHeader is similar to RetrieveChunks, this just returns the header of the blob.
NodeInfoNodeInfoRequestNodeInfoReplyRetrieve node info metadata

Top

relay/relay.proto

ChunkRequest

A request for chunks within a specific blob. Requests are fulfilled in all-or-nothing fashion. If any of the requested chunks are not found or are unable to be fetched, the entire request will fail.

FieldTypeLabelDescription
by_indexChunkRequestByIndexRequest chunks by their individual indices.
by_rangeChunkRequestByRangeRequest chunks by a range of indices.

ChunkRequestByIndex

A request for chunks within a specific blob. Each chunk is requested individually by its index.

FieldTypeLabelDescription
blob_keybytesThe blob key.
chunk_indicesuint32repeatedThe index of the chunk within the blob.

ChunkRequestByRange

A request for chunks within a specific blob. Each chunk is requested a range of indices.

FieldTypeLabelDescription
blob_keybytesThe blob key.
start_indexuint32The first index to start fetching chunks from.
end_indexuint32One past the last index to fetch chunks from. Similar semantics to golang slices.

GetBlobReply

The reply to a GetBlobs request.

FieldTypeLabelDescription
blobbytesThe blob requested.

GetBlobRequest

A request to fetch one or more blobs.

FieldTypeLabelDescription
blob_keybytesThe key of the blob to fetch.

GetChunksReply

The reply to a GetChunks request.

FieldTypeLabelDescription
databytesrepeatedThe chunks requested. The order of these chunks will be the same as the order of the requested chunks. data is the raw data of the bundle (i.e. serialized byte array of the frames)

GetChunksRequest

Request chunks from blobs stored by this relay.

FieldTypeLabelDescription
chunk_requestsChunkRequestrepeatedThe chunk requests. Chunks are returned in the same order as they are requested.
operator_idbytesIf this is an authenticated request, this should hold the ID of the operator. If this is an unauthenticated request, this field should be empty. Relays may choose to reject unauthenticated requests.
timestampuint32Timestamp of the request in seconds since the Unix epoch. If too far out of sync with the server's clock, request may be rejected.
operator_signaturebytesIf this is an authenticated request, this field will hold a BLS signature by the requester on the hash of this request. Relays may choose to reject unauthenticated requests.

The following describes the schema for computing the hash of this request This algorithm is implemented in golang using relay.auth.HashGetChunksRequest().

All integers are encoded as unsigned 4 byte big endian values.

Perform a keccak256 hash on the following data in the following order: 1. the length of the operator ID in bytes 2. the operator id 3. the number of chunk requests 4. for each chunk request: a. if the chunk request is a request by index: i. a one byte ASCII representation of the character "i" (aka Ox69) ii. the length blob key in bytes iii. the blob key iv. the start index v. the end index b. if the chunk request is a request by range: i. a one byte ASCII representation of the character "r" (aka Ox72) ii. the length of the blob key in bytes iii. the blob key iv. each requested chunk index, in order 5. the timestamp (seconds since the Unix epoch encoded as a 4 byte big endian value) |

Relay

Relay is a service that provides access to public relay functionality.

Method NameRequest TypeResponse TypeDescription
GetBlobGetBlobRequestGetBlobReplyGetBlob retrieves a blob stored by the relay.
GetChunksGetChunksRequestGetChunksReplyGetChunks retrieves chunks from blobs stored by the relay.

Top

retriever/retriever.proto

BlobReply

FieldTypeLabelDescription
databytesThe blob retrieved and reconstructed from the EigenDA Nodes per BlobRequest.

BlobRequest

FieldTypeLabelDescription
batch_header_hashbytesThe hash of the ReducedBatchHeader defined onchain, see: https://github.com/Layr-Labs/eigenda/blob/master/contracts/src/interfaces/IEigenDAServiceManager.sol#L43 This identifies the batch that this blob belongs to.
blob_indexuint32Which blob in the batch this is requesting for (note: a batch is logically an ordered list of blobs).
reference_block_numberuint32The Ethereum block number at which the batch for this blob was constructed.
quorum_iduint32Which quorum of the blob this is requesting for (note a blob can participate in multiple quorums).

Retriever

The Retriever is a service for retrieving chunks corresponding to a blob from the EigenDA operator nodes and reconstructing the original blob from the chunks. This is a client-side library that the users are supposed to operationalize.

Note: Users generally have two ways to retrieve a blob from EigenDA:

  1. Retrieve from the Disperser that the user initially used for dispersal: the API is Disperser.RetrieveBlob() as defined in api/proto/disperser/disperser.proto
  2. Retrieve directly from the EigenDA Nodes, which is supported by this Retriever.

The Disperser.RetrieveBlob() (the 1st approach) is generally faster and cheaper as the Disperser manages the blobs that it has processed, whereas the Retriever.RetrieveBlob() (the 2nd approach here) removes the need to trust the Disperser, with the downside of worse cost and performance.

Method NameRequest TypeResponse TypeDescription
RetrieveBlobBlobRequestBlobReplyThis fans out request to EigenDA Nodes to retrieve the chunks and returns the reconstructed original blob in response.

Top

retriever/v2/retriever_v2.proto

BlobReply

A reply to a RetrieveBlob() request.

FieldTypeLabelDescription
databytesThe blob retrieved and reconstructed from the EigenDA Nodes per BlobRequest.

BlobRequest

A request to retrieve a blob from the EigenDA Nodes via RetrieveBlob().

FieldTypeLabelDescription
blob_headercommon.v2.BlobHeaderheader of the blob to be retrieved
reference_block_numberuint32The Ethereum block number at which the batch for this blob was constructed.
quorum_iduint32Which quorum of the blob this is requesting for (note a blob can participate in multiple quorums).

Retriever

The Retriever is a service for retrieving chunks corresponding to a blob from the EigenDA operator nodes and reconstructing the original blob from the chunks. This is a client-side library that the users are supposed to operationalize.

Note: Users generally have two ways to retrieve a blob from EigenDA V2:

  1. Retrieve from the relay that the blob is assigned to: the API is Relay.GetBlob() as defined in api/proto/relay/relay.proto
  2. Retrieve directly from the EigenDA Nodes, which is supported by this Retriever.

The Relay.GetBlob() (the 1st approach) is generally faster and cheaper as the relay manages the blobs that it has processed, whereas the Retriever.RetrieveBlob() (the 2nd approach here) removes the need to trust the relay, with the downside of worse cost and performance.

Method NameRequest TypeResponse TypeDescription
RetrieveBlobBlobRequestBlobReplyThis fans out request to EigenDA Nodes to retrieve the chunks and returns the reconstructed original blob in response.

Top

validator/node_v2.proto

GetChunksReply

The response to the GetChunks() RPC.

FieldTypeLabelDescription
chunksbytesrepeatedAll chunks the Node is storing for the requested blob per GetChunksRequest.
chunk_encoding_formatChunkEncodingFormatThe format how the above chunks are encoded.

GetChunksRequest

The parameter for the GetChunks() RPC.

FieldTypeLabelDescription
blob_keybytesThe unique identifier for the blob the chunks are being requested for. The blob_key is the keccak hash of the rlp serialization of the BlobHeader, as computed here: https://github.com/Layr-Labs/eigenda/blob/0f14d1c90b86d29c30ff7e92cbadf2762c47f402/core/v2/serialization.go#L30
quorum_iduint32Which quorum of the blob to retrieve for (note: a blob can have multiple quorums and the chunks for different quorums at a Node can be different). The ID must be in range [0, 254].

GetNodeInfoReply

Node info reply

FieldTypeLabelDescription
semverstringThe version of the node.
archstringThe architecture of the node.
osstringThe operating system of the node.
num_cpuuint32The number of CPUs on the node.
mem_bytesuint64The amount of memory on the node in bytes.

GetNodeInfoRequest

The parameter for the GetNodeInfo() RPC.

StoreChunksReply

StoreChunksReply is the message type used to respond to a StoreChunks() RPC.

FieldTypeLabelDescription
signaturebytesThe validator's BSL signature signed on the batch header hash.

StoreChunksRequest

Request that the Node store a batch of chunks.

FieldTypeLabelDescription
batchcommon.v2.Batchbatch of blobs to store
disperserIDuint32ID of the disperser that is requesting the storage of the batch.
timestampuint32Timestamp of the request in seconds since the Unix epoch. If too far out of sync with the server's clock, request may be rejected.
signaturebytesSignature using the disperser's ECDSA key over keccak hash of the batch. The purpose of this signature is to prevent hooligans from tricking validators into storing data that they shouldn't be storing.

Algorithm for computing the hash is as follows. All integer values are serialized in big-endian order (unsigned). A reference implementation (golang) can be found at https://github.com/Layr-Labs/eigenda/blob/master/disperser/auth/request_signing.go

  1. digest len(batch.BatchHeader.BatchRoot) (4 bytes, unsigned big endian) 2. digest batch.BatchHeader.BatchRoot 3. digest batch.BatchHeader.ReferenceBlockNumber (8 bytes, unsigned big endian) 4. digest len(batch.BlobCertificates) (4 bytes, unsigned big endian) 5. for each certificate in batch.BlobCertificates: a. digest certificate.BlobHeader.Version (4 bytes, unsigned big endian) b. digest len(certificate.BlobHeader.QuorumNumbers) (4 bytes, unsigned big endian) c. for each quorum_number in certificate.BlobHeader.QuorumNumbers: i. digest quorum_number (4 bytes, unsigned big endian) d. digest len(certificate.BlobHeader.Commitment.Commitment) (4 bytes, unsigned big endian) e. digest certificate.BlobHeader.Commitment.Commitment f digest len(certificate.BlobHeader.Commitment.LengthCommitment) (4 bytes, unsigned big endian) g. digest certificate.BlobHeader.Commitment.LengthCommitment h. digest len(certificate.BlobHeader.Commitment.LengthProof) (4 bytes, unsigned big endian) i. digest certificate.BlobHeader.Commitment.LengthProof j. digest certificate.BlobHeader.Commitment.Length (4 bytes, unsigned big endian) k. digest len(certificate.BlobHeader.PaymentHeader.AccountId) (4 bytes, unsigned big endian) l. digest certificate.BlobHeader.PaymentHeader.AccountId m. digest certificate.BlobHeader.PaymentHeader.Timestamp (4 bytes, signed big endian) n digest len(certificate.BlobHeader.PaymentHeader.CumulativePayment) (4 bytes, unsigned big endian) o. digest certificate.BlobHeader.PaymentHeader.CumulativePayment p digest len(certificate.BlobHeader.Signature) (4 bytes, unsigned big endian) q. digest certificate.BlobHeader.Signature r. digest len(certificate.Relays) (4 bytes, unsigned big endian) s. for each relay in certificate.Relays: i. digest relay (4 bytes, unsigned big endian) 6. digest disperserID (4 bytes, unsigned big endian) 7. digest timestamp (4 bytes, unsigned big endian)

Note that this signature is not included in the hash for obvious reasons. |

ChunkEncodingFormat

This describes how the chunks returned in GetChunksReply are encoded. Used to facilitate the decoding of chunks.

NameNumberDescription
UNKNOWN0A valid response should never use this value. If encountered, the client should treat it as an error.
GNARK1A chunk encoded in GNARK has the following format:

[KZG proof: 32 bytes] [Coeff 1: 32 bytes] [Coeff 2: 32 bytes] ... [Coeff n: 32 bytes]

The KZG proof is a point on G1 and is serialized with bn254.G1Affine.Bytes(). The coefficients are field elements in bn254 and serialized with fr.Element.Marshal().

References: - bn254.G1Affine: github.com/consensys/gnark-crypto/ecc/bn254 - fr.Element: github.com/consensys/gnark-crypto/ecc/bn254/fr

Golang serialization and deserialization can be found in: - Frame.SerializeGnark() - Frame.DeserializeGnark() Package: github.com/Layr-Labs/eigenda/encoding |

Dispersal

Dispersal is utilized to disperse chunk data.

Method NameRequest TypeResponse TypeDescription
StoreChunksStoreChunksRequestStoreChunksReplyStoreChunks instructs the validator to store a batch of chunks. This call blocks until the validator either acquires the chunks or the validator determines that it is unable to acquire the chunks. If the validator is able to acquire and validate the chunks, it returns a signature over the batch header. This RPC describes which chunks the validator should store but does not contain that chunk data. The validator is expected to fetch the chunk data from one of the relays that is in possession of the chunk.
GetNodeInfoGetNodeInfoRequestGetNodeInfoReplyGetNodeInfo fetches metadata about the node.

Retrieval

Retrieval is utilized to retrieve chunk data.

Method NameRequest TypeResponse TypeDescription
GetChunksGetChunksRequestGetChunksReplyGetChunks retrieves the chunks for a blob custodied at the Node. Note that where possible, it is generally faster to retrieve chunks from the relay service if that service is available.
GetNodeInfoGetNodeInfoRequestGetNodeInfoReplyRetrieve node info metadata

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)