public async Task <ByteString> IssueWithdrawal(IList <OutboundTransaction> transactions)
        {
            HttpClient          client   = new HttpClient();
            BitcoinAddress      address  = storageKey.ScriptPubKey.GetDestinationAddress(this.Network);
            HttpResponseMessage response = await client.GetAsync(new Uri(url, $"addresses/{address.ToString()}/unspents"));

            string body = await response.Content.ReadAsStringAsync();

            JArray outputs = JArray.Parse(body);

            TransactionBuilder builder = new TransactionBuilder();

            builder.AddKeys(storageKey.GetBitcoinSecret(Network));
            foreach (JObject output in outputs)
            {
                string transactionHash = (string)output["transaction_hash"];
                uint   outputIndex     = (uint)output["output_index"];
                long   amount          = (long)output["value"];

                builder.AddCoins(new Coin(uint256.Parse(transactionHash), outputIndex, new Money(amount), storageKey.ScriptPubKey));
            }

            foreach (OutboundTransaction outboundTransaction in transactions)
            {
                builder.Send(BitcoinAddress.Create(outboundTransaction.Target, Network).ScriptPubKey, new Money(outboundTransaction.Amount));
            }

            builder.SendFees(defaultFees);
            builder.SetChange(storageKey.ScriptPubKey, ChangeType.All);

            NBitcoin.Transaction transaction = builder.BuildTransaction(true);

            return(new ByteString(transaction.ToBytes()));
        }
Exemplo n.º 2
0
		public static bool VerifyScriptConsensus(Script scriptPubKey, Transaction tx, uint nIn, Money amount, ScriptVerify flags, out BitcoinConsensusError err)
		{
			var scriptPubKeyBytes = scriptPubKey.ToBytes();
			var txToBytes = tx.ToBytes();
			err = BitcoinConsensusError.ERR_OK;
			var valid = VerifyScriptConsensusWithAmount(scriptPubKeyBytes, (uint)scriptPubKeyBytes.Length, amount.Satoshi, txToBytes, (uint)txToBytes.Length, nIn, flags, ref err);
			return valid == 1;
		}
Exemplo n.º 3
0
        public static bool VerifyScriptConsensus(Script scriptPubKey, Transaction tx, uint nIn, ScriptVerify flags)
        {
            var scriptPubKeyBytes = scriptPubKey.ToBytes();
            var txToBytes         = tx.ToBytes();

            var err   = BitcoinConsensusError.ERR_OK;
            var valid = VerifyScriptConsensus(scriptPubKeyBytes, (uint)scriptPubKeyBytes.Length, txToBytes, (uint)txToBytes.Length, nIn, flags, ref err);

            return(valid == 1);
        }
Exemplo n.º 4
0
        public void Serialize(BitcoinStream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException(nameof(stream));
            }
            // Write the utxo
            // If there is a non-witness utxo, then don't serialize the witness one.
            if (witness_utxo != null)
            {
                // key
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_WITNESS_UTXO;
                stream.ReadWrite(ref key);

                // value
                var data = witness_utxo.ToBytes();
                stream.ReadWriteAsVarString(ref data);
            }

            if (non_witness_utxo != null)
            {
                // key
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_NON_WITNESS_UTXO;
                stream.ReadWrite(ref key);
                // value
                byte[] data = non_witness_utxo.ToBytes();
                stream.ReadWriteAsVarString(ref data);
            }

            // Write the sighash type
            if (sighash_type > 0)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SIGHASH;
                stream.ReadWrite(ref key);
                var tmp = Utils.ToBytes((uint)sighash_type, true);
                stream.ReadWriteAsVarString(ref tmp);
            }

            // Write the redeem script
            if (redeem_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_REDEEMSCRIPT;
                stream.ReadWrite(ref key);
                var value = redeem_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // Write the witness script
            if (witness_script != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_WITNESSSCRIPT;
                stream.ReadWrite(ref key);
                var value = witness_script.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // Write any partial signatures
            foreach (var sig_pair in partial_sigs)
            {
                var key = new byte[] { PSBTConstants.PSBT_IN_PARTIAL_SIG }.Concat(sig_pair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                var sig = sig_pair.Value.ToBytes();
                stream.ReadWriteAsVarString(ref sig);
            }

            // Write any hd keypaths
            foreach (var pathPair in hd_keypaths)
            {
                var key = new byte[] { PSBTConstants.PSBT_IN_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes());
                stream.ReadWriteAsVarString(ref key);
                var masterFingerPrint = pathPair.Value.MasterFingerprint;
                var path              = pathPair.Value.KeyPath.ToBytes();
                var pathInfo          = masterFingerPrint.ToBytes().Concat(path);
                stream.ReadWriteAsVarString(ref pathInfo);
            }

            // Write script sig
            if (final_script_sig != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SCRIPTSIG;
                stream.ReadWrite(ref key);
                byte[] value = final_script_sig.ToBytes();
                stream.ReadWriteAsVarString(ref value);
            }

            // write script witness
            if (final_script_witness != null)
            {
                stream.ReadWriteAsVarInt(ref defaultKeyLen);
                var key = PSBTConstants.PSBT_IN_SCRIPTWITNESS;
                stream.ReadWrite(ref key);
                var stack = final_script_witness.ToBytes();
                stream.ReadWriteAsVarString(ref stack);
            }

            // Write unknown things
            foreach (var entry in unknown)
            {
                var k = entry.Key;
                var v = entry.Value;
                stream.ReadWriteAsVarString(ref k);
                stream.ReadWriteAsVarString(ref v);
            }

            var sep = PSBTConstants.PSBT_SEPARATOR;

            stream.ReadWrite(ref sep);
        }
Exemplo n.º 5
0
		//struct GetRejectReason()  { return strRejectReason; }

		public bool CheckTransaction(Transaction tx)
		{
			// Basic checks that don't depend on any context
			if(tx.Inputs.Count == 0)
				return DoS(10, Utils.error("CheckTransaction() : vin empty"),
								 RejectCode.INVALID, "bad-txns-vin-empty");
			if(tx.Outputs.Count == 0)
				return DoS(10, Utils.error("CheckTransaction() : vout empty"),
								 RejectCode.INVALID, "bad-txns-vout-empty");
			// Size limits
			if(tx.ToBytes().Length > MAX_BLOCK_SIZE)
				return DoS(100, Utils.error("CheckTransaction() : size limits failed"),
								 RejectCode.INVALID, "bad-txns-oversize");

			// Check for negative or overflow output values
			long nValueOut = 0;
			foreach(var txout in tx.Outputs)
			{
				if(txout.Value < 0)
					return DoS(100, Utils.error("CheckTransaction() : txout.nValue negative"),
									 RejectCode.INVALID, "bad-txns-vout-negative");
				if(txout.Value > MAX_MONEY)
					return DoS(100, Utils.error("CheckTransaction() : txout.nValue too high"),
									 RejectCode.INVALID, "bad-txns-vout-toolarge");
				nValueOut += (long)txout.Value;
				if(!((nValueOut >= 0 && nValueOut <= (long)MAX_MONEY)))
					return DoS(100, Utils.error("CheckTransaction() : txout total out of range"),
									 RejectCode.INVALID, "bad-txns-txouttotal-toolarge");
			}

			// Check for duplicate inputs
			HashSet<OutPoint> vInOutPoints = new HashSet<OutPoint>();
			foreach(var txin in tx.Inputs)
			{
				if(vInOutPoints.Contains(txin.PrevOut))
					return DoS(100, Utils.error("CheckTransaction() : duplicate inputs"),
									 RejectCode.INVALID, "bad-txns-inputs-duplicate");
				vInOutPoints.Add(txin.PrevOut);
			}

			if(tx.IsCoinBase)
			{
				if(tx.Inputs[0].ScriptSig.Length < 2 || tx.Inputs[0].ScriptSig.Length > 100)
					return DoS(100, Utils.error("CheckTransaction() : coinbase script size"),
									 RejectCode.INVALID, "bad-cb-length");
			}
			else
			{
				foreach(var txin in tx.Inputs)
					if(txin.PrevOut.IsNull)
						return DoS(10, Utils.error("CheckTransaction() : prevout is null"),
										 RejectCode.INVALID, "bad-txns-prevout-null");
			}

			return true;
		}
Exemplo n.º 6
0
		public static bool VerifyScriptConsensus(Script scriptPubKey, Transaction tx, uint nIn, ScriptVerify flags)
		{
			var scriptPubKeyBytes = scriptPubKey.ToBytes();
			var txToBytes = tx.ToBytes();

			var err = BitcoinConsensusError.ERR_OK;
			var valid = VerifyScriptConsensus(scriptPubKeyBytes, (uint)scriptPubKeyBytes.Length, txToBytes, (uint)txToBytes.Length, nIn, flags, ref err);
			return valid == 1;
		}
Exemplo n.º 7
0
		//https://en.bitcoin.it/wiki/OP_CHECKSIG
		public uint256 SignatureHash(Transaction txTo, int nIn, SigHash nHashType)
		{
			if(nIn >= txTo.Inputs.Count)
			{
				Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n");
				return uint256.One;
			}

			// Check for invalid use of SIGHASH_SINGLE
			if(nHashType == SigHash.Single)
			{
				if(nIn >= txTo.Outputs.Count)
				{
					Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n");
					return uint256.One;
				}
			}

			var scriptCopy = new Script(_Script);
			scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR);

			var txCopy = new Transaction(txTo.ToBytes());

			//Set all TxIn script to empty string
			foreach(var txin in txCopy.Inputs)
			{
				txin.ScriptSig = new Script();
			}
			//Copy subscript into the txin script you are checking
			txCopy.Inputs[nIn].ScriptSig = scriptCopy;

			var hashType = nHashType & (SigHash)31;
			if(hashType == SigHash.None)
			{
				//The output of txCopy is set to a vector of zero size.
				txCopy.Outputs.Clear();

				//All other inputs aside from the current input in txCopy have their nSequence index set to zero
				foreach(var input in txCopy.Inputs.Where((x, i) => i != nIn))
					input.Sequence = 0;
			}
			else if(hashType == SigHash.Single)
			{
				//The output of txCopy is resized to the size of the current input index+1.
				txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1));
				//All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1.
				for(var i = 0 ; i < txCopy.Outputs.Count ; i++)
				{
					if(i == nIn)
						continue;
					txCopy.Outputs[i] = new TxOut();
				}
				//All other txCopy inputs aside from the current input are set to have an nSequence index of zero.
				foreach(var input in txCopy.Inputs.Where((x, i) => i != nIn))
					input.Sequence = 0;
			}


			if((nHashType & SigHash.AnyoneCanPay) != 0)
			{
				//The txCopy input vector is resized to a length of one.
				var script = txCopy.Inputs[nIn];
				txCopy.Inputs.Clear();
				txCopy.Inputs.Add(script);
				//The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector.
				txCopy.Inputs[0].ScriptSig = scriptCopy;
			}


			//Serialize TxCopy, append 4 byte hashtypecode
			var ms = new MemoryStream();
			var bitcoinStream = new BitcoinStream(ms, true);
			txCopy.ReadWrite(bitcoinStream);
			bitcoinStream.ReadWrite((uint)nHashType);

			var hashed = ms.ToArray();
			return Hashes.Hash256(hashed);
		}
Exemplo n.º 8
0
        //https://en.bitcoin.it/wiki/OP_CHECKSIG
        public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
        {
            if (sigversion == HashVersion.Witness)
            {
                if (amount == null)
                {
                    throw new ArgumentException("The amount of the output being signed must be provided", "amount");
                }
                uint256 hashPrevouts = uint256.Zero;
                uint256 hashSequence = uint256.Zero;
                uint256 hashOutputs  = uint256.Zero;

                if ((nHashType & SigHash.AnyoneCanPay) == 0)
                {
                    hashPrevouts = precomputedTransactionData == null?
                                   GetHashPrevouts(txTo) : precomputedTransactionData.HashPrevouts;
                }

                if ((nHashType & SigHash.AnyoneCanPay) == 0 && ((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None)
                {
                    hashSequence = precomputedTransactionData == null?
                                   GetHashSequence(txTo) : precomputedTransactionData.HashSequence;
                }

                if (((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None)
                {
                    hashOutputs = precomputedTransactionData == null?
                                  GetHashOutputs(txTo) : precomputedTransactionData.HashOutputs;
                }
                else if (((uint)nHashType & 0x1f) == (uint)SigHash.Single && nIn < txTo.Outputs.Count)
                {
                    BitcoinStream ss = CreateHashWriter(sigversion);
                    ss.ReadWrite(txTo.Outputs[nIn]);
                    hashOutputs = GetHash(ss);
                }

                BitcoinStream sss = CreateHashWriter(sigversion);
                // Version
                sss.ReadWrite(txTo.Version);
                // Input prevouts/nSequence (none/all, depending on flags)
                sss.ReadWrite(hashPrevouts);
                sss.ReadWrite(hashSequence);
                // The input being signed (replacing the scriptSig with scriptCode + amount)
                // The prevout may already be contained in hashPrevout, and the nSequence
                // may already be contain in hashSequence.
                sss.ReadWrite(txTo.Inputs[nIn].PrevOut);
                sss.ReadWrite(scriptCode);
                sss.ReadWrite(amount.Satoshi);
                sss.ReadWrite((uint)txTo.Inputs[nIn].Sequence);
                // Outputs (none/one/all, depending on flags)
                sss.ReadWrite(hashOutputs);
                // Locktime
                sss.ReadWriteStruct(txTo.LockTime);
                // Sighash type
                sss.ReadWrite((uint)nHashType);

                return(GetHash(sss));
            }



            if (nIn >= txTo.Inputs.Count)
            {
                Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n");
                return(uint256.One);
            }

            // Check for invalid use of SIGHASH_SINGLE
            if (nHashType == SigHash.Single)
            {
                if (nIn >= txTo.Outputs.Count)
                {
                    Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n");
                    return(uint256.One);
                }
            }

            var scriptCopy = new Script(scriptCode._Script);

            scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR);

            var txCopy = new Transaction(txTo.ToBytes());

            //Set all TxIn script to empty string
            foreach (var txin in txCopy.Inputs)
            {
                txin.ScriptSig = new Script();
            }
            //Copy subscript into the txin script you are checking
            txCopy.Inputs[nIn].ScriptSig = scriptCopy;

            var hashType = nHashType & (SigHash)31;

            if (hashType == SigHash.None)
            {
                //The output of txCopy is set to a vector of zero size.
                txCopy.Outputs.Clear();

                //All other inputs aside from the current input in txCopy have their nSequence index set to zero
                foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn))
                {
                    input.Sequence = 0;
                }
            }
            else if (hashType == SigHash.Single)
            {
                //The output of txCopy is resized to the size of the current input index+1.
                txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1));
                //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1.
                for (var i = 0; i < txCopy.Outputs.Count; i++)
                {
                    if (i == nIn)
                    {
                        continue;
                    }
                    txCopy.Outputs[i] = new TxOut();
                }
                //All other txCopy inputs aside from the current input are set to have an nSequence index of zero.
                foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn))
                {
                    input.Sequence = 0;
                }
            }


            if ((nHashType & SigHash.AnyoneCanPay) != 0)
            {
                //The txCopy input vector is resized to a length of one.
                var script = txCopy.Inputs[nIn];
                txCopy.Inputs.Clear();
                txCopy.Inputs.Add(script);
                //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector.
                txCopy.Inputs[0].ScriptSig = scriptCopy;
            }


            //Serialize TxCopy, append 4 byte hashtypecode
            var stream = CreateHashWriter(sigversion);

            txCopy.ReadWrite(stream);
            stream.ReadWrite((uint)nHashType);
            return(GetHash(stream));
        }
Exemplo n.º 9
0
        //https://en.bitcoin.it/wiki/OP_CHECKSIG
        public uint256 SignatureHash(Transaction txTo, int nIn, SigHash nHashType)
        {
            if (nIn >= txTo.Inputs.Count)
            {
                Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n");
                return(1);
            }

            // Check for invalid use of SIGHASH_SINGLE
            if (nHashType == SigHash.Single)
            {
                if (nIn >= txTo.Outputs.Count)
                {
                    Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n");
                    return(1);
                }
            }

            var scriptCopy = new Script(_Script);

            scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR);

            var txCopy = new Transaction(txTo.ToBytes());

            //Set all TxIn script to empty string
            foreach (var txin in txCopy.Inputs)
            {
                txin.ScriptSig = new Script();
            }
            //Copy subscript into the txin script you are checking
            txCopy.Inputs[nIn].ScriptSig = scriptCopy;

            if (((int)nHashType & 31) == (int)SigHash.None)
            {
                //The output of txCopy is set to a vector of zero size.
                txCopy.Outputs.Clear();
                //All other inputs aside from the current input in txCopy have their nSequence index set to zero
                for (int i = 0; i < txCopy.Inputs.Count; i++)
                {
                    if (i == nIn)
                    {
                        continue;
                    }
                    txCopy.Inputs[i].Sequence = 0;
                }
            }

            if (((int)nHashType & 31) == (int)SigHash.Single)
            {
                //The output of txCopy is resized to the size of the current input index+1.
                var remainingOut = txCopy.Outputs.Take(nIn + 1).ToArray();
                txCopy.Outputs.Clear();
                txCopy.Outputs.AddRange(remainingOut);
                //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1.
                for (int i = 0; i < txCopy.Outputs.Count; i++)
                {
                    if (i == nIn)
                    {
                        continue;
                    }
                    txCopy.Outputs[i] = new TxOut();
                }
                for (int i = 0; i < txCopy.Inputs.Count; i++)
                {
                    //All other txCopy inputs aside from the current input are set to have an nSequence index of zero.
                    if (i == nIn)
                    {
                        continue;
                    }
                    txCopy.Inputs[i].Sequence = 0;
                }
            }

            if (((int)nHashType & (int)SigHash.AnyoneCanPay) != 0)
            {
                //The txCopy input vector is resized to a length of one.
                var script = txCopy.Inputs[nIn];
                txCopy.Inputs.Clear();
                txCopy.Inputs.Add(script);
                //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector.
                txCopy.Inputs[0].ScriptSig = scriptCopy;
            }


            //Serialize TxCopy, append 4 byte hashtypecode
            MemoryStream  ms            = new MemoryStream();
            BitcoinStream bitcoinStream = new BitcoinStream(ms, true);

            txCopy.ReadWrite(bitcoinStream);
            bitcoinStream.ReadWrite((uint)nHashType);

            var hashed = ms.ToArray();

            return(Hashes.Hash256(hashed));
        }
Exemplo n.º 10
0
		//https://en.bitcoin.it/wiki/OP_CHECKSIG
		public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount = null, HashVersion sigversion = HashVersion.Original)
		{
			if(sigversion == HashVersion.Witness)
			{
				if(amount == null)
					throw new ArgumentException("The amount of the output being signed must be provided", "amount");
				uint256 hashPrevouts = uint256.Zero;
				uint256 hashSequence = uint256.Zero;
				uint256 hashOutputs = uint256.Zero;

				if((nHashType & SigHash.AnyoneCanPay) == 0)
				{
					BitcoinStream ss = CreateHashWriter(sigversion);
					foreach(var input in txTo.Inputs)
					{
						ss.ReadWrite(input.PrevOut);
					}
					hashPrevouts = GetHash(ss); // TODO: cache this value for all signatures in a transaction
				}

				if((nHashType & SigHash.AnyoneCanPay) == 0 && ((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None)
				{
					BitcoinStream ss = CreateHashWriter(sigversion);
					foreach(var input in txTo.Inputs)
					{
						ss.ReadWrite((uint)input.Sequence);
					}
					hashSequence = GetHash(ss); // TODO: cache this value for all signatures in a transaction
				}

				if(((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None)
				{
					BitcoinStream ss = CreateHashWriter(sigversion);
					foreach(var txout in txTo.Outputs)
					{
						ss.ReadWrite(txout);
					}
					hashOutputs = GetHash(ss); // TODO: cache this value for all signatures in a transaction
				}
				else if(((uint)nHashType & 0x1f) == (uint)SigHash.Single && nIn < txTo.Outputs.Count)
				{
					BitcoinStream ss = CreateHashWriter(sigversion);
					ss.ReadWrite(txTo.Outputs[nIn]);
					hashOutputs = GetHash(ss);
				}

				BitcoinStream sss = CreateHashWriter(sigversion);
				// Version
				sss.ReadWrite(txTo.Version);
				// Input prevouts/nSequence (none/all, depending on flags)
				sss.ReadWrite(hashPrevouts);
				sss.ReadWrite(hashSequence);
				// The input being signed (replacing the scriptSig with scriptCode + amount)
				// The prevout may already be contained in hashPrevout, and the nSequence
				// may already be contain in hashSequence.
				sss.ReadWrite(txTo.Inputs[nIn].PrevOut);
				sss.ReadWrite(scriptCode);
				sss.ReadWrite(amount.Satoshi);
				sss.ReadWrite((uint)txTo.Inputs[nIn].Sequence);
				// Outputs (none/one/all, depending on flags)
				sss.ReadWrite(hashOutputs);
				// Locktime
				sss.ReadWriteStruct(txTo.LockTime);
				// Sighash type
				sss.ReadWrite((uint)nHashType);

				return GetHash(sss);
			}




			if(nIn >= txTo.Inputs.Count)
			{
				Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n");
				return uint256.One;
			}

			// Check for invalid use of SIGHASH_SINGLE
			if(nHashType == SigHash.Single)
			{
				if(nIn >= txTo.Outputs.Count)
				{
					Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n");
					return uint256.One;
				}
			}

			var scriptCopy = new Script(scriptCode._Script);
			scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR);

			var txCopy = new Transaction(txTo.ToBytes());

			//Set all TxIn script to empty string
			foreach(var txin in txCopy.Inputs)
			{
				txin.ScriptSig = new Script();
			}
			//Copy subscript into the txin script you are checking
			txCopy.Inputs[nIn].ScriptSig = scriptCopy;

			var hashType = nHashType & (SigHash)31;
			if(hashType == SigHash.None)
			{
				//The output of txCopy is set to a vector of zero size.
				txCopy.Outputs.Clear();

				//All other inputs aside from the current input in txCopy have their nSequence index set to zero
				foreach(var input in txCopy.Inputs.Where((x, i) => i != nIn))
					input.Sequence = 0;
			}
			else if(hashType == SigHash.Single)
			{
				//The output of txCopy is resized to the size of the current input index+1.
				txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1));
				//All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1.
				for(var i = 0 ; i < txCopy.Outputs.Count ; i++)
				{
					if(i == nIn)
						continue;
					txCopy.Outputs[i] = new TxOut();
				}
				//All other txCopy inputs aside from the current input are set to have an nSequence index of zero.
				foreach(var input in txCopy.Inputs.Where((x, i) => i != nIn))
					input.Sequence = 0;
			}


			if((nHashType & SigHash.AnyoneCanPay) != 0)
			{
				//The txCopy input vector is resized to a length of one.
				var script = txCopy.Inputs[nIn];
				txCopy.Inputs.Clear();
				txCopy.Inputs.Add(script);
				//The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector.
				txCopy.Inputs[0].ScriptSig = scriptCopy;
			}


			//Serialize TxCopy, append 4 byte hashtypecode
			var stream = CreateHashWriter(sigversion);
			txCopy.ReadWrite(stream);
			stream.ReadWrite((uint)nHashType);
			return GetHash(stream);
		}
Exemplo n.º 11
0
        //struct GetRejectReason()  { return strRejectReason; }

        public bool CheckTransaction(Transaction tx)
        {
            // Basic checks that don't depend on any context
            if (tx.Inputs.Count == 0)
            {
                return(DoS(10, Utils.error("CheckTransaction() : vin empty"),
                           RejectCode.INVALID, "bad-txns-vin-empty"));
            }
            if (tx.Outputs.Count == 0)
            {
                return(DoS(10, Utils.error("CheckTransaction() : vout empty"),
                           RejectCode.INVALID, "bad-txns-vout-empty"));
            }
            // Size limits
            if (tx.ToBytes().Length > MAX_BLOCK_SIZE)
            {
                return(DoS(100, Utils.error("CheckTransaction() : size limits failed"),
                           RejectCode.INVALID, "bad-txns-oversize"));
            }

            // Check for negative or overflow output values
            long nValueOut = 0;

            foreach (var txout in tx.Outputs)
            {
                if (txout.Value < 0)
                {
                    return(DoS(100, Utils.error("CheckTransaction() : txout.nValue negative"),
                               RejectCode.INVALID, "bad-txns-vout-negative"));
                }
                if (txout.Value > MAX_MONEY)
                {
                    return(DoS(100, Utils.error("CheckTransaction() : txout.nValue too high"),
                               RejectCode.INVALID, "bad-txns-vout-toolarge"));
                }
                nValueOut += (long)txout.Value;
                if (!((nValueOut >= 0 && nValueOut <= (long)MAX_MONEY)))
                {
                    return(DoS(100, Utils.error("CheckTransaction() : txout total out of range"),
                               RejectCode.INVALID, "bad-txns-txouttotal-toolarge"));
                }
            }

            // Check for duplicate inputs
            HashSet <OutPoint> vInOutPoints = new HashSet <OutPoint>();

            foreach (var txin in tx.Inputs)
            {
                if (vInOutPoints.Contains(txin.PrevOut))
                {
                    return(DoS(100, Utils.error("CheckTransaction() : duplicate inputs"),
                               RejectCode.INVALID, "bad-txns-inputs-duplicate"));
                }
                vInOutPoints.Add(txin.PrevOut);
            }

            if (tx.IsCoinBase)
            {
                if (tx.Inputs[0].ScriptSig.Length < 2 || tx.Inputs[0].ScriptSig.Length > 100)
                {
                    return(DoS(100, Utils.error("CheckTransaction() : coinbase script size"),
                               RejectCode.INVALID, "bad-cb-length"));
                }
            }
            else
            {
                foreach (var txin in tx.Inputs)
                {
                    if (txin.PrevOut.IsNull)
                    {
                        return(DoS(10, Utils.error("CheckTransaction() : prevout is null"),
                                   RejectCode.INVALID, "bad-txns-prevout-null"));
                    }
                }
            }

            return(true);
        }