From f5bce709d9e0bfbfe733a67b21440e9de61bba42 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 16 Jul 2026 21:53:22 -0800 Subject: [PATCH] feat: support extra payload data in transactions (vExtraData) Add an optional vExtraData field to Transaction, serialized as a var-length slice after the locktime. This supports special transactions carrying an extra payload, such as Firo masternode (DIP2-style) transactions. The field is carried through input/output modification copies and legacy sighash computation. Ported from cypherstack/coinlib commit 22778c0. --- .../lib/src/tx/sighash/legacy_signature_hasher.dart | 1 + coinlib/lib/src/tx/transaction.dart | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/coinlib/lib/src/tx/sighash/legacy_signature_hasher.dart b/coinlib/lib/src/tx/sighash/legacy_signature_hasher.dart index daf0396..1ff2f0d 100644 --- a/coinlib/lib/src/tx/sighash/legacy_signature_hasher.dart +++ b/coinlib/lib/src/tx/sighash/legacy_signature_hasher.dart @@ -71,6 +71,7 @@ final class LegacySignatureHasher extends SignatureHasher { inputs: modifiedInputs, outputs: modifiedOutputs, locktime: tx.locktime, + vExtraData: tx.vExtraData, ); // Add sighash type onto the end diff --git a/coinlib/lib/src/tx/transaction.dart b/coinlib/lib/src/tx/transaction.dart index aefd7bb..36f8049 100644 --- a/coinlib/lib/src/tx/transaction.dart +++ b/coinlib/lib/src/tx/transaction.dart @@ -47,6 +47,7 @@ class Transaction with Writable { final List inputs; final List outputs; final Locktime locktime; + final Uint8List? vExtraData; /// Constructs a transaction with the given [inputs] and [outputs]. /// [TransactionTooLarge] will be thrown if the resulting transction exceeds @@ -59,6 +60,7 @@ class Transaction with Writable { required Iterable inputs, required Iterable outputs, this.locktime = Locktime.zero, + this.vExtraData, }) : inputs = List.unmodifiable(inputs), outputs = List.unmodifiable(outputs) @@ -187,6 +189,10 @@ class Transaction with Writable { writer.writeUInt32(locktime.value); + if (vExtraData != null) { + writer.writeVarSlice(vExtraData!); + } + } Transaction _newInputs(List newInputs) => Transaction( @@ -194,6 +200,7 @@ class Transaction with Writable { inputs: newInputs, outputs: outputs, locktime: locktime, + vExtraData: vExtraData, ); T _requireInputOfType(int inputN) { @@ -346,6 +353,7 @@ class Transaction with Writable { ], outputs: outputs, locktime: locktime, + vExtraData: vExtraData, ); /// Returns a new [Transaction] with the [output] added to the end of the @@ -370,6 +378,7 @@ class Transaction with Writable { inputs: modifiedInputs, outputs: [...outputs, output], locktime: locktime, + vExtraData: vExtraData, ); } @@ -394,6 +403,7 @@ class Transaction with Writable { ), outputs: outputs, locktime: locktime, + vExtraData: vExtraData, ) : this;