public static ScriptSigs CombineSignatures(Script scriptPubKey, TransactionChecker checker, ScriptSigs input1, ScriptSigs input2) { if (scriptPubKey == null) { scriptPubKey = new Script(); } var scriptSig1 = input1.ScriptSig; var scriptSig2 = input2.ScriptSig; HashVersion hashVersion = HashVersion.Original; var isWitness = input1.WitSig != WitScript.Empty || input2.WitSig != WitScript.Empty; if (isWitness) { scriptSig1 = input1.WitSig.ToScript(); scriptSig2 = input2.WitSig.ToScript(); hashVersion = HashVersion.Witness; } var context = new ScriptEvaluationContext(); context.ScriptVerify = ScriptVerify.StrictEnc; context.EvalScript(scriptSig1, checker, hashVersion); var stack1 = context.Stack.AsInternalArray(); context = new ScriptEvaluationContext(); context.ScriptVerify = ScriptVerify.StrictEnc; context.EvalScript(scriptSig2, checker, hashVersion); var stack2 = context.Stack.AsInternalArray(); var result = CombineSignatures(scriptPubKey, checker, stack1, stack2, hashVersion); if (result == null) { return(scriptSig1.Length < scriptSig2.Length ? input2 : input1); } if (!isWitness) { return new ScriptSigs() { ScriptSig = result, WitSig = WitScript.Empty } } ; else { return(new ScriptSigs() { ScriptSig = input1.ScriptSig.Length < input2.ScriptSig.Length ? input2.ScriptSig : input1.ScriptSig, WitSig = new WitScript(result) }); } }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, Money value, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var eval = new ScriptEvaluationContext { SigHash = sigHash, ScriptVerify = scriptVerify }; var result = eval.VerifyScript(scriptSig, scriptPubKey, tx, i, value); error = eval.Error; return result; }
public static bool IsCanonicalBlockSignature(Block block, bool checkLowS) { if (BlockStake.IsProofOfWork(block)) { return(block.BlockSignatur.IsEmpty()); } return(checkLowS ? ScriptEvaluationContext.IsLowDerSignature(block.BlockSignatur.Signature) : ScriptEvaluationContext.IsValidSignatureEncoding(block.BlockSignatur.Signature)); }
public bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction txTo, int nIn) { ScriptEvaluationContext evaluationCopy = null; if (!EvalScript(scriptSig, txTo, nIn)) { return(false); } if ((ScriptVerify & ScriptVerify.P2SH) != 0) { evaluationCopy = Clone(); } if (!EvalScript(scriptPubKey, txTo, nIn)) { return(false); } if (Result == null || Result.Value == false) { return(false); } // Additional validation for spend-to-script-hash transactions: if (((ScriptVerify & ScriptVerify.P2SH) != 0) && scriptPubKey.IsPayToScriptHash) { this.Load(evaluationCopy); evaluationCopy = this; if (!scriptSig.IsPushOnly) { return(false); } // stackCopy cannot be empty here, because if it was the // P2SH HASH <> EQUAL scriptPubKey would be evaluated with // an empty stack and the EvalScript above would return false. if (evaluationCopy.Stack.Count == 0) { throw new InvalidProgramException("stackCopy cannot be empty here"); } var pubKeySerialized = evaluationCopy.Stack.Pop(); Script pubKey2 = new Script(pubKeySerialized); if (!evaluationCopy.EvalScript(pubKey2, txTo, nIn)) { return(false); } return(evaluationCopy.Result != null && evaluationCopy.Result.Value); } return(true); }
public static bool CheckBlockSignature(Block block) { if (BlockStake.IsProofOfWork(block)) { return(block.BlockSignatur.IsEmpty()); } if (block.BlockSignatur.IsEmpty()) { return(false); } var txout = block.Transactions[1].Outputs[1]; if (PayToPubkeyTemplate.Instance.CheckScriptPubKey(txout.ScriptPubKey)) { var pubKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(txout.ScriptPubKey); return(pubKey.Verify(block.GetHash(), new ECDSASignature(block.BlockSignatur.Signature))); } if (IsProtocolV3((int)block.Header.Time)) { // Block signing key also can be encoded in the nonspendable output // This allows to not pollute UTXO set with useless outputs e.g. in case of multisig staking var ops = txout.ScriptPubKey.ToOps().ToList(); if (!ops.Any()) // script.GetOp(pc, opcode, vchPushValue)) { return(false); } if (ops.ElementAt(0).Code != OpcodeType.OP_RETURN) // OP_RETURN) { return(false); } if (ops.Count < 2) // script.GetOp(pc, opcode, vchPushValue) { return(false); } var data = ops.ElementAt(1).PushData; if (!ScriptEvaluationContext.IsCompressedOrUncompressedPubKey(data)) { return(false); } return(new PubKey(data).Verify(block.GetHash(), new ECDSASignature(block.BlockSignatur.Signature))); } return(false); }
public static bool VerifyScript(Script scriptSig, Transaction tx, int i, TxOut spentOutput, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { if (spentOutput == null) { throw new ArgumentNullException(nameof(spentOutput)); } var eval = new ScriptEvaluationContext { SigHash = sigHash, ScriptVerify = scriptVerify }; var result = eval.VerifyScript(scriptSig, tx, i, spentOutput); error = eval.Error; return(result); }
public bool SignedByMe(Transaction tx) { for (int i = 0; i < tx.Inputs.Count; i++) { var vin = tx.Inputs[i]; var key = GetKey(vin.ScriptSig.GetSourcePubKey()); if (key == null) { return(false); } var pubkeyScript = new PayToPubkeyHashTemplate().GenerateScriptPubKey(key.PubKey); var eval = new ScriptEvaluationContext(); eval.SigHash = SigHash.All; if (!eval.VerifyScript(vin.ScriptSig, pubkeyScript, tx, i)) { return(false); } } return(true); }
public static Script CombineSignatures(Script scriptPubKey, Transaction transaction, int n, Script scriptSig1, Script scriptSig2) { if (scriptPubKey == null) { scriptPubKey = new Script(); } ScriptEvaluationContext context = new ScriptEvaluationContext(); context.ScriptVerify = ScriptVerify.StrictEnc; context.EvalScript(scriptSig1, transaction, n); var stack1 = context.Stack.Reverse().ToArray(); context = new ScriptEvaluationContext(); context.ScriptVerify = ScriptVerify.StrictEnc; context.EvalScript(scriptSig2, transaction, n); var stack2 = context.Stack.Reverse().ToArray(); return(CombineSignatures(scriptPubKey, transaction, n, stack1, stack2)); }
/// <summary> /// Check if valid transaction signature /// </summary> /// <param name="sig">The signature</param> /// <param name="scriptVerify">Verification rules</param> /// <param name="error">Error</param> /// <returns>True if valid</returns> public static bool IsValid(byte[] sig, ScriptVerify scriptVerify, out ScriptError error) { if (sig == null) { throw new ArgumentNullException(nameof(sig)); } if (sig.Length == 0) { error = ScriptError.SigDer; return(false); } error = ScriptError.OK; var ctx = new ScriptEvaluationContext() { ScriptVerify = scriptVerify }; if (!ctx.CheckSignatureEncoding(sig)) { error = ctx.Error; return(false); } return(true); }
private static bool VerifySignature(Transaction txFrom, Transaction txTo, int txToInN, ScriptVerify flagScriptVerify) { var input = txTo.Inputs[txToInN]; if (input.PrevOut.N >= txFrom.Outputs.Count) { return(false); } if (input.PrevOut.Hash != txFrom.GetHash()) { return(false); } var output = txFrom.Outputs[input.PrevOut.N]; var txData = new PrecomputedTransactionData(txFrom); var checker = new TransactionChecker(txTo, txToInN, output.Value, txData); var ctx = new ScriptEvaluationContext { ScriptVerify = flagScriptVerify }; return(ctx.VerifyScript(input.ScriptSig, output.ScriptPubKey, checker)); }
private static Script CombineMultisig(Script scriptPubKey, TransactionChecker checker, byte[][] sigs1, byte[][] sigs2, HashVersion hashVersion) { // Combine all the signatures we've got: List <TransactionSignature> allsigs = new List <TransactionSignature>(); foreach (var v in sigs1) { if (TransactionSignature.IsValid(v)) { allsigs.Add(new TransactionSignature(v)); } } foreach (var v in sigs2) { if (TransactionSignature.IsValid(v)) { allsigs.Add(new TransactionSignature(v)); } } var multiSigParams = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(scriptPubKey); if (multiSigParams == null) { throw new InvalidOperationException("The scriptPubKey is not a valid multi sig"); } Dictionary <PubKey, TransactionSignature> sigs = new Dictionary <PubKey, TransactionSignature>(); foreach (var sig in allsigs) { foreach (var pubkey in multiSigParams.PubKeys) { if (sigs.ContainsKey(pubkey)) { continue; // Already got a sig for this pubkey } ScriptEvaluationContext eval = new ScriptEvaluationContext(); if (eval.CheckSig(sig, pubkey, scriptPubKey, checker, hashVersion)) { sigs.AddOrReplace(pubkey, sig); } } } // Now build a merged CScript: int nSigsHave = 0; Script result = new Script(OpcodeType.OP_0); // pop-one-too-many workaround foreach (var pubkey in multiSigParams.PubKeys) { if (sigs.ContainsKey(pubkey)) { result += Op.GetPushOp(sigs[pubkey].ToBytes()); nSigsHave++; } if (nSigsHave >= multiSigParams.SignatureCount) { break; } } // Fill any missing with OP_0: for (int i = nSigsHave; i < multiSigParams.SignatureCount; i++) { result += OpcodeType.OP_0; } return(result); }
private void Load(ScriptEvaluationContext other) { _Stack = Clone(other._Stack); ScriptVerify = other.ScriptVerify; SigHash = other.SigHash; }