Пример #1
0
        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)
                });
            }
        }
Пример #2
0
		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;
		}
Пример #3
0
        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));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
 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);
 }
Пример #8
0
        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);
        }
Пример #10
0
        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));
        }
Пример #11
0
        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);
        }
Пример #12
0
 private void Load(ScriptEvaluationContext other)
 {
     _Stack       = Clone(other._Stack);
     ScriptVerify = other.ScriptVerify;
     SigHash      = other.SigHash;
 }