@@ -47,6 +47,9 @@ class Transaction with Writable {
4747 final List <Input > inputs;
4848 final List <Output > outputs;
4949 final Locktime locktime;
50+ /// Raw MWEB extension data carried between the witness data and locktime,
51+ /// as used by Litecoin. This is kept as opaque bytes.
52+ final Uint8List ? mwebBytes;
5053
5154 /// Constructs a transaction with the given [inputs] and [outputs] .
5255 /// [TransactionTooLarge] will be thrown if the resulting transction exceeds
@@ -59,6 +62,7 @@ class Transaction with Writable {
5962 required Iterable <Input > inputs,
6063 required Iterable <Output > outputs,
6164 this .locktime = Locktime .zero,
65+ this .mwebBytes,
6266 })
6367 : inputs = List .unmodifiable (inputs),
6468 outputs = List .unmodifiable (outputs)
@@ -77,11 +81,17 @@ class Transaction with Writable {
7781
7882 final version = reader.readInt32 ();
7983
84+ bool hasWitness = false ;
85+ bool hasMweb = false ;
8086 if (witness) {
81- // Check for witness data
87+ // Check for witness data. The 0x01 flag bit signals witness data and
88+ // the 0x08 flag bit signals MWEB data as used by Litecoin.
8289 final marker = reader.readUInt8 ();
8390 final flag = reader.readUInt8 ();
84- if (marker != 0 || flag != 1 ) return null ;
91+ if (marker != 0 ) return null ;
92+ hasWitness = (flag & 1 ) != 0 ;
93+ hasMweb = (flag & 8 ) != 0 ;
94+ if (! hasWitness && ! hasMweb) return null ;
8595 }
8696
8797 final rawInputs = List .generate (
@@ -96,17 +106,27 @@ class Transaction with Writable {
96106
97107 // Match the raw inputs with witness data if this is a witness transaction
98108 final inputs = rawInputs.map (
99- (raw) => Input .match (raw, witness ? reader.readVector () : []),
109+ (raw) => Input .match (raw, hasWitness ? reader.readVector () : []),
100110 // Create list now to ensure we read the witness data before the locktime
101111 ).toList ();
102112
113+ // Any MWEB data is carried between the witness data and the locktime
114+ Uint8List ? mwebBytes;
115+ if (hasMweb) {
116+ final remaining = reader.bytes.lengthInBytes - reader.offset;
117+ if (remaining > 4 ) {
118+ mwebBytes = reader.readSlice (remaining - 4 );
119+ }
120+ }
121+
103122 final locktime = reader.readUInt32 ();
104123
105124 return Transaction (
106125 version: version,
107126 inputs: inputs,
108127 outputs: outputs,
109128 locktime: Locktime (locktime),
129+ mwebBytes: mwebBytes,
110130 );
111131
112132 }
@@ -166,7 +186,7 @@ class Transaction with Writable {
166186
167187 if (isWitness) {
168188 writer.writeUInt8 (0 ); // Marker
169- writer.writeUInt8 (1 ); // Flag
189+ writer.writeUInt8 (mwebBytes != null ? 9 : 1 ); // Flag
170190 }
171191
172192 writer.writeVarInt (BigInt .from (inputs.length));
@@ -185,6 +205,10 @@ class Transaction with Writable {
185205 }
186206 }
187207
208+ if (mwebBytes != null ) {
209+ writer.writeSlice (mwebBytes! );
210+ }
211+
188212 writer.writeUInt32 (locktime.value);
189213
190214 }
@@ -194,6 +218,7 @@ class Transaction with Writable {
194218 inputs: newInputs,
195219 outputs: outputs,
196220 locktime: locktime,
221+ mwebBytes: mwebBytes,
197222 );
198223
199224 T _requireInputOfType <T >(int inputN) {
@@ -346,6 +371,7 @@ class Transaction with Writable {
346371 ],
347372 outputs: outputs,
348373 locktime: locktime,
374+ mwebBytes: mwebBytes,
349375 );
350376
351377 /// Returns a new [Transaction] with the [output] added to the end of the
@@ -370,6 +396,7 @@ class Transaction with Writable {
370396 inputs: modifiedInputs,
371397 outputs: [...outputs, output],
372398 locktime: locktime,
399+ mwebBytes: mwebBytes,
373400 );
374401
375402 }
@@ -394,6 +421,7 @@ class Transaction with Writable {
394421 ),
395422 outputs: outputs,
396423 locktime: locktime,
424+ mwebBytes: mwebBytes,
397425 )
398426 : this ;
399427
@@ -414,8 +442,9 @@ class Transaction with Writable {
414442 String get txid
415443 => bytesToHex (Uint8List .fromList (legacyHash.reversed.toList ()));
416444
417- /// If the transaction has any witness inputs.
418- bool get isWitness => inputs.any ((input) => input is WitnessInput );
445+ /// If the transaction has any witness inputs or carries MWEB data.
446+ bool get isWitness
447+ => inputs.any ((input) => input is WitnessInput ) || mwebBytes != null ;
419448
420449 bool get isCoinBase
421450 => inputs.length == 1
0 commit comments