3

I extracted a TransactionEnvelope XDR several months ago for testing. It parses fine in the lab and the SDKs.

I've tried parsing it by hand and there's something I don't understand. After the MemoText is finished, the next item should be an int (4 bytes) count of operations. The next 4 bytes are 0, 0, 0, 0, indicating that there's zero operations. But there is actually 1 operation. As the fifth byte is 1, and the bytes that follow it decode to that single operation, it seems that there's an extra 0 byte between the Memo and the operation count.

It's not a string terminator, because the en/decoding of strings clearly uses 4 bytes to count the number of bytes in the string, followed by that quantity of bytes and no trailing bytes.

It's not a Memo terminator, because there isn't one. And it doesn't separate the Transaction data from the operation list, because there's no such separator.

The extra weird bit is when I debug the Java SDK's parsing of this, I can see the extra 0 in the buffer, but when it comes to parse the operation count, this extra byte is "magically" skipped. I can't find the code that is reading it.

Here's the Java SDK parsing code that I used for debugging:

Network.useTestNetwork();

String sample = "AAAAAHN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAFeAAAAAAAAAABAAAAAAAAAAAAAAAOAAAAAAAAAAAAAAAAAYPAuntzs/lk6C+6JkakdDhc5zXww5d6mPBdFK+c3FQAAAACVAvkAAAAAAAAAAAAAAAAALE0VmAhfAS7Juzrcn3ZJ8q6XTRMsAztEdYPxjUNGlN+AAAAAlQL5AAAAAAAAAAAAAAAAAC87zZTiuFN3kMO5HLufFatDo63xg/2ve3ivM4Jh4iM8wAAAAJUC+QAAAAAAQAAAACxNFZgIXwEuybs63J92SfKul00TLAM7RHWD8Y1DRpTfgAAAAoAAAAYbGlmZV91bml2ZXJzZV9ldmVyeXRoaW5nAAAAAQAAAAI0MgAAAAAAAQAAAAC87zZTiuFN3kMO5HLufFatDo63xg/2ve3ivM4Jh4iM8wAAAAoAAAAGZmVudG9uAAAAAAABAAAAB0ZFTlRPTiEAAAAAAQAAAAC87zZTiuFN3kMO5HLufFatDo63xg/2ve3ivM4Jh4iM8wAAAAoAAAAGZmVudG9uAAAAAAAAAAAAAQAAAAABg8C6e3Oz+WToL7omRqR0OFznNfDDl3qY8F0Ur5zcVAAAAAUAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAACxNFZgIXwEuybs63J92SfKul00TLAM7RHWD8Y1DRpTfgAAAAYAAAACQWFyZHZhcmsAAAAAAAAAAAGDwLp7c7P5ZOgvuiZGpHQ4XOc18MOXepjwXRSvnNxUAAAAAAX14QAAAAABAAAAALE0VmAhfAS7Juzrcn3ZJ8q6XTRMsAztEdYPxjUNGlN+AAAABgAAAAJCZWF2ZXIAAAAAAAAAAAAAAYPAuntzs/lk6C+6JkakdDhc5zXww5d6mPBdFK+c3FQAAAAABfXhAAAAAAEAAAAAsTRWYCF8BLsm7OtyfdknyrpdNEywDO0R1g/GNQ0aU34AAAAGAAAAAkNoaW5jaGlsbGEAAAAAAAABg8C6e3Oz+WToL7omRqR0OFznNfDDl3qY8F0Ur5zcVAAAAAAF9eEAAAAAAQAAAAABg8C6e3Oz+WToL7omRqR0OFznNfDDl3qY8F0Ur5zcVAAAAAYAAAACQ2hpbmNoaWxsYQAAAAAAAHN2/eiOTNYcwPspSheGs/HQYfXy8cpXRl+qkyIRuUbWAAAAAAX14QAAAAABAAAAAAGDwLp7c7P5ZOgvuiZGpHQ4XOc18MOXepjwXRSvnNxUAAAABwAAAACxNFZgIXwEuybs63J92SfKul00TLAM7RHWD8Y1DRpTfgAAAAJBYXJkdmFyawAAAAAAAAABAAAAAQAAAAABg8C6e3Oz+WToL7omRqR0OFznNfDDl3qY8F0Ur5zcVAAAAAcAAAAAsTRWYCF8BLsm7OtyfdknyrpdNEywDO0R1g/GNQ0aU34AAAACQ2hpbmNoaWxsYQAAAAAAAQAAAAEAAAAAAYPAuntzs/lk6C+6JkakdDhc5zXww5d6mPBdFK+c3FQAAAABAAAAALE0VmAhfAS7Juzrcn3ZJ8q6XTRMsAztEdYPxjUNGlN+AAAAAkFhcmR2YXJrAAAAAAAAAAABg8C6e3Oz+WToL7omRqR0OFznNfDDl3qY8F0Ur5zcVAAAAAAAAAIrAAAAAAAAAASHiIzzAAAAQE00K8gytC2tLc9ZNgbg5soLJxHwRuPQYIcFoEh7XA36HFPnn0adM1ytn7NF+lSc0Cuoutaaj3pgvrFfuhpZ9gUNGlN+AAAAQGzSbbChPW/f1jADXSCuDpNunHSI95Na46O8tsIWmBjdipzFZeuV2v+sgmwqjeaFE48f4VtPzULtMSR7Y8mPgAWvnNxUAAAAQMNCi/yq4becgE9Dc5XYXKu6aGfa55/jNxANPefE5e+B1n5fYWftfX/we6fEduXTTEIoHiNpsVsw7O0nouI54w0RuUbWAAAAQF4UP8Pq6xXhOOzlF3iX5nvQh5AX8+aXjq4rwzpEaTCpFCVgstD+R5qXyRq/Nyywm/JDV5nU6rbRLFciMP2r/wc=";

Transaction.fromEnvelopeXdr(sample);

And this is my console output where I'm parsing the data manually, 1 field at a time:

@ s.drop(60).take(23)
res128: Array[Byte] = Array(72, 105, 32, 90, 121, 44, 32, 104, 101, 114, 101, 115, 32, 97, 110, 32, 97, 110, 103, 112, 97, 111, 33)

@ new String(res128)
res129: String = "Hi Zy, heres an angpao!"

@ s.drop(83).take(5)
res130: Array[Byte] = Array(0, 0, 0, 0, 1)

You can see that after the String of the Memo is parsed, the subsequent bytes are 0,0,0,0,1 and not 0,0,0,1 as expected.

My question can be framed in a number of different ways, but the underlying question is the same. Why does this XDR parse OK when it has this extra 0? Why is there an extra 0 when the encoder doesn't write one? Why does the decoder ignore the extra 0?

5

I believe that is the extra padding bytes set so that the length is a multiple of 4. From the RFC 4506 (a.k.a. the XDR Spec):

The standard defines a string of n (numbered 0 through n-1) ASCII bytes to be the number n encoded as an unsigned integer (as described above), and followed by the n bytes of the string. Byte m of the string always precedes byte m+1 of the string, and byte 0 of the string always follows the string's length. If n is not a multiple of four, then the n bytes are followed by enough (0 to 3) residual zero bytes, r, to make the total byte count a multiple of four.

In this case, the string is 23 bytes long and so we have one extra byte of padding.

  • 1
    Francesco is right, it looks like the 4-bytes data structure alignment. – Orbit Lens Dec 28 '18 at 15:38
  • 1
    Thanks Francesco. I had the RFC tab open, but neglected to check it and got transfixed on the code. Thanks a bunch! – Synesso Dec 28 '18 at 22:28

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.