Skip to content

Commit

Permalink
Add anyprevout and anyprevoutscript flags to sighash type
Browse files Browse the repository at this point in the history
  • Loading branch information
peerchemist committed Nov 28, 2024
1 parent d66f2de commit aabc78c
Showing 1 changed file with 61 additions and 28 deletions.
89 changes: 61 additions & 28 deletions coinlib/lib/src/tx/sighash/sighash_type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,32 @@
/// Signatures may sign different output and inputs to allow for transaction
/// modifications. To sign an entire transaction the [all] constructor should be
/// used.
/// Supports SIGHASH_ANYPREVOUT and SIGHASH_ANYPREVOUTANYSCRIPT.
class SigHashType {

/// Special value representing the default Schnorr behaviour to sign
/// everything. This is encoded as an absent byte.
static const schnorrDefaultValue = 0;

/// Value to sign all outputs
static const allValue = 1;

/// Value to sign no outputs
static const noneValue = 2;

/// Value to sign the output at the same index as the input
static const singleValue = 3;

/// Flag that can be combined with other hash type values to only sign the
/// input containing the signature
static const anyOneCanPayFlag = 0x80;

/// The single byte representation of the sighash type. Use [all], [none],
/// [single] and [anyOneCanPay] to extract details of the type.
/// Flag for SIGHASH_ANYPREVOUT (APO)
static const anyPrevOutFlag = 0x40;

/// Flag for SIGHASH_ANYPREVOUTANYSCRIPT (APOAS)
static const anyPrevOutAnyScriptFlag = 0xC0;

/// The single-byte representation of the sighash type.
final int value;

/// Returns true if the sighash type value is valid.
Expand All @@ -45,40 +53,65 @@ class SigHashType {
/// only acceptable for Taproot Schnorr signatures.
const SigHashType.schnorrDefault() : value = schnorrDefaultValue;

/// Sign all of the outputs. If [anyOneCanPay] is true, then only the input
/// containing the signature will be signed.
/// If [anyOneCanPay] is false and a Taproot input is being signed, this will
/// be treated as "SIGHASH_DEFAULT".
const SigHashType.all({ bool anyOneCanPay = false })
: value = allValue | (anyOneCanPay ? anyOneCanPayFlag : 0);
/// Sign all outputs. Optional flags can be set to modify the behavior.
const SigHashType.all({
bool anyOneCanPay = false,
bool anyPrevOut = false,
bool anyPrevOutAnyScript = false,
}) : value = allValue |
(anyOneCanPay ? anyOneCanPayFlag : 0) |
(anyPrevOutAnyScript
? anyPrevOutAnyScriptFlag
: (anyPrevOut ? anyPrevOutFlag : 0));

/// Sign no outputs. If [anyOneCanPay] is true, then only the input containing
/// the signature will be signed.
const SigHashType.none({ bool anyOneCanPay = false })
: value = noneValue | (anyOneCanPay ? anyOneCanPayFlag : 0);
/// Sign no outputs. Optional flags can be set to modify the behavior.
const SigHashType.none({
bool anyOneCanPay = false,
bool anyPrevOut = false,
bool anyPrevOutAnyScript = false,
}) : value = noneValue |
(anyOneCanPay ? anyOneCanPayFlag : 0) |
(anyPrevOutAnyScript
? anyPrevOutAnyScriptFlag
: (anyPrevOut ? anyPrevOutFlag : 0));

/// Sign the output at the same index as the input. If [anyOneCanPay] is true,
/// then only the input containing the signature will be signed.
const SigHashType.single({ bool anyOneCanPay = false })
: value = singleValue | (anyOneCanPay ? anyOneCanPayFlag : 0);
/// Sign the output at the same index as the input. Optional flags can be set.
const SigHashType.single({
bool anyOneCanPay = false,
bool anyPrevOut = false,
bool anyPrevOutAnyScript = false,
}) : value = singleValue |
(anyOneCanPay ? anyOneCanPayFlag : 0) |
(anyPrevOutAnyScript
? anyPrevOutAnyScriptFlag
: (anyPrevOut ? anyPrevOutFlag : 0));

/// If this is the default hash type for a Schnorr signature.
/// Checks if this is the default hash type for a Schnorr signature.
bool get schnorrDefault => value == schnorrDefaultValue;

/// All outputs shall be signed
bool get all => value == schnorrDefaultValue
|| (value & ~anyOneCanPayFlag) == allValue;
/// No outputs shall be signed
bool get none => (value & ~anyOneCanPayFlag) == noneValue;
/// Only the output with the same index as the input shall be signed
bool get single => (value & ~anyOneCanPayFlag) == singleValue;
/// Only the input receiving the signature shall be signed
/// All outputs shall be signed.
bool get all => value == schnorrDefaultValue || (value & 0x03) == allValue;

/// No outputs shall be signed.
bool get none => (value & 0x03) == noneValue;

/// Only the output with the same index as the input shall be signed.
bool get single => (value & 0x03) == singleValue;

/// Only the input receiving the signature shall be signed.
bool get anyOneCanPay => (value & anyOneCanPayFlag) != 0;

/// The signature can sign any previous output.
bool get anyPrevOut => (value & anyPrevOutFlag) != 0 || anyPrevOutAnyScript;

/// The signature can sign any previous output and any script.
bool get anyPrevOutAnyScript =>
(value & anyPrevOutAnyScriptFlag) == anyPrevOutAnyScriptFlag;

@override
bool operator==(Object other) => other is SigHashType && value == other.value;
bool operator ==(Object other) =>
other is SigHashType && value == other.value;

@override
int get hashCode => value;

}

0 comments on commit aabc78c

Please sign in to comment.