insertSignature method

P2SHMultisigInput insertSignature(
  1. ECDSAInputSignature insig,
  2. ECPublicKey pubkey,
  3. Uint8List getSigHash(
    1. SigHashType hashType
    )
)

Returns a new P2SHMultisigInput with the new signature added in order. The pubkey should be the public key for the signature to ensure that it matches. getSigHash obtains the signature hash for a given type so that existing signatures can be checked. If existing signatures are not in-order then they may not be fully matched and included in the resulting input. If there are more signatures than the required threshold, the last signature will be removed.

Implementation

P2SHMultisigInput insertSignature(
  ECDSAInputSignature insig,
  ECPublicKey pubkey,
  Uint8List Function(SigHashType hashType) getSigHash,
) {

  final pubkeys = program.pubkeys;

  // Create list that will match signatures to the public keys in order
  List<ECDSAInputSignature?> positionedSigs
    = List.filled(pubkeys.length, null);

  // Iterate both public key positions and signatures sequentially as they
  // should already be in order
  for (int pos = 0, sigI = 0; pos < pubkeys.length; pos++) {

    final numAdded = positionedSigs.whereType<ECDSAInputSignature>().length;

    // Check existing first to ensure they get matched
    if (
      // Check all signatures have not already been matched
      sigI != sigs.length
      // Do not add any more when threshold is reached
      && numAdded < program.threshold
      // Check signature against candidate public key and message hash
      && sigs[sigI].signature.verify(
        pubkeys[pos], getSigHash(sigs[sigI].hashType),
      )
    ) {
      // Existing signature matched for this public key
      positionedSigs[pos] = sigs[sigI++];
    }

    // Check new signature last to ensure it gets included
    if (pubkey == pubkeys[pos]) positionedSigs[pos] = insig;

  }

  return P2SHMultisigInput(
    prevOut: prevOut,
    program: program,
    // Remove nulls leaving actual signatures and trim down to threshold if
    // needed
    sigs: positionedSigs
      .whereType<ECDSAInputSignature>()
      .take(program.threshold),
    sequence: sequence,
  );

}