Skip to main content
The kate_queryRows method retrieves complete rows from the Kate commitment data availability matrix for a specified block.

Method Signature

async fn query_rows(
    &self,
    rows: Rows,
    at: Option<HashOf<Block>>
) -> RpcResult<Vec<GRow>>

Parameters

rows
Rows
required
Array of row indices to query from the data matrix.Type: BoundedVec<u32, MaxRows> where MaxRows = 64Maximum: 64 rows per requestExample: [0, 1, 5] to query rows 0, 1, and 5
at
Hash
default:"null"
Block hash at which to query the rows. If not provided, uses the best (latest finalized) block.Format: 32-byte hexadecimal hash prefixed with 0xExample: "0x1234...abcd"

Returns

result
Vec<GRow>
Array of rows, where each row is a vector of 256-bit scalars representing the data cells.Type Definition:
pub type GRawScalar = U256;
pub type GRow = Vec<GRawScalar>;
Each GRow contains the complete data for one row of the matrix, with each element representing a cell in that row.

Example Request

curl -X POST http://localhost:9944 \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "kate_queryRows",
    "params": [
      [0, 1],
      "0xa1b2c3d4e5f6789012345678901234567890123456789012345678901234567890"
    ],
    "id": 1
  }'

Example Response

{
  "jsonrpc": "2.0",
  "result": [
    [
      "0x1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef1234567890",
      "0x234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12",
      "0x34567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234"
      // ... more cells in row 0
    ],
    [
      "0x4567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef123456",
      "0x567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567",
      "0x67890abcdef1234567890abcdef1234567890abcdef1234567890abcdef12345678"
      // ... more cells in row 1
    ]
  ],
  "id": 1
}

Query Without Block Hash

If you don’t specify a block hash, the method queries the latest finalized block:
{
  "jsonrpc": "2.0",
  "method": "kate_queryRows",
  "params": [[0]],
  "id": 1
}

Error Responses

Block Not Finalized

If the requested block is not yet finalized:
{
  "jsonrpc": "2.0",
  "error": {
    "code": 1,
    "message": "Requested block 0xa1b2...7890 is not finalized"
  },
  "id": 1
}

Empty Commitments

If the block has no data commitments (e.g., contains only system extrinsics):
{
  "jsonrpc": "2.0",
  "error": {
    "code": 1,
    "message": "Requested block 0xa1b2...7890 has empty commitments"
  },
  "id": 1
}

Invalid Block Number

If the block hash doesn’t exist:
{
  "jsonrpc": "2.0",
  "error": {
    "code": 1,
    "message": "Invalid block number: ..."
  },
  "id": 1
}

Missing Block

If the block is not available:
{
  "jsonrpc": "2.0",
  "error": {
    "code": 1,
    "message": "Missing block 0xa1b2...7890"
  },
  "id": 1
}

Too Many Rows

If requesting more than 64 rows:
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32602,
    "message": "Invalid params: rows exceeds maximum length"
  },
  "id": 1
}

Implementation Details

Source Code Reference

From /rpc/kate-rpc/src/lib.rs:205-224:
async fn query_rows(&self, rows: Rows, at: Option<HashOf<Block>>) -> RpcResult<Vec<GRow>> {
    let _metric_observer = MetricObserver::new(ObserveKind::KateQueryRows);

    let (api, at, number, block_len, extrinsics, header) = self.scope(at)?;

    match header.extension() {
        HeaderExtension::V3(ext) => {
            if ext.commitment.commitment.is_empty() {
                return Err(internal_err!("Requested block {at} has empty commitments"));
            }
        },
    };

    let grid_rows = api
        .rows(at, number, extrinsics, block_len, rows.into())
        .map_err(|kate_err| internal_err!("Failed Kate rows: {kate_err:?}"))?
        .map_err(|api_err| internal_err!("Failed API: {api_err:?}"))?;

    Ok(grid_rows)
}

Validation Steps

  1. Block Finalization: Ensures the requested block is finalized
  2. Commitment Check: Verifies the block has non-empty data commitments
  3. Row Retrieval: Fetches the requested rows from the Kate API
  4. Metrics: Records query performance metrics (if enabled)

Use Cases

Data Availability Sampling

Validators can sample entire rows to verify data availability:
// Sample rows 0, 5, and 10 from the latest block
const rows = await rpc('kate_queryRows', [[0, 5, 10]]);

Block Reconstruction

Light clients can reconstruct portions of a block:
// Retrieve first 4 rows for reconstruction
const blockHash = '0x...';
const rows = await rpc('kate_queryRows', [[0, 1, 2, 3], blockHash]);

Row Verification

Verify specific rows against commitments:
// Query row and verify against header commitment
const [row] = await rpc('kate_queryRows', [[rowIndex], blockHash]);
const header = await rpc('chain_getHeader', [blockHash]);
// Verify row against header.extension.commitment

Build docs developers (and LLMs) love