sign method

dynamic sign({
  1. required int vin,
  2. required ECPair keyPair,
  3. String? prevOutScriptType,
  4. Uint8List? redeemScript,
  5. int? witnessValue,
  6. Uint8List? witnessScript,
  7. int? hashType,
})

Implementation

dynamic sign({required int vin, required ECPair keyPair, String? prevOutScriptType, Uint8List? redeemScript, int? witnessValue, Uint8List? witnessScript, int? hashType}) {
  if (keyPair.network.toString().compareTo(network.toString()) != 0) throw ArgumentError('Inconsistent network');
  if (vin >= _inputs!.length) throw ArgumentError('No input at index: $vin');

  hashType = hashType ?? SIGHASH_ALL;
  if (_needsOutputs(hashType)) throw ArgumentError('Transaction needs outputs');

  final input = _inputs![vin];
  final ourPubKey = keyPair.publicKey;

  // if redeemScript was previously provided, enforce consistency
  if (input.redeemScript != null && redeemScript != null && input.redeemScript.toString() != redeemScript.toString()) throw ArgumentError('Inconsistent redeemScript');

  if (!_canSign(input)) {
    if (witnessValue != null) {
      if (input.value != null && input.value != witnessValue) throw ArgumentError('Input did not match witnessValue');
      input.value = witnessValue;
    }

    if (redeemScript != null && witnessScript != null) { }
    if (redeemScript != null) {
      final p2sh = P2SH(data: PaymentData(redeem: PaymentData(output: redeemScript)), network: network);
      if (input.prevOutScript != null) { }
      final expanded = OutputBase.expandOutput(p2sh.data.redeem!.output, ourPubKey);

      if (expanded.pubkeys == null) throw ArgumentError('${expanded.type} not supported as redeemScript (${bscript.toASM(redeemScript)})');

      if (input.signatures != null && input.signatures!.any((x) => x != null)) expanded.signatures = input.signatures;

      Uint8List? signScript = redeemScript;
      if (expanded.type == SCRIPT_TYPES['P2WPKH']) {
        signScript = P2PKH(data: PaymentData(pubkey: expanded.pubkeys![0]), network: network).data.output;
      }
      input.redeemScript = redeemScript;
      input.redeemScriptType = expanded.type;
      input.prevOutType = SCRIPT_TYPES['P2SH'];
      input.prevOutScript = p2sh.data.output;
      input.hasWitness = (expanded.type == SCRIPT_TYPES['P2WPKH']);
      input.signScript = signScript;
      input.signType = expanded.type;
      input.pubkeys = expanded.pubkeys;
      input.signatures = expanded.signatures;
      input.maxSignatures = expanded.maxSignatures;
    }
    if (witnessScript != null) { }

    if (input.prevOutScript != null && input.prevOutType != null) {
      var type = classifyOutput(input.prevOutScript!);
      if (type == SCRIPT_TYPES['P2WPKH']) {
        input.prevOutType = SCRIPT_TYPES['P2WPKH'];
        input.hasWitness = true;
        input.signatures = [null];
        input.pubkeys = [ourPubKey];
        input.signScript = P2PKH(data: PaymentData(pubkey: ourPubKey), network: network).data.output;
      } else if (type == SCRIPT_TYPES['P2PKH']) {
        var prevOutScript = pubkeyToOutputScript(ourPubKey);
        input.prevOutType = SCRIPT_TYPES['P2PKH'];
        input.signatures = [null];
        input.pubkeys = [ourPubKey];
        input.signScript = prevOutScript;
      } else { }
    } else {
      var prevOutScript = pubkeyToOutputScript(ourPubKey);
      input.prevOutType = SCRIPT_TYPES['P2PKH'];
      input.signatures = [null];
      input.pubkeys = [ourPubKey];
      input.signScript = prevOutScript;
    }
  }
  var signatureHash = input.hasWitness || (hashType & SIGHASH_BITCOINCASHBIP143) > 0 ?  _tx.hashForWitnessV0(vin, input.signScript!, input.value!, hashType) : _tx.hashForSignature(vin, input.signScript, hashType);
  // enforce in order signing of public keys
  var signed = false;
  for (var i = 0; i < input.pubkeys!.length; i++) {
    if (HEX.encode(ourPubKey!).compareTo(HEX.encode(input.pubkeys![i]!)) != 0) continue;
    if (input.signatures![i] != null) throw ArgumentError('Signature already exists');

    final signature = keyPair.sign(signatureHash);
    input.signatures![i] = bscript.encodeSignature(signature, hashType);
    signed = true;
  }

  if (!signed) throw ArgumentError('Key pair cannot sign for this input');
}