2

I want to interact with a program and discover this website: https://bettercallsol.dev/

Basically it allows you to serialize the data using both Borsh & Buffer layout.

Despite they are two different methods, but the input and output of serialization looks the same.

I just wonder what is the difference between them? Does program has to deal with them differently? Or is it just a preference and not much difference?

Because I have tested locally and it seems like both of them works on the same program.

Here is my program state source:

use borsh::{BorshDeserialize, BorshSerialize};

#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
pub struct Counter {
    pub count: u64,
    pub label: u64,
}


impl Counter {
  pub fn new(count: u64, label: u64) -> Self {
    Counter {
        count,
        label
    }
  }
}

and here is my serialization code:

function createDecrementInstruction(
  accounts: Instruction1Accounts,
  args: Instruction1Args
): TransactionInstruction {

  // option 1 to encode calldata using buffer layout
  let calldata1 = encodeData(NATIVE_PROGRAM_INSTRUCTION_LAYOUTS.Instruction1, args)

  // option 2 to encode calldata using borsh
  const initializeSchema = new Map(
    [
      [
        CounterArgs,
        {
          kind: "struct",
          fields: [
            ["instruction", "u8"],
          ]
        }
      ],
    ]
  );

  const c = new CounterArgs({
    instruction: 1,
  });
  let calldata2 = Buffer.from(borsh.serialize(initializeSchema, c));

  return new TransactionInstruction({
    programId: PROGRAM_ID,
    keys: [
      {
        pubkey: accounts.counter,
        isSigner: false,
        isWritable: true
      }
    ],
    data: calldata1
    // data: calldata2, // ths works as well
  })
}

Thanks!

1 Answer 1

2

Borsh is just a particular serialization format, given by the spec at https://borsh.io/. They also provide libraries for serializing and deserializing types based on that spec.

Buffer layout is a JS library for specifying exactly how to serialize and deserialize a type to and from bytes.

In the end, both get you to and from bytes. Borsh will adhere to a specification for serializing and deserializing, and typically do more with less work. Buffer layout gives you more flexibility, but you need to define the serialization by hand for each type.

So in the end, it depends on what you prefer! Using Borsh is typically easiest to get things working quickly, but sometimes you'll need buffer-layout for custom types.

2
  • Got it, thanks! I noticed that there is another serialize/deserialize lib called Serde, does the serialization output of Serde also the same as borsh? And do I need to handled the deserialization differently at my rust program? Thanks again :)
    – johnhckuo
    Commented Dec 9, 2023 at 5:48
  • 1
    Serde is a generic serialization library, so it can work with many different formats. From their docs, here are the different formats that it supports: serde.rs/#data-formats, so just knowing that it uses serde isn't enough. You still need to know what data format the type using. For example, a lot of the Solana core types use bincode with serde, but bincode is inefficient when used in an on-chain program.
    – Jon C
    Commented Dec 9, 2023 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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