0

I have some code where by adding all the instructions I easily blast past the maximum transaction size of 1232 bytes. Before I go off writing my own -- is there code out there anywhere I'm overlooking to split out transactions already?

2 Answers 2

2

The ability to split a tx into multiple is very dependant of the application and can also introduce security issues by breaking atomicity.

The resulting txs might need to run in series, or could be run in any order, and that is application specific.

Good to run sequentially in series: set up ATAs, perform action

Not good to run in series: system program create account then initializing that account in another tx. Anyone can grab the created account in between if the program assigned allows it.

The only attempt I have seen at achieving it automatically is in @saber-hq/solana-contrib in the TransactionEnvelope class

https://github.com/saber-hq/saber-common/blob/454b861286ecc05e0d2eccf30d7b8781b43850d6/packages/solana-contrib/src/transaction/TransactionEnvelope.ts#L208-L214

1
  • Bah, you're right. What a pain, but for all the right reasons. Thanks for the answer. Sep 20 at 22:54
-1

I had to do something similar in TypeScript.

This function accepts array of arrays of instructions. This is important as instructions in internal arrays are considered to be atomic. While arrays themselves can be split into multiple transactions:

export const PACKET_DATA_SIZE = 1280 - 40 - 8;
export const SIGNATURE_LENGTH = 64;


export const splitInstructions = (
  ixss: TransactionInstruction[][],
  recentBlockhash: string,
  feePayer: PublicKey,
): Transaction[] => {
  const txs = [];
  const dummy = new Keypair();

  let i = 0;
  let j = ixss.length;
  while (i !== ixss.length) {
    const dummyTx = new Transaction();
    ixss.slice(i, j).forEach((ixs) => ixs.forEach((ix) => dummyTx.add(ix)));
    dummyTx.recentBlockhash = recentBlockhash;
    dummyTx.sign(dummy);
    const transactionLength =
      dummyTx.compileMessage().serialize().length +
      SIGNATURE_LENGTH +
      1; /* SIGNATURE_LENGTH_SIZE */
    if (transactionLength <= PACKET_DATA_SIZE) {
      const tx = new Transaction();
      ixss.slice(i, j).forEach((ixs) => ixs.forEach((ix) => tx.add(ix)));
      tx.recentBlockhash = recentBlockhash;
      tx.feePayer = feePayer;
      txs.push(tx);
      i = j;
      j = ixss.length;
    } else {
      j -= 1;
      if (j < i) {
        throw new Error("A single instruction doesn't fit into a transaction");
      }
    }
  }
  return txs;
};

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.