Skip to content

Implement appendFile JSON-RPC method #20

Description

@aceppaluni

Problem

The TCK server does not implement appendFile, so the TCK driver's FileAppendTransaction suite cannot run against the Python SDK. The SDK transaction (src/hiero_sdk_python/file/file_append_transaction.py) already exists and already extends ChunkedTransaction.

Blocked by hiero-ledger#2488 (createFile) — needs the file-service TCK modules and a created file to append to. Soft-blocked by hiero-ledger#2492 (deleteFile) — one spec test ("Appends to a deleted file") needs delete to exist; it can stay skipped until hiero-ledger#2492 lands. Related to bug hiero-ledger#2480 (ChunkedTransaction body-bytes fix) — see chunking notes below.

This is the most involved of the six file-service methods because it exercises chunking — recommended last in the sequence, and better suited to skill: intermediate than the other five.

Solution

Add an appendFile handler wrapping FileAppendTransaction.

Method contract (from the spec):

Input Type Required Notes
fileId string optional
contents string required Content to append
maxChunks number optional Default 20
chunkSize number optional Default 4096 (bytes)
commonTransactionParams object optional

Output: status — reuse StatusOnlyResponse from tck/response/base.py.

Implementation steps:

  1. Add AppendFileParams(BaseTransactionParams) to tck/param/file.py with fileId, contents, maxChunks, chunkSize (use to_int() for the numerics).
  2. Add the handler to tck/handlers/file.py:
    @rpc_method("appendFile")
    def append_file(params: AppendFileParams) -> StatusOnlyResponse:
        client = get_client(params.sessionId)
        transaction = FileAppendTransaction().set_grpc_deadline(DEFAULT_GRPC_TIMEOUT)
    
        if params.fileId is not None:
            transaction.set_file_id(FileId.from_string(params.fileId))
        if params.contents is not None:
            transaction.set_contents(params.contents)
        if params.maxChunks is not None:
            transaction.set_max_chunks(params.maxChunks)
        if params.chunkSize is not None:
            transaction.set_chunk_size(params.chunkSize)
    
        if params.commonTransactionParams is not None:
            params.commonTransactionParams.apply_common_params(transaction, client)
    
        response = transaction.execute(client, wait_for_receipt=False)
        receipt = response.get_receipt(client, validate_status=True)
        return StatusOnlyResponse(ResponseCode(receipt.status).name)
  3. Add unit tests under tests/tck/ covering both single-chunk and multi-chunk paths.

Chunking notes — read before starting:

  • Do not re-implement chunking. FileAppendTransaction extends ChunkedTransaction and its own defaults (max_chunks=20, chunk_size=4096) match the spec exactly. (The ChunkedTransaction base default is chunk_size=1024FileAppendTransaction deliberately overrides it; don't "fix" that.) Just wire set_max_chunks() / set_chunk_size().
  • Setter order matters: the chunk count derives from len(contents) / chunk_size, so set contents and chunk size before anything reads the chunk count.
  • execute() vs execute_all(): ChunkedTransaction has both; execute() returns the first chunk's response. The spec wants a single status, so execute() is right — but verify a failure in a later chunk still surfaces instead of reporting the first chunk's SUCCESS.
  • Interaction with signers: apply_common_params() calls freeze_with(client) then signs. For a chunked transaction that freeze must cover every chunk body — exactly the surface open bug Fix ChunkedTransaction to create transaction_body_bytes for all chunks hiero-ledger/hiero-sdk-python#2480 touches ("Fix ChunkedTransaction to create transaction_body_bytes for all chunks"). If a multi-chunk append with signers fails, check Fix ChunkedTransaction to create transaction_body_bytes for all chunks hiero-ledger/hiero-sdk-python#2480 before debugging your handler, and coordinate there rather than working around it.
  • Test with >4096 bytes of content (forces multiple chunks) both with and without signers.

Acceptance criteria

  • appendFile registered and dispatchable
  • Single-chunk append (<4096 bytes) succeeds
  • Multi-chunk append (>4096 bytes) succeeds, including with commonTransactionParams.signers
  • maxChunks / chunkSize overrides honoured; content exceeding maxChunks * chunkSize surfaces a proper error
  • Invalid fileId format → SDK internal error; non-existent ID → network INVALID_FILE_ID
  • Unit tests added; uv run pytest tests/tck -q passes

Spec: https://github.com/hiero-ledger/hiero-sdk-tck/blob/main/docs/test-specifications/file-service/FileAppendTransaction.md

JS reference: https://github.com/hiero-ledger/hiero-sdk-js/blob/main/tck/methods/file.ts (appendFile)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions