I am trying to send borsh serialized data from JS to rust application. However, when serialising data in javascript AND rust (to compare the outputs), I am getting 4 extra bytes in rust serialised output. Here is the code:
Borsh JS code
// class class Poll { id: string = ''; question: string = ''; options: string[] = []; votes: number[] = []; constructor(fields?: { id: string; question: string; options: string[]; votes: number[]; }) { if (fields) { this.id = fields.id; this.question = fields.question; this.options = fields.options; this.votes = fields.votes; } } } // Schema const schema: Schema = new Map([ [ Poll, { kind: 'struct', fields: [ ['id', 'string'], ['question', 'string'], ['options', ['string']], ['votes', ['u32', 1]], ], }, ], ]); // class object const testPoll = new Poll({ id: '1', question: 'What is your favorite color?', options: ['a', 'b', 'c'], votes: [100], }); //object serialization let serializedPoll: Uint8Array = new Uint8Array(); serializedPoll = serialize(schema, testPoll); // this succeeds // output [1, 0, 0, 0, 49, 28, 0, 0, 0, 87, 104, 97, 116, 32, 105, 115, 32, 121, 111, 117, 114, 32, 102, 97, 118, 111, 114, 105, 116, 101, 32, 99, 111, 108, 111, 114, 63, 3, 0, 0, 0, 1, 0, 0, 0, 97, 1, 0, 0, 0, 98, 1, 0, 0, 0, 99, 100, 0, 0, 0]
Borsh Rust Code
#[derive(BorshDeserialize, BorshSerialize, Debug)] pub struct Poll { pub id: String, pub question: String, pub options: Vec<String>, pub votes: Vec<u32>, } // poll object - with same values as that in JS code above let p = Poll { id: "1".to_string(), question: "What is your favorite color?".to_string(), options: vec!["a".to_string(), "b".to_string(), "c".to_string()], votes: vec![100], }; // serialization let serialized_data = p.try_to_vec().unwrap(); // this succeeds //output [1, 0, 0, 0, 49, 28, 0, 0, 0, 87, 104, 97, 116, 32, 105, 115, 32, 121, 111, 117, 114, 32, 102, 97, 118, 111, 114, 105, 116, 101, 32, 99, 111, 108, 111, 114, 63, 3, 0, 0, 0, 1, 0, 0, 0, 97, 1, 0, 0, 0, 98, 1, 0, 0, 0, 99, 1, 0, 0, 0, 100, 0, 0, 0]
Comparing outputs of both
- Borsh JS
- Borsh Rust
[1, 0, 0, 0, 49, 28, 0, 0, 0, 87, 104, 97, 116, 32, 105, 115, 32, 121, 111, 117, 114, 32, 102, 97, 118, 111, 114, 105, 116, 101, 32, 99, 111, 108, 111, 114, 63, 3, 0, 0, 0, 1, 0, 0, 0, 97, 1, 0, 0, 0, 98, 1, 0, 0, 0, 99, 100, 0, 0, 0] [1, 0, 0, 0, 49, 28, 0, 0, 0, 87, 104, 97, 116, 32, 105, 115, 32, 121, 111, 117, 114, 32, 102, 97, 118, 111, 114, 105, 116, 101, 32, 99, 111, 108, 111, 114, 63, 3, 0, 0, 0, 1, 0, 0, 0, 97, 1, 0, 0, 0, 98, 1, 0, 0, 0, 99, 1, 0, 0, 0, 100, 0, 0, 0]
There are extra 4 bytes (1, 0, 0, 0) in rust serialised output.
I believe this is happening because of Vec<u32>
used for votes
field (it works fine for u32
). However I am unable to understand why this is happening.
Any sort of help/insights are appreciated.
Thank you!
Advertisement
Answer
A Vec<u32>
has to encode the length of the data since a Vec
represents a variable size. Conversely, you’ve designed your schema in JS as ['u32', 1]
which is an array of length 1, so it does not need to encode a length since it is a fixed size.
To resolve the difference, either set your schema to a variable size array: ['u32']
. Or change your type in Rust to be a fixed-size array: votes: [u32; 1]
.