verify method

  1. @override
bool verify()
override

Implementation

@override
bool verify() {
  final inputs = txData.inputs;
  if (inputs.isEmpty || !txData.isSigned) return false;

  final btc.Transaction tx;
  try {
    tx = btc.Transaction.fromHex(txData.hex);
  } catch (_) {
    return false;
  }
  if (tx.ins.length != inputs.length) return false;

  final inputAddress = wallet.publicKeyToAddress(wallet.publicKey);
  final prevOutScript = btc.Address.addressToOutputScript(
    inputAddress,
    networkType,
  );
  if (prevOutScript == null) return false;

  final allPrevScripts = <Uint8List>[];
  final allValues = <int>[];
  for (final input in inputs) {
    if (input.amount == null) return false;
    allPrevScripts.add(prevOutScript);
    allValues.add(input.amount!);
  }

  for (var i = 0; i < inputs.length; i++) {
    final input = inputs[i];
    final sidecarSignature = input.signature;
    if (sidecarSignature == null) return false;

    final txInput = tx.ins[i];
    late final Uint8List signature;
    late final int hashType;

    if (isTaprootInput) {
      final witness = txInput.witness;
      if (txInput.script?.isNotEmpty ?? false) return false;
      if (witness == null || witness.length != 1 || witness[0] == null) {
        return false;
      }

      final encodedSignature = witness[0]!;
      if (encodedSignature.length == 64) {
        hashType = btc.SIGHASH_DEFAULT;
        signature = encodedSignature;
      } else if (encodedSignature.length == 65) {
        hashType = encodedSignature[64];
        if (!_isValidTaprootHashType(hashType)) return false;
        signature = Uint8List.fromList(encodedSignature.sublist(0, 64));
      } else {
        return false;
      }
    } else {
      if (txInput.witness?.isNotEmpty ?? false) return false;
      final chunks = bscript.decompile(txInput.script);
      if (chunks == null ||
          chunks.length != 2 ||
          chunks[0] is! Uint8List ||
          chunks[1] is! Uint8List) {
        return false;
      }

      signature = chunks[0] as Uint8List;
      final publicKey = chunks[1] as Uint8List;
      if (signature.isEmpty ||
          !bscript.bip66check(signature.sublist(0, signature.length - 1)) ||
          dynamicToString(publicKey) != dynamicToString(wallet.publicKey)) {
        return false;
      }
      hashType = signature.last;
    }

    if (hashType != _hashTypeFor(input) ||
        dynamicToString(signature) != dynamicToString(sidecarSignature)) {
      return false;
    }

    final Uint8List sigHash;
    try {
      sigHash = _sigHashFor(
        tx,
        i,
        prevOutScript,
        allPrevScripts,
        allValues,
        hashType,
      );
    } catch (_) {
      return false;
    }

    if (!wallet.verify(
      dynamicToString(signature),
      dynamicToString(sigHash),
    )) {
      return false;
    }
  }
  return true;
}