Protocol Documentation
Table of Contents
churner/churner.proto
ChurnReply
Field | Type | Label | Description |
---|---|---|---|
signature_with_salt_and_expiry | SignatureWithSaltAndExpiry | The signature signed by the Churner. | |
operators_to_churn | OperatorToChurn | repeated | A 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
Field | Type | Label | Description |
---|---|---|---|
operator_address | string | The Ethereum address (in hex like "0x123abcdef...") of the operator. | |
operator_to_register_pubkey_g1 | bytes | The operator making the churn request. | |
operator_to_register_pubkey_g2 | bytes | ||
operator_request_signature | bytes | The operator's BLS signature signed on the keccak256 hash of concat("ChurnRequest", operator address, g1, g2, salt). | |
salt | bytes | The salt used as part of the message to sign on for operator_request_signature. | |
quorum_ids | uint32 | repeated | The 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.
Field | Type | Label | Description |
---|---|---|---|
quorum_id | uint32 | The ID of the quorum of the operator to churn out. | |
operator | bytes | The address of the operator. | |
pubkey | bytes | BLS pubkey (G1 point) of the operator. |
SignatureWithSaltAndExpiry
Field | Type | Label | Description |
---|---|---|---|
signature | bytes | Churner's signature on the Operator's attributes. | |
salt | bytes | Salt is the keccak256 hash of concat("churn", time.Now(), operatorToChurn's OperatorID, Churner's ECDSA private key) | |
expiry | int64 | When 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 Name | Request Type | Response Type | Description |
---|---|---|---|
Churn | ChurnRequest | ChurnReply |
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.
Field | Type | Label | Description |
---|---|---|---|
commitment | bytes | A commitment to the blob data. | |
length_commitment | bytes | A commitment to the blob data with G2 SRS, used to work with length_proof such that the claimed length below is verifiable. | |
length_proof | bytes | A 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. | |
length | uint32 | The 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
Field | Type | Label | Description |
---|---|---|---|
x | bytes | The X coordinate of the KZG commitment. This is the raw byte representation of the field element. | |
y | bytes | The Y coordinate of the KZG commitment. This is the raw byte representation of the field element. |
common/v2/common_v2.proto
Batch
Batch is a batch of blob certificates
Field | Type | Label | Description |
---|---|---|---|
header | BatchHeader | header contains metadata about the batch | |
blob_certificates | BlobCertificate | repeated | blob_certificates is the list of blob certificates in the batch |
BatchHeader
BatchHeader is the header of a batch of blobs
Field | Type | Label | Description |
---|---|---|---|
batch_root | bytes | batch_root is the root of the merkle tree of the hashes of blob certificates in the batch | |
reference_block_number | uint64 | reference_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).
Field | Type | Label | Description |
---|---|---|---|
blob_header | BlobHeader | blob_header contains data about the blob. | |
signature | bytes | signature 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_keys | uint32 | repeated | relay_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.
Field | Type | Label | Description |
---|---|---|---|
version | uint32 | The 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_numbers | uint32 | repeated | quorum_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).
Field | Type | Label | Description |
---|---|---|---|
account_id | string | The 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. | |
timestamp | int64 | The 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. |
disperser/disperser.proto
AuthenticatedReply
Field | Type | Label | Description |
---|---|---|---|
blob_auth_header | BlobAuthHeader | ||
disperse_reply | DisperseBlobReply |
AuthenticatedRequest
Field | Type | Label | Description |
---|---|---|---|
disperse_request | DisperseBlobRequest | ||
authentication_data | AuthenticationData |
AuthenticationData
AuthenticationData contains the signature of the BlobAuthHeader.
Field | Type | Label | Description |
---|---|---|---|
authentication_data | bytes |
BatchHeader
Field | Type | Label | Description |
---|---|---|---|
batch_root | bytes | The root of the merkle tree with the hashes of blob headers as leaves. | |
quorum_numbers | bytes | All quorums associated with blobs in this batch. Sorted in ascending order. Ex. [0, 2, 1] => 0x000102 | |
quorum_signed_percentages | bytes | The percentage of stake that has signed for this batch. The quorum_signed_percentages[i] is percentage for the quorum_numbers[i]. | |
reference_block_number | uint32 | The 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
Field | Type | Label | Description |
---|---|---|---|
batch_header | BatchHeader | ||
signatory_record_hash | bytes | The hash of all public keys of the operators that did not sign the batch. | |
fee | bytes | The fee payment paid by users for dispersing this batch. It's the bytes representation of a big.Int value. | |
confirmation_block_number | uint32 | The Ethereum block number at which the batch is confirmed onchain. | |
batch_header_hash | bytes | This 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.
Field | Type | Label | Description |
---|---|---|---|
challenge_parameter | uint32 |
BlobHeader
Field | Type | Label | Description |
---|---|---|---|
commitment | common.G1Commitment | KZG commitment of the blob. | |
data_length | uint32 | The length of the blob in symbols (each symbol is 32 bytes). | |
blob_quorum_params | BlobQuorumParam | repeated | The params of the quorums that this blob participates in. |
BlobInfo
BlobInfo contains information needed to confirm the blob against the EigenDA contracts
Field | Type | Label | Description |
---|---|---|---|
blob_header | BlobHeader | ||
blob_verification_proof | BlobVerificationProof |
BlobQuorumParam
Field | Type | Label | Description |
---|---|---|---|
quorum_number | uint32 | The ID of the quorum. | |
adversary_threshold_percentage | uint32 | The 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_percentage | uint32 | The min percentage of stake that must attest in order to consider the dispersal is successful. | |
chunk_length | uint32 | The length of each chunk. |
BlobStatusReply
Field | Type | Label | Description |
---|---|---|---|
status | BlobStatus | The status of the blob. | |
info | BlobInfo | The blob info needed for clients to confirm the blob against the EigenDA contracts. |
BlobStatusRequest
BlobStatusRequest is used to query the status of a blob.
Field | Type | Label | Description |
---|---|---|---|
request_id | bytes | Refer 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
Field | Type | Label | Description |
---|---|---|---|
batch_id | uint32 | batch_id is an incremental ID assigned to a batch by EigenDAServiceManager | |
blob_index | uint32 | The index of the blob in the batch (which is logically an ordered list of blobs). | |
batch_metadata | BatchMetadata | ||
inclusion_proof | bytes | inclusion_proof is a merkle proof for a blob header's inclusion in a batch | |
quorum_indexes | bytes | indexes 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
Field | Type | Label | Description |
---|---|---|---|
result | BlobStatus | The status of the blob associated with the request_id. Will always be PROCESSING. | |
request_id | bytes | The 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
Field | Type | Label | Description |
---|---|---|---|
data | bytes | The 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_numbers | uint32 | repeated | The 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_id | string | The 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
Field | Type | Label | Description |
---|---|---|---|
data | bytes |
RetrieveBlobRequest
RetrieveBlobRequest contains parameters to retrieve the blob.
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
Name | Number | Description |
---|---|---|
UNKNOWN | 0 | |
PROCESSING | 1 | PROCESSING means that the blob is currently being processed by the disperser |
CONFIRMED | 2 | CONFIRMED means that the blob has been dispersed to DA Nodes and the dispersed batch containing the blob has been confirmed onchain |
FAILED | 3 | FAILED 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. |
FINALIZED | 4 | FINALIZED means that the block containing the blob's confirmation transaction has been finalized on Ethereum |
INSUFFICIENT_SIGNATURES | 5 | INSUFFICIENT_SIGNATURES means that the confirmation threshold for the blob was not met for at least one quorum. |
DISPERSING | 6 | The 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 Name | Request Type | Response Type | Description |
---|---|---|---|
DisperseBlob | DisperseBlobRequest | DisperseBlobReply | DisperseBlob 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. |
disperser/v2/disperser_v2.proto
Attestation
Field | Type | Label | Description |
---|---|---|---|
non_signer_pubkeys | bytes | repeated | Serialized bytes of non signer public keys (G1 points) |
apk_g2 | bytes | Serialized bytes of G2 point that represents aggregate public key of all signers | |
quorum_apks | bytes | repeated | Serialized 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 |
sigma | bytes | Serialized bytes of aggregate signature | |
quorum_numbers | uint32 | repeated | Relevant quorum numbers for the attestation |
quorum_signed_percentages | bytes | The 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().
Field | Type | Label | Description |
---|---|---|---|
blob_commitment | common.BlobCommitment | The commitment of the blob. |
BlobCommitmentRequest
The input for a BlobCommitmentRequest(). This can be used to construct a BlobHeader.commitment.
Field | Type | Label | Description |
---|---|---|---|
blob | bytes | The blob data to compute the commitment for. |
BlobInclusionInfo
BlobInclusionInfo is the information needed to verify the inclusion of a blob in a batch.
Field | Type | Label | Description |
---|---|---|---|
blob_certificate | common.v2.BlobCertificate | ||
blob_index | uint32 | blob_index is the index of the blob in the batch | |
inclusion_proof | bytes | inclusion_proof is the inclusion proof of the blob in the batch |
BlobStatusReply
BlobStatusReply is the reply to a BlobStatusRequest.
Field | Type | Label | Description |
---|---|---|---|
status | BlobStatus | The status of the blob. | |
signed_batch | SignedBatch | The 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_info | BlobInclusionInfo | BlobInclusionInfo 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.
Field | Type | Label | Description |
---|---|---|---|
blob_key | bytes | The unique identifier for the blob. |
DisperseBlobReply
A reply to a DisperseBlob request.
Field | Type | Label | Description |
---|---|---|---|
result | BlobStatus | The status of the blob associated with the blob key. | |
blob_key | bytes | The 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.
Field | Type | Label | Description |
---|---|---|---|
blob | bytes | The 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.
Field | Type | Label | Description |
---|---|---|---|
payment_global_params | PaymentGlobalParams | global payment vault parameters | |
period_records | PeriodRecord | repeated | off-chain account reservation usage records |
reservation | Reservation | on-chain account reservation setting | |
cumulative_payment | bytes | off-chain on-demand payment usage | |
onchain_cumulative_payment | bytes | on-chain on-demand payment deposited |
GetPaymentStateRequest
GetPaymentStateRequest contains parameters to query the payment state of an account.
Field | Type | Label | Description |
---|---|---|---|
account_id | string | The ID of the account being queried. This account ID is an eth wallet address of the user. | |
signature | bytes | Signature over the account ID |
PaymentGlobalParams
Global constant parameters defined by the payment vault.
Field | Type | Label | Description |
---|---|---|---|
global_symbols_per_second | uint64 | Global ratelimit for on-demand dispersals | |
min_num_symbols | uint64 | Minimum number of symbols accounted for all dispersals | |
price_per_symbol | uint64 | Price charged per symbol for on-demand dispersals | |
reservation_window | uint64 | Reservation window for all reservations | |
on_demand_quorum_numbers | uint32 | repeated | quorums 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.
Field | Type | Label | Description |
---|---|---|---|
index | uint32 | Period index of the reservation | |
usage | uint64 | symbol usage recorded |
Reservation
Reservation parameters of an account, used to determine the rate limit for the account.
Field | Type | Label | Description |
---|---|---|---|
symbols_per_second | uint64 | rate limit for the account | |
start_timestamp | uint32 | start timestamp of the reservation | |
end_timestamp | uint32 | end timestamp of the reservation | |
quorum_numbers | uint32 | repeated | quorums allowed to make reserved dispersals |
quorum_splits | uint32 | repeated | quorum splits describes how the payment is split among the quorums |
SignedBatch
SignedBatch is a batch of blobs with a signature.
Field | Type | Label | Description |
---|---|---|---|
header | common.v2.BatchHeader | header contains metadata about the batch | |
attestation | Attestation | attestation 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
Name | Number | Description |
---|---|---|
UNKNOWN | 0 | UNKNOWN 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 Name | Request Type | Response Type | Description |
---|---|---|---|
DisperseBlob | DisperseBlobRequest | DisperseBlobReply | DisperseBlob 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. |
GetBlobStatus | BlobStatusRequest | BlobStatusReply | GetBlobStatus is meant to be polled for the blob status. |
GetBlobCommitment | BlobCommitmentRequest | BlobCommitmentReply | GetBlobCommitment is a utility method that calculates commitment for a blob payload. |
GetPaymentState | GetPaymentStateRequest | GetPaymentStateReply | GetPaymentState is a utility method to get the payment state of a given account. |
node/node.proto
AttestBatchReply
Field | Type | Label | Description |
---|---|---|---|
signature | bytes |
AttestBatchRequest
Field | Type | Label | Description |
---|---|---|---|
batch_header | BatchHeader | header of the batch | |
blob_header_hashes | bytes | repeated | the header hashes of all blobs in the batch |
BatchHeader
BatchHeader (see core/data.go#BatchHeader)
Field | Type | Label | Description |
---|---|---|---|
batch_root | bytes | The root of the merkle tree with hashes of blob headers as leaves. | |
reference_block_number | uint32 | The 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.
Field | Type | Label | Description |
---|---|---|---|
header | BlobHeader | Which (original) blob this is for. | |
bundles | Bundle | repeated | Each 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
Field | Type | Label | Description |
---|---|---|---|
commitment | common.G1Commitment | The KZG commitment to the polynomial representing the blob. | |
length_commitment | G2Commitment | The KZG commitment to the polynomial representing the blob on G2, it is used for proving the degree of the polynomial | |
length_proof | G2Commitment | The low degree proof. It's the KZG commitment to the polynomial shifted to the largest SRS degree. | |
length | uint32 | The length of the original blob in number of symbols (in the field where the polynomial is defined). | |
quorum_headers | BlobQuorumInfo | repeated | The params of the quorums that this blob participates in. |
account_id | string | The ID of the user who is dispersing this blob to EigenDA. | |
reference_block_number | uint32 | The reference block number whose state is used to encode the blob |
BlobQuorumInfo
See BlobQuorumParam as defined in api/proto/disperser/disperser.proto
Field | Type | Label | Description |
---|---|---|---|
quorum_id | uint32 | ||
adversary_threshold | uint32 | ||
confirmation_threshold | uint32 | ||
chunk_length | uint32 | ||
ratelimit | uint32 |
Bundle
A Bundle is the collection of chunks associated with a single blob, for a single operator and a single quorum.
Field | Type | Label | Description |
---|---|---|---|
chunks | bytes | repeated | Each chunk corresponds to a collection of points on the polynomial. Each chunk has same number of points. |
bundle | bytes | All chunks of the bundle encoded in a byte array. |
G2Commitment
Field | Type | Label | Description |
---|---|---|---|
x_a0 | bytes | The A0 element of the X coordinate of G2 point. | |
x_a1 | bytes | The A1 element of the X coordinate of G2 point. | |
y_a0 | bytes | The A0 element of the Y coordinate of G2 point. | |
y_a1 | bytes | The A1 element of the Y coordinate of G2 point. |
GetBlobHeaderReply
Field | Type | Label | Description |
---|---|---|---|
blob_header | BlobHeader | The header of the blob requested per GetBlobHeaderRequest. | |
proof | MerkleProof | Merkle 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.
MerkleProof
Field | Type | Label | Description |
---|---|---|---|
hashes | bytes | repeated | The proof itself. |
index | uint32 | Which index (the leaf of the Merkle tree) this proof is for. |
NodeInfoReply
Node info reply
NodeInfoRequest
Node info request
RetrieveChunksReply
Field | Type | Label | Description |
---|---|---|---|
chunks | bytes | repeated | All chunks the Node is storing for the requested blob per RetrieveChunksRequest. |
chunk_encoding_format | ChunkEncodingFormat | How the above chunks are encoded. |
RetrieveChunksRequest
Field | Type | Label | Description |
---|---|---|---|
batch_header_hash | bytes | The 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_index | uint32 | Which blob in the batch to retrieve for (note: a batch is logically an ordered list of blobs). | |
quorum_id | uint32 | Which 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
Field | Type | Label | Description |
---|---|---|---|
signatures | google.protobuf.BytesValue | repeated | The 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
Field | Type | Label | Description |
---|---|---|---|
blobs | Blob | repeated | Blobs to store |
reference_block_number | uint32 | The reference block number whose state is used to encode the blobs |
StoreChunksReply
Field | Type | Label | Description |
---|---|---|---|
signature | bytes | The operator's BLS signature signed on the batch header hash. |
StoreChunksRequest
Field | Type | Label | Description |
---|---|---|---|
batch_header | BatchHeader | Which batch this request is for. | |
blobs | Blob | repeated | The 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.
Name | Number | Description |
---|---|---|
UNKNOWN | 0 | |
GNARK | 1 | |
GOB | 2 |
Dispersal
Method Name | Request Type | Response Type | Description |
---|---|---|---|
StoreChunks | StoreChunksRequest | StoreChunksReply | StoreChunks 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. |
StoreBlobs | StoreBlobsRequest | StoreBlobsReply | StoreBlobs 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 |
AttestBatch | AttestBatchRequest | AttestBatchReply | AttestBatch 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 |
NodeInfo | NodeInfoRequest | NodeInfoReply | Retrieve node info metadata |
Retrieval
Method Name | Request Type | Response Type | Description |
---|---|---|---|
RetrieveChunks | RetrieveChunksRequest | RetrieveChunksReply | RetrieveChunks retrieves the chunks for a blob custodied at the Node. |
GetBlobHeader | GetBlobHeaderRequest | GetBlobHeaderReply | GetBlobHeader is similar to RetrieveChunks, this just returns the header of the blob. |
NodeInfo | NodeInfoRequest | NodeInfoReply | Retrieve node info metadata |
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.
Field | Type | Label | Description |
---|---|---|---|
by_index | ChunkRequestByIndex | Request chunks by their individual indices. | |
by_range | ChunkRequestByRange | Request chunks by a range of indices. |
ChunkRequestByIndex
A request for chunks within a specific blob. Each chunk is requested individually by its index.
Field | Type | Label | Description |
---|---|---|---|
blob_key | bytes | The blob key. | |
chunk_indices | uint32 | repeated | The index of the chunk within the blob. |
ChunkRequestByRange
A request for chunks within a specific blob. Each chunk is requested a range of indices.
Field | Type | Label | Description |
---|---|---|---|
blob_key | bytes | The blob key. | |
start_index | uint32 | The first index to start fetching chunks from. | |
end_index | uint32 | One past the last index to fetch chunks from. Similar semantics to golang slices. |
GetBlobReply
The reply to a GetBlobs request.
Field | Type | Label | Description |
---|---|---|---|
blob | bytes | The blob requested. |
GetBlobRequest
A request to fetch one or more blobs.
Field | Type | Label | Description |
---|---|---|---|
blob_key | bytes | The key of the blob to fetch. |
GetChunksReply
The reply to a GetChunks request.
Field | Type | Label | Description |
---|---|---|---|
data | bytes | repeated | The 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.
Field | Type | Label | Description |
---|---|---|---|
chunk_requests | ChunkRequest | repeated | The chunk requests. Chunks are returned in the same order as they are requested. |
operator_id | bytes | If 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. | |
timestamp | uint32 | Timestamp 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_signature | bytes | If 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 Name | Request Type | Response Type | Description |
---|---|---|---|
GetBlob | GetBlobRequest | GetBlobReply | GetBlob retrieves a blob stored by the relay. |
GetChunks | GetChunksRequest | GetChunksReply | GetChunks retrieves chunks from blobs stored by the relay. |
retriever/retriever.proto
BlobReply
Field | Type | Label | Description |
---|---|---|---|
data | bytes | The blob retrieved and reconstructed from the EigenDA Nodes per BlobRequest. |
BlobRequest
Field | Type | Label | Description |
---|---|---|---|
batch_header_hash | bytes | The 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_index | uint32 | Which blob in the batch this is requesting for (note: a batch is logically an ordered list of blobs). | |
reference_block_number | uint32 | The Ethereum block number at which the batch for this blob was constructed. | |
quorum_id | uint32 | Which 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:
- Retrieve from the Disperser that the user initially used for dispersal: the API is Disperser.RetrieveBlob() as defined in api/proto/disperser/disperser.proto
- 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 Name | Request Type | Response Type | Description |
---|---|---|---|
RetrieveBlob | BlobRequest | BlobReply | This fans out request to EigenDA Nodes to retrieve the chunks and returns the reconstructed original blob in response. |
retriever/v2/retriever_v2.proto
BlobReply
A reply to a RetrieveBlob() request.
Field | Type | Label | Description |
---|---|---|---|
data | bytes | The blob retrieved and reconstructed from the EigenDA Nodes per BlobRequest. |
BlobRequest
A request to retrieve a blob from the EigenDA Nodes via RetrieveBlob().
Field | Type | Label | Description |
---|---|---|---|
blob_header | common.v2.BlobHeader | header of the blob to be retrieved | |
reference_block_number | uint32 | The Ethereum block number at which the batch for this blob was constructed. | |
quorum_id | uint32 | Which 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:
- Retrieve from the relay that the blob is assigned to: the API is Relay.GetBlob() as defined in api/proto/relay/relay.proto
- 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 Name | Request Type | Response Type | Description |
---|---|---|---|
RetrieveBlob | BlobRequest | BlobReply | This fans out request to EigenDA Nodes to retrieve the chunks and returns the reconstructed original blob in response. |
validator/node_v2.proto
GetChunksReply
The response to the GetChunks() RPC.
Field | Type | Label | Description |
---|---|---|---|
chunks | bytes | repeated | All chunks the Node is storing for the requested blob per GetChunksRequest. |
chunk_encoding_format | ChunkEncodingFormat | The format how the above chunks are encoded. |
GetChunksRequest
The parameter for the GetChunks() RPC.
Field | Type | Label | Description |
---|---|---|---|
blob_key | bytes | The 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_id | uint32 | Which 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
Field | Type | Label | Description |
---|---|---|---|
semver | string | The version of the node. | |
arch | string | The architecture of the node. | |
os | string | The operating system of the node. | |
num_cpu | uint32 | The number of CPUs on the node. | |
mem_bytes | uint64 | The 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.
Field | Type | Label | Description |
---|---|---|---|
signature | bytes | The validator's BSL signature signed on the batch header hash. |
StoreChunksRequest
Request that the Node store a batch of chunks.
Field | Type | Label | Description |
---|---|---|---|
batch | common.v2.Batch | batch of blobs to store | |
disperserID | uint32 | ID of the disperser that is requesting the storage of the batch. | |
timestamp | uint32 | Timestamp of the request in seconds since the Unix epoch. If too far out of sync with the server's clock, request may be rejected. | |
signature | bytes | Signature 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
- 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.
Name | Number | Description |
---|---|---|
UNKNOWN | 0 | A valid response should never use this value. If encountered, the client should treat it as an error. |
GNARK | 1 | A 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 Name | Request Type | Response Type | Description |
---|---|---|---|
StoreChunks | StoreChunksRequest | StoreChunksReply | StoreChunks 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. |
GetNodeInfo | GetNodeInfoRequest | GetNodeInfoReply | GetNodeInfo fetches metadata about the node. |
Retrieval
Retrieval is utilized to retrieve chunk data.
Method Name | Request Type | Response Type | Description |
---|---|---|---|
GetChunks | GetChunksRequest | GetChunksReply | GetChunks 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. |
GetNodeInfo | GetNodeInfoRequest | GetNodeInfoReply | Retrieve node info metadata |