How to decipher mweb blocks and transactions

Hello! We have a software which parses Litecoin blocks. Basically we read block header and then transactions one by one. It stopped working with MW update, the first block which failed is 2265984. Can you please help me understand format of MW-enabled blocks? The last transaction which can be parsed with our software for the block 2265984 is:

2b78b424eb1d325a037c0e8a23ae4a7082b52fefb70b5f056656842bb50cb4d3 (cannot put links as I’m new user, use litecoinblockexplorer dot net to decipher and see raw payload)

But then we have the whole lot of bytes:

02000000000801f0e3f3ee06603dec65d593a4efede7da81dcf999d4c07a5e11f51fe526ce544e0000000000ffffffff01a6437307000000002258202d19998ab39025280552c7d88725c9c212587091502dcfadc98ac41e15009f6b0000000000018089a600ec59e1becf5c0bc0c1f08fb34caa02b89b0aa2165637dc0ed05ebab92b9b65325dbfd10771054953618690cc065b8aab5045028266e12ac84b2ff08bfd3e9cb2af2edc674154ff129d9e826727ada0828d3ba480924bbed84bf6dcae2e1f1db28ea89151e5daf7e29dd4c5d45d705d294ec897641c5b3deb29da341db39cc3b8ba26531869d89b3f427d721abfd1667fa5a90027d4f6949aff8a7c1b4417412502010002098bc23843a3d486ab40e61f2ce497278bbf26f7c05ed5b0cc4eb7be3a2810c9f70320f88895c3810a1e248c999ab8aa5077ab074479ee0c5a8dc373849c98d807e8038d25ab07a3440a0d59be1da60ff01af2dd735c768294773e08cee78718f881af0103c2ff90299306a70fabd462f00179e42689a66e030b78a98984983671169761c18e66eefd47db95baa593e35739ba2d211eba4169a3c0de94b989b04c51ccd74650ff56ef6af7c110e48f00e14d665db3570b1e55b3c26bfa23849e7757f58aeeab9220dae0a44684e52bebbcb1ea5e3b25efaf55cb8ea5ad4a0c3a5f0cf7cd58e092ddbe631b96d142e9ff2f71cb1c8db94d5655abfe681e938723db70a956add4f93dee77d8f03ae0ea04d0bf29890c1fce1ea26ac38e1c57afc0719c3b436f6caecfddf5ad0981ef44b4c0920a2ebc44fbafb26ad7f3b6bad9eb6133ec99262aea4f07bf14e58d414ec97f78fc4425c5c3d61161a270544f3fb7911b34ad13f8d7cfd8d85c22dc9a64ff92461254f1541dbd5298a1c1007557121a09d9d224e1e9a3e737d9c683a468027030a2fc69805927fc1637c2bdc7a7f84795df6cf52b89703aadbc1aa8d7a3a3d6869705e93bd8ef060893c476cbb7975482f4f4dcb6fe6a60ee51cca0af0cdf58afee551e6fe44ce4fc7c06e2a976a639fe49fbf12d95be601199b45fd54c49d593e557f91d49de04c34dcd5575545d03f523ae513b84ab87ab9b1d9cd7379c373f3d84f4bd062271c99441a0fd3a19f97c1f4df1525138da8033d0b3337d7487971ec4020c5d024d961496af5b40d4dcbbdece160cc501d174d1cfbc407b65c55b6f593a2299752dd957da6b66a4724242188665d7ed5ea3d255793f94e9bafa58077beafcac8e296da080ed576504a36e6154829fb8c4d9233c2213e050d89a13331794c5fc8b9859fbe5c31f125d60feb75d3bdacbc8b9c3d75cb6c5527c23f70db069ed04976f100d16b067a40073db03e0d0f6561b8878cac70df0a499804a294162a68dc05086086b15ebb0f0a56c3bd0621242073d07c447ae393fed0e83be5cedba7a9b6f7b05943de4917057ac3c22d5fdac10247dd9971673c15db36bbbc35a24ea96f04ba78f917bdd6aeae7a74490a57883fed4495a5ac4f6837414df1116ccc40f738d80dec1971af1ba607db3c2716f9c9077f65a30cbfca889f94175bff39962d67b8d715b69e4ed694541c1e4283896e6a280ac0c36fa64d3b33408ffe7b480775e414c2acef4791c084c8c162c685d22f1648856b92f879500a86ee3961f21e2c3fa5283352740dbc10276c160c52f1f952d6810885c325ac0982f5260a6f1719edbfbeef7041f064e0d0343c21f0266614d68f33870832fd7d31e372cfe3c29b6d345fcb51314cd4ecef4010241bdba8a6a56dc33bb6328d1269699657cdac2e6a61115cb2995d8f9933ba5451675b1d7e0e39269ba8201b54a6eeab5ac1da9fd4027d2aed02c4cdd296323b6ac04fd29d37cf3fcf15115ef7462d1a999d6884f876f5f75418cca5167a887d53e45714e911327bb1f42bc8a5d32d8727a50bd7f7a7cdcd16a070245d1154912d1536d012ab204bc69d8125c2e8204e999815ad82f2c1280b48e22d5af70e670904c10c966e0d8b4f7103fd267673a960bb2e6ac99b4b4ee23c05dd4572400da76a0c8529e5e3eaf8f035f9d0008748d54b6dc9cc1102e688f8d0d9d09353be061c88d1a1512a347a5e46eca1dbf2e32627919bb16566ac55aaa21ae24e992e39e29479c4e83a5852bdb28f57070633196a0f0a5f2e2c1bb0d6f5cc438a0c25db9d940e9d5c838fd95a7325a923351ba3a5c6d8682a0e2023871c6a1a05313f953689774f5f23b20c66211640f9339c4ae96753161d4ce57560759a5d023109c58049c3dc56f30b58105cf1c51b6180926b0dbd022604e271b80d192f26ef52aa90d888e09951f41b4a7f91e0ba98aae2d4fa3251bcd129592b1820062e50190bdcf0a7941469ca27c232dddc84602855861a677f109d55283201da41e0cb7aa74e7345f19ac2aeab883d7c3cd54bed1615023145a98d5ad6f143b0600bd30bd49a37741964ee858ab66fb20cfc96fc1dacd5701fef25ea5386a550866fc2275dba3359fc9110fb017c0f824dafc7ec9bcf8ccbf487f76ed1c6ba89ccbcc20e89f4f5afeb7a3594e49c7b63e15560f777d58dee684d21fb63cee24ab772d0aeea834696c8dc782a08a4a1f1d6ffc1cec959c88227ef34bfce55fa81c859b0506861c011d30959c959f49575d7ab2313ccab4ef96a8ad57cdcb86ff081f38728c74b40c3336440a43ab4f1b20b86c46270d6cd18ef0200065c2f3117dd8e5f6bc3b41495b65aff4ecef5d7e8b066233d64f03470a515058212d7894976f224c02e8b555554dc3f2abf6f1ea8f1370335e4e8bb4524b4719cbac0bf3d52878a17752b99b3e8348bb908392850a16e4b667b92ca4a022e91ff93f0711547d7ba587377d3c9896407259a7788575d9c4ede71dec960994fc6cd9790adfe701139d3cbacca46203b1fb7c0fe800d947415a6b6acd0f440486797f1efbabcfd6cb02a72584b8e66e08c80c2f3214064aec8645605dd4ea2f0d019a0ec6cc46b7d6bf1fe933afb786a88a670d88232009c8a44a323e4a18cac95b90676d49f823ccece449c9261dd3d4dac4578d16617e62edf4074a9c1f315de21496c6b4d0cfdfbe910b33e946f0f0

I assume 0200 is a transaction version 2, but what to do with the rest of the bytes? Explorer shows some simple transaction:

69b57b9d080622e82b795ecff246b34c78d9b2d095e8622ba7a5412008c1409b

I have tried to find documentation about MW, but found close to none. Please direct me towards proper documentation, preferably with examples.

1 Like

I am also facing the similar problem. Can anyone help?

Here’s my understanding, but a more authoritative answer would be helpful.

For a MWEB-versioned block, the last transaction in the regular block (non-MWEB) transactions will be a “integration” or HogEx transaction. This is indicated by the block header’s Version bits. After this txn is the extension block itself.

In my application, I believe I only need to deserialize the regular transactions, discarding both the integration tx and the WMEB itself. So if that works for you, I think you can check the block Version with the mask 0x20000000 (1 << 29), and if that’s set, expect the final txn to have its tx flag to have bit 3 set (8). Note in 02000000000801 you can see the tx flag set this way (normally it’s just 1 for a witness tx). This tx will also have an output with a pkScript using witness version 8 (MWEB_HOG_ADDR_WITNESS_VERSION) i.e. OP_8/0x58 like 58202d1... as in your paste.

After that HogEx, it’s the MWEB. See the LIPs and the code for that structure, but I’m just discarding it.

Refs:

The following code is not in production, but it is working to get the block header and all but the integration transaction, and we’re considering this approach: dcrdex/block.go at cac2f85170af29fd123926d691c1e7205faaa1ec · decred/dcrdex · GitHub

Thank you very much, very useful. Will ignore HogEx and EB.

Note that one can also run litecoind with -rpcserialversion=1 and the MWEB stuff is deleted from the serialization.

@chappjc Thank you for your explanation.
It seems that you have finally figured out the structure of MWEB txs and are parsing them fully here:
[Unable to post links as a new user!]
github…/decred/dcrdex/blob/89273503dcd19210b6150c9360ee9cd581b6edc9/dex/networks/ltc/tx.go#L211

am I right?

In this case, would it be possible for you to please explain what’s the overall structure of such blocks and how the byte string must be parsed? (I’m not that familiar with Go)

@David Would you please shed light on the structure of MWEB blocks and transactions? Any link to public documentation describing the format of such blocks and how to parse their byte string would be greatly appreciated. If there is no such document, please let us know to see what other way we can understand them…

Let me know if this is clear enough for your needs.

This might also be quite useful if you’re trying to decode mweb blocks and transactions: MWEB tx deserialisation by losh11 · Pull Request #31 · ltcsuite/ltcd · GitHub Special thanks to @chappjc.