diff --git a/src/NLitecoin/Litecoin.fs b/src/NLitecoin/Litecoin.fs index 760ae0c..5c347e8 100644 --- a/src/NLitecoin/Litecoin.fs +++ b/src/NLitecoin/Litecoin.fs @@ -90,9 +90,12 @@ type LitecoinTransaction() = flags <- flags ^^^ 1uy if (flags &&& mwebExtensionTxFlag) <> 0uy then - let version = ref 0uy - stream.ReadWrite version - self.MimbleWimbleTransaction <- Some(MimbleWimble.Transaction.Read stream) + let isMWTransactionPresent = stream.ReadWrite Unchecked.defaultof + if isMWTransactionPresent <> 0uy then + self.MimbleWimbleTransaction <- Some(MimbleWimble.Transaction.Read stream) + else + // HogEx transaction + self.MimbleWimbleTransaction <- None flags <- flags ^^^ 8uy if flags <> 0uy then @@ -142,7 +145,8 @@ type LitecoinTransaction() = match self.MimbleWimbleTransaction with | Some mwebTransaction -> - stream.ReadWrite MimbleWimble.Transaction.Version |> ignore + let valueIsPresentMarker = 1uy + stream.ReadWrite valueIsPresentMarker |> ignore (mwebTransaction :> MimbleWimble.ISerializeable).Write stream | None -> () diff --git a/src/NLitecoin/MimbleWimble/Types.fs b/src/NLitecoin/MimbleWimble/Types.fs index 113ddc7..1748028 100644 --- a/src/NLitecoin/MimbleWimble/Types.fs +++ b/src/NLitecoin/MimbleWimble/Types.fs @@ -712,7 +712,6 @@ type Transaction = // The transaction body. Body: TxBody } - static member Version = 1uy /// Parse hex-encoded MimbleWimble transaction static member ParseString(txString: string) : Transaction = diff --git a/tests/NLitecoin.MimbleWimble.Tests/NLitecoin.MimbleWimble.Tests.fsproj b/tests/NLitecoin.MimbleWimble.Tests/NLitecoin.MimbleWimble.Tests.fsproj index 2119e36..5e2f4c5 100644 --- a/tests/NLitecoin.MimbleWimble.Tests/NLitecoin.MimbleWimble.Tests.fsproj +++ b/tests/NLitecoin.MimbleWimble.Tests/NLitecoin.MimbleWimble.Tests.fsproj @@ -8,6 +8,9 @@ + + Always + Always diff --git a/tests/NLitecoin.MimbleWimble.Tests/TransactionTests.fs b/tests/NLitecoin.MimbleWimble.Tests/TransactionTests.fs index b0e448a..596cdec 100644 --- a/tests/NLitecoin.MimbleWimble.Tests/TransactionTests.fs +++ b/tests/NLitecoin.MimbleWimble.Tests/TransactionTests.fs @@ -69,3 +69,13 @@ let ParsePegOutTransaction () = Validation.ValidateTransactionBody transaction.Body Validation.ValidateKernelSumForTransaction transaction + +[] +let ParseBlockWithHogExTransaction () = + // Check if HogEx transaction, which has mweb extension flag but doesn't contain MW transaction, is pardsed correctly + let blockData = IO.File.ReadAllText "block1.txt" + let block = NBitcoin.Block.Parse(blockData, NLitecoin.Litecoin.Instance.Mainnet) + // HogEx transaction must be at the end of the block + // (see https://github.com/litecoin-project/lips/blob/master/lip-0002.mediawiki#user-content-Integrating_Transaction_ExtTxn) + let lastTransaction = block.Transactions.[block.Transactions.Count - 1] :?> NLitecoin.LitecoinTransaction + Assert.IsTrue(lastTransaction.MimbleWimbleTransaction.IsNone) diff --git a/tests/NLitecoin.MimbleWimble.Tests/block1.txt b/tests/NLitecoin.MimbleWimble.Tests/block1.txt new file mode 100644 index 0000000..efa34da --- /dev/null +++ b/tests/NLitecoin.MimbleWimble.Tests/block1.txt @@ -0,0 +1 @@ +0000002037C3D1A8A8DE1E51AD8D3BB9866671D4994611EF2B3E561B80CF96EC0FEAC6B9AFA64AA0BA761A131621B83C10811741CE75017D2CEBC23EB05FAB305011D735FE6A3A65FFFF7F200600000003020000000001010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF0502B0010101FFFFFFFF02140B824A000000001600141500D9EB709B25A56B523104D883E9F38D8E346E0000000000000000266A24AA21A9ED260AD835EBC9334E20017EA11BBAD893D8E9EEF1A3AA283A50363C55B185B641012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101D58B7B0D601DF7D1C567FBE8F7B19B34F8583A12CC7C632FF03FF1FE938114590000000000FEFFFFFF01A872052A0100000022592008A5CCDDDE3AD474194F0540CCCA9A5BD74265DECB8AC200A515782521029C6702473044022066E2DD706A8AF63D25D9F21DC5C8842836D9F508EB423DB614169946315A90E702200614568C1778DCE3567DEC60FE6060BA9FDE75733C9CBEB72389223FA527876601210324B1C90D01D167AA88DAE5447B1B4E479AD8228BC174E2601B750A16EE94730EAF01000002000000000801D8D6C49E7D97BBFA9E1E6BCBD7E94D6BB0E773B27951055B0EE3A911351CA4F10000000000FFFFFFFF016C63052A0100000022582083A772E96B12E03CC234A48BDD7474749C9984032EE10DC72B048E17E579FBD1000000000001823066313BE96A43C32A20E7951EB52EDC7C15200505F59B767E542F82AA3EEDE40CF96D8F1200F9B4ED65960CE43FD8378319BEC86C46811CC71265BBF30B60F401AF2EDC674154FF129D9E826727ADA0828D3BA480924BBED84BF6DCAE2E1F1DB268BC457FCF5E99B14CC9B5477A9F67BDADAA1F6FEDCCF97A6E4490E6A1D5FBDE6CD43CF80643380C5D6AF43439E93DFC12554DDE4A414A878AE9BCDDAEC994B70201000208CDBCE43C8FAD17E523EE75030DE21719ED9ED418310B66281F59239FC0B652EF033C0A0B330F2D790C613717257EB5BFDCD835022C81E5ABEAD18F3CAAEEDC10DB0340F4B66050085A5F6F932310963A50A1DAA26F3F22EA4D256C85E4F38261936101028A709A126DCAB20650E51FF16AD992B1D0AD54A75A626DA30C91FA6D086D0C339C33455E35486AE54C1061B861BC68FF4F1AE4AF6063752F0B28E66AE26298FB8A89029DF6978578419D14DC0940710FEE13CAAC40788A25E6854B8E8AC88DB8F95DBAFD1F1F7BA0C82B4CB8EF4AA602A2AD806AFA1DE98B8B0835048BE996EE4CB189D2484820BE584E24E2A65AC8D662CF09C3F4A8D411FC8A12E3392B46F38871EA7FF85669F740E521B744B726749CBCC1C669917E8C067983AC76C097E7A52EEC7A3D7FE8CD12D4194CF6571050A54DC98DAA50DAA251E12389B43B6875120A662BDE26548B2BEEA716381D7D37828EF5228F3624BA08ACE75C36FC964D04127627A880895214918989A1B16ACBE442B3431E134DBDB71704F7527F693F09ABA9E235FF35A8BCF675140D680D88C874E102D13E814274151353B16580607F57E12CB09618FE21E2AA4C1FB55DFC382BE6A4D7C3E34221AD45E24C34D6BE95952F802E2EB8EFBE9CC2A060D05A3E68283BE2195183A7FA18CA1E6C96901B28FD0E93FE8BA4B7D46FCEEAF217D7B0D92E2B584AC6CF46629845032534D37F55422472BAFDD26291778E93E6363757002D2EE82FB055C42664DFC40C6771210000BA4212BA434865A3C0C7ACAC8AA5CB798353E34545CC69BB02E150C93E63DA80834A7564C82194A7916E4188D10D4CC8CDC866FDF269EEA879857A7410B6B643511E2953014B9D1F97B3079B7585FFEBD2E19C3F0B3D93E5525B71677BBFBF6919F219C7EE56B11ACBA306427C7A21968A18273849380E42CAB80B4C55A791D55A2D5409ADE5C983E8F46B59099C47E0F8E4A3FDCB39FB1D090465107FC7BDF3B05A7BDEFE35EC8C0F0548E48DD1DA0F5388A7605A723F7CC24B9FEC7C9063A329E39D22A0C3858B9067A177D7EC3504609309F1CC243C419AE5FAD0C719703D9A280ED5279958D9CC5AEEDC61F4D318F69030407C9815385BE28421DAA231F3E2E5FEA5EE0A76B8FE3102E6F84EF78F611E30385B36434828FC3C32B67473A466E4E70A2B5D211C4DEF56CE3D88379B32DCE70A4E75B53A4CEE53B9311936D6285BE6296D06CF5904165CEB30EE695E886C0902E9FBF36FED6F09E69851FF41562E0E2734A49E44E932823BBAFA56B13E2C1DB9EBCC0D27A0BD9F031429144BAAE14A98DA3ECE5E2098DB22E2CB56FA3533E094CA74014509A0FBD803000505E782A5FCEFEFB9C32677D8ABEE300EF5B0D36B55FD1F733356F168BE6A010283FC80195F400F46D1EC0D7BDB73CFE8875C20179E9DBEA7F5D334076AC24B8AA1736706E22AD93E9B7D2E19EE1C5D6A967D6A6B206969130DACEC029BB3A3A470A255B925C5632B7A2565C00E7BA6FAEF650CAD0D6B4B56209E3CA8B3F234E0884A44CE2A683A542F5C6BF0E84086690D66DA2768989E24D4070FB2BB47A68C5B12440F620E7BDB3385F6714734D1BE5F8C6DB069B26019F414942C78D364225DC4EFEAF98D38EB0B2C22371FC390144B2E88AE44C1B28A8058326E08880FAA9BB90CB6F6EF3A918D26D6237CEE30F719B8CC6FC4D0517EE844AECDB9B07A2B9972E41659942D6F6B8535B9EB0515AB8540BA12BAF1999264AA5249B8D2D0C4E5F000AA65638EE295A83B3979B518B1C366BA69BF3E3E48DC1B7E1F51C30355477CC927B1CABFE9FE346C815B7BBC7C2C27C0427551391D4A40BFC77CAA5CF44C75DC0AB0139029C7AA769F6685F79AE71F9DEAB4348F45348FCABC47D81E865A0410B61F2591E9288C33C03BF5A03D1C2F468002487A0B9A15938DFFC56F7F866A7683B792C16137B3781D2B7ECE381821ACC2CEC43CD3BD9F3001E5600EBDD925B1248F5B6BBD0975009FA98C1E74A78D24EC5593FD9F02E99FE2BC215D923150D126B7EE378EA18FCC2C174B7799568869A343B6419FC91CF13E280A05B119D84C35571BB60155CD524EA2D2DD382747AE21D2DD024277EF07DB4A92544C23BD7E8AD21941C7782D0FF10FCCAC8CAA425835FF76EC73FFCB20D08E4BF5B2486E29FED081D35B65D94CF50025EBE6BE072D85277CFFBD4BC9786D73CA17893E74C868A5F05D80DE06B647A6F40337350D080CF9EAAAB20DD6007F493E4B590AA11DAB394C8736083723BEF482E0F7723AE00299B70F319661B6A325AE25583D57C8F44BC0375A6AB0079AA30B003A1592AAF2ABBC5343BE56915EB01419226BBEA5B85C770E56C2D9D380368943B9FC5770BEB6E47CC30DDAA52F9958A6E844BDC48C9094DCF911E587591BEC71D0413F777A921F98D3027483C8888E0631CF9B32AD8E7169A2228EAD38A26FD4A0ED5E55A29845BC0F45633F5C4CF1FFCD1A36160CB30D5575A34E3B9037C27679CC7D2FF41BB1E17FAEFCF83A01139D3C91CF94E428021B768DDA5822104465A13DE66930A11C0CAC248FA6F41E505DA7325068703C0D0935652B6E778004EF3FD23ABB6DE5C2B7F489B8DF4B9AE88B680DC4130C271C09B2B09549CCF6BE6A924CF36CB0F04DF374F280CEE2465152BE3C87286ED643AC0728EF0029D17FD102E702499089D299806326D17A543F3E9495DA315F3D5ABD \ No newline at end of file