Skip to content

Add support for building a struct decoder where later fields can depend on earlier ones #1448

@mcintyre94

Description

@mcintyre94

Motivation

The v1 transaction codec makes heavy use of dependencies between fields. numInstructions is encoded early on, and later is required to know how to decode instruction headers (encoded as an array with no size prefix). The instruction header for instruction N is required to decode the instruction payload.

Currently this can't be expressed as a struct decoder, because we don't have access to the decoded values in those earlier fields when writing the decoder for the later ones.

Example use case

For v1 transactions it would be great to be able to write something like (pseudocode, simplified):

getStructDecoder([
  ['numInstructions', getU8Decoder()],
  ['numStaticAccounts', getU8Decoder()],
  ['instructionHeaders', (fields) => getArrayDecoder(getInstructionHeaderDecoder(), { size: fields.numInstructions }),
  // more fields
])

Details

I think this would be very difficult to do with the current getStructDecoder fields array, because there's no type-safe way to access the earlier fields when defining that array.

However, it could be done using a builder pattern, where we add .field(name, decoder) one at a time:

const decoder = structDecoderBuilder()
  .field('numInstructions', getU8Decoder())
  .field('numStaticAccounts', getU8Decoder())
  .field('instructionHeaders', fields => getArrayDecoder(getInstructionHeaderDecoder(), { size: fields.numInstructions }))
  // more .field calls
  .build();

This would allow fields to be defined at each stage as an object containing all previously decoded values, meaning that we can write the mappings from already decoded fields to a later field decoder in a type-safe way.

Claude coded prototype with tests: main...struct-codec-dependencies

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions