/// <summary> /// Performs signature verification /// </summary> /// <param name="message">raw message to verify</param> /// <returns>bool</returns> public bool Verify(byte[] message) { if (this.version == 1 && this.threshold > 0 && this.subsigs.Count != 0) { if (this.threshold > this.subsigs.Count) { return(false); } else { int verifiedCount = 0; Signature emptySig = new Signature(); for (int i = 0; i < this.subsigs.Count; ++i) { MultisigSubsig subsig = subsigs[i]; if (!subsig.sig.Equals(emptySig)) { try { var pk = subsig.key; var signer = new Ed25519Signer(); signer.Init(false, pk); //for verify signer.BlockUpdate(message, 0, message.Length); bool verified = signer.VerifySignature(subsig.sig.Bytes); if (verified) { ++verifiedCount; } } catch (Exception var9) { throw new ArgumentException("verification of subsig " + i + "failed", var9); } } } if (verifiedCount < this.threshold) { return(false); } else { return(true); } } } else { return(false); } }
/// <summary> /// MergeMultisigTransactions merges the given (partially) signed multisig transactions. /// </summary> /// <param name="txs">partially signed multisig transactions to merge. Underlying transactions may be mutated.</param> /// <returns>merged multisig transaction</returns> public static SignedTransaction MergeMultisigTransactions(params SignedTransaction[] txs) { if (txs.Length < 2) { throw new ArgumentException("cannot merge a single transaction"); } SignedTransaction merged = txs[0]; for (int i = 0; i < txs.Length; i++) { // check that multisig parameters match SignedTransaction tx = txs[i]; if (tx.mSig.version != merged.mSig.version || tx.mSig.threshold != merged.mSig.threshold) { throw new ArgumentException("transaction msig parameters do not match"); } for (int j = 0; j < tx.mSig.subsigs.Count; j++) { MultisigSubsig myMsig = merged.mSig.subsigs[j]; MultisigSubsig theirMsig = tx.mSig.subsigs[j]; if (!theirMsig.key.Equals(myMsig.key)) { throw new ArgumentException("transaction msig public keys do not match"); } if (myMsig.sig.Equals(new Signature())) { myMsig.sig = theirMsig.sig; } else if (!myMsig.sig.Equals(theirMsig.sig) && !theirMsig.sig.Equals(new Signature())) { throw new ArgumentException("transaction msig has mismatched signatures"); } merged.mSig.subsigs[j] = myMsig; } } return(merged); }
/// <summary> /// Appends a signature to multisig logic signed transaction /// </summary> /// <param name="lsig">LogicsigSignature append to</param> /// <returns>LogicsigSignature</returns> public LogicsigSignature AppendToLogicsig(LogicsigSignature lsig) { var pk = this.GetEd25519PublicKey(); int pkIndex = -1; for (int i = 0; i < lsig.msig.subsigs.Count; i++) { MultisigSubsig subsig = lsig.msig.subsigs[i]; if (Enumerable.SequenceEqual(subsig.key.GetEncoded(), pk.GetEncoded())) { pkIndex = i; } } if (pkIndex == -1) { throw new ArgumentException("Multisig account does not contain this secret key"); } // now, create the multisignature byte[] bytesToSign = lsig.BytesToSign(); Signature sig = this.RawSignBytes(bytesToSign); lsig.msig.subsigs[pkIndex] = new MultisigSubsig(pk, sig); return(lsig); }