Пример #1
0
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length < 1)
				return false;
			if(ops[0].Code != OpcodeType.OP_RETURN)
				return false;
			if(scriptPubKey.ToBytes(true).Length > MaxScriptSizeLimit)
				return false;
			return scriptPubKeyOps.Skip(1).All(o => o.PushData != null && !o.IsInvalid);
		}
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length < 1)
				return false;
			if(ops[0].Code != OpcodeType.OP_RETURN)
				return false;
			if(ops.Length == 2)
			{
				return ops[1].PushData != null && ops[1].PushData.Length <= MAX_OPRETURN_SIZE;
			}
			return true;
		}
Пример #3
0
		public const int MAX_OP_RETURN_RELAY = 83; //! bytes (+1 for OP_RETURN, +2 for the pushdata opcodes)
		public Script GenerateScriptPubKey(params byte[][] data)
		{
			if(data == null)
				throw new ArgumentNullException("data");
			Op[] ops = new Op[data.Length + 1];
			ops[0] = OpcodeType.OP_RETURN;
			for(int i = 0; i < data.Length; i++)
			{
				ops[1 + i] = Op.GetPushOp(data[i]);
			}
			var script = new Script(ops);
			if(script.ToBytes(true).Length > MaxScriptSizeLimit)
				throw new ArgumentOutOfRangeException("data", "Data in OP_RETURN should have a maximum size of " + MaxScriptSizeLimit + " bytes");
			return script;
		}
Пример #4
0
		public static Op GetPushOp(byte[] data)
		{
			Op op = new Op();
			op.PushData = data;
			if(data.Length == 0)
				op.Code = OpcodeType.OP_0;
			else if(data.Length == 1 && (byte)1 <= data[0] && data[0] <= (byte)16)
				op.Code = (OpcodeType)(data[0] + (byte)OpcodeType.OP_1 - 1);
			else if(data.Length == 1 && (byte)0x81 == data[0])
				op.Code = OpcodeType.OP_1NEGATE;
			else if(0x01 <= data.Length && data.Length <= 0x4b)
				op.Code = (OpcodeType)(byte)data.Length;
			else if(data.Length <= 0xFF)
				op.Code = OpcodeType.OP_PUSHDATA1;
#if !PORTABLE
			else if(data.LongLength <= 0xFFFF)
				op.Code = OpcodeType.OP_PUSHDATA2;
			else if(data.LongLength <= 0xFFFFFFFF)
				op.Code = OpcodeType.OP_PUSHDATA4;
#else
			else if(data.Length <= 0xFFFF)
				op.Code = OpcodeType.OP_PUSHDATA2;
#endif
			else
				throw new NotSupportedException("Data length should not be bigger than 0xFFFFFFFF");
			return op;
		}
Пример #5
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			return false;
		}
Пример #6
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptSigOps;
			if(ops.Length != 1)
				return false;
			return ops[0].PushData != null && TransactionSignature.IsValid(ops[0].PushData);
		}
Пример #7
0
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			return true;
		}
Пример #8
0
        internal static byte[] ReadData(Op op, Stream stream, bool ignoreWrongPush = false)
        {
            var           opcode    = op.Code;
            uint          len       = 0;
            BitcoinStream bitStream = new BitcoinStream(stream, false);

            if (opcode == 0)
            {
                return(new byte[0]);
            }

            if ((byte)OpcodeType.OP_1 <= (byte)opcode && (byte)opcode <= (byte)OpcodeType.OP_16)
            {
                return(new byte[] { (byte)(opcode - OpcodeType.OP_1 + 1) });
            }

            if (opcode == OpcodeType.OP_1NEGATE)
            {
                return(new byte[] { 0x81 });
            }

            try
            {
                if (0x01 <= (byte)opcode && (byte)opcode <= 0x4b)
                {
                    len = (uint)opcode;
                }
                else if (opcode == OpcodeType.OP_PUSHDATA1)
                {
                    len = bitStream.ReadWrite((byte)0);
                }
                else if (opcode == OpcodeType.OP_PUSHDATA2)
                {
                    len = bitStream.ReadWrite((ushort)0);
                }
                else if (opcode == OpcodeType.OP_PUSHDATA4)
                {
                    len = bitStream.ReadWrite((uint)0);
                }
                else
                {
                    throw new FormatException("Invalid opcode for pushing data : " + opcode);
                }
            }
            catch (EndOfStreamException)
            {
                if (!ignoreWrongPush)
                {
                    throw new FormatException("Incomplete script");
                }
                op.IncompleteData = true;
                return(new byte[0]);
            }

            if (stream.CanSeek && stream.Length - stream.Position < len)
            {
                len = (uint)(stream.Length - stream.Position);
                if (!ignoreWrongPush)
                {
                    throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + len);
                }
                op.IncompleteData = true;
            }
            byte[] data   = new byte[len];
            var    readen = stream.Read(data, 0, data.Length);

            if (readen != data.Length && !ignoreWrongPush)
            {
                throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + readen);
            }
            else if (readen != data.Length)
            {
                op.IncompleteData = true;
                Array.Resize(ref data, readen);
            }
            return(data);
        }
Пример #9
0
		public Script GenerateScriptSig(Op[] ops, Script redeemScript)
		{
			var pushScript = Op.GetPushOp(redeemScript._Script);
			return new Script(ops.Concat(new[] { pushScript }));
		}
Пример #10
0
		public WitScript GenerateWitScript(Op[] scriptSig, Script redeemScript)
		{
			if(redeemScript == null)
				throw new ArgumentNullException("redeemScript");
			if(scriptSig == null)
				throw new ArgumentNullException("scriptSig");

			var ops = scriptSig.Concat(new[] { Op.GetPushOp(redeemScript.ToBytes(true)) }).ToArray();
			return new WitScript(ops);
		}
Пример #11
0
		internal int FindAndDelete(Op op)
		{
			return op == null ? 0 : FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData));
		}
Пример #12
0
        /// <summary>
        /// Mines a new genesis block, to use with a new network.
        /// Typically, 3 such genesis blocks need to be created when bootstrapping a new coin: for Main, Test and Reg networks.
        /// </summary>
        /// <param name="consensusFactory">
        /// The consensus factory used to create transactions and blocks.
        /// Use <see cref="PosConsensusFactory"/> for proof-of-stake based networks.
        /// </param>
        /// <param name="coinbaseText">
        /// Traditionally a news headline from the day of the launch, but could be any string or link.
        /// This will be inserted in the input coinbase transaction script.
        /// It should be shorter than 92 characters.
        /// </param>
        /// <param name="target">
        /// The difficulty target under which the hash of the block need to be.
        /// Some more details: As an example, the target for the Stratis Main network is 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.
        /// To make it harder to mine the genesis block, have more zeros at the beginning (keeping the length the same). This will make the target smaller, so finding a number under it will be more difficult.
        /// To make it easier to mine the genesis block ,do the opposite. Example of an easy one: 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff.
        /// Make the Test and Reg targets ones easier to find than the Main one so that you don't wait too long to mine the genesis block.
        /// </param>
        /// <param name="genesisReward">
        /// Specify how many coins to put in the genesis transaction's output. These coins are unspendable.
        /// </param>
        /// <param name="version">
        /// The version of the transaction and the block header set in the genesis block.
        /// </param>
        /// <example>
        /// The following example shows the creation of a genesis block.
        /// <code>
        /// Block genesis = MineGenesisBlock(new PosConsensusFactory(), "Some topical headline.", new Target(new uint256("000fffff00000000000000000000000000000000000000000000000000000000")), Money.Coins(50m));
        /// BlockHeader header = genesis.Header;
        /// Console.WriteLine("Make a note of the following values:");
        /// Console.WriteLine("bits: " + header.Bits);
        /// Console.WriteLine("nonce: " + header.Nonce);
        /// Console.WriteLine("time: " + header.Time);
        /// Console.WriteLine("version: " + header.Version);
        /// Console.WriteLine("hash: " + header.GetHash());
        /// Console.WriteLine("merkleroot: " + header.HashMerkleRoot);
        /// </code>
        /// </example>
        /// <returns>A genesis block.</returns>
        public static Block MineGenesisBlock(ConsensusFactory consensusFactory, string coinbaseText, Target target, Money genesisReward, int version = 1)
        {
            if (consensusFactory == null)
            {
                throw new ArgumentException($"Parameter '{nameof(consensusFactory)}' cannot be null. Use 'new ConsensusFactory()' for Bitcoin-like proof-of-work blockchains and 'new PosConsensusFactory()' for Stratis-like proof-of-stake blockchains.");
            }

            if (string.IsNullOrEmpty(coinbaseText))
            {
                throw new ArgumentException($"Parameter '{nameof(coinbaseText)}' cannot be null. Use a news headline or any other appropriate string.");
            }

            if (target == null)
            {
                throw new ArgumentException($"Parameter '{nameof(target)}' cannot be null. Example use: new Target(new uint256(\"0000ffff00000000000000000000000000000000000000000000000000000000\"))");
            }

            if (coinbaseText.Length >= 92)
            {
                throw new ArgumentException($"Parameter '{nameof(coinbaseText)}' should be shorter than 92 characters.");
            }

            if (genesisReward == null)
            {
                throw new ArgumentException($"Parameter '{nameof(genesisReward)}' cannot be null. Example use: 'Money.Coins(50m)'.");
            }

            DateTimeOffset time     = DateTimeOffset.Now;
            uint           unixTime = Utils.DateTimeToUnixTime(time);

            Transaction txNew = consensusFactory.CreateTransaction();

            txNew.Version = (uint)version;
            txNew.Time    = unixTime;
            txNew.AddInput(new TxIn()
            {
                ScriptSig = new Script(
                    Op.GetPushOp(0),
                    new Op()
                {
                    Code     = (OpcodeType)0x1,
                    PushData = new[] { (byte)42 }
                },
                    Op.GetPushOp(Encoders.ASCII.DecodeData(coinbaseText)))
            });

            txNew.AddOutput(new TxOut()
            {
                Value = genesisReward,
            });

            Block genesis = consensusFactory.CreateBlock();

            genesis.Header.BlockTime = time;
            genesis.Header.Bits      = target;
            genesis.Header.Nonce     = 0;
            genesis.Header.Version   = version;
            genesis.Transactions.Add(txNew);
            genesis.Header.HashPrevBlock = uint256.Zero;
            genesis.UpdateMerkleRoot();

            // Iterate over the nonce until the proof-of-work is valid.
            // This will mean the block header hash is under the target.
            while (!genesis.CheckProofOfWork())
            {
                genesis.Header.Nonce++;
                if (genesis.Header.Nonce == 0)
                {
                    genesis.Header.Time++;
                }
            }

            return(genesis);
        }
Пример #13
0
 private static Block CreateGenesisBlock(uint nTime, uint nNonce, uint nBits, int nVersion, Money genesisReward)
 {
     string pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
     Script genesisOutputScript = new Script(Op.GetPushOp(Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f")), OpcodeType.OP_CHECKSIG);
     return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
 }
Пример #14
0
 public Script GenerateScriptSig(TransactionSignature signature)
 {
     return(new Script(
                Op.GetPushOp(signature.ToBytes())
                ));
 }
Пример #15
0
        public Script GenerateScriptSig(Op[] ops, Script redeemScript)
        {
            var pushScript = Op.GetPushOp(redeemScript._Script);

            return(new Script(ops.Concat(new[] { pushScript })));
        }
Пример #16
0
 public TransactionSignature[] GetMultisigSignatures()
 {
     return(PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(new Script(Pushes.Select(p => Op.GetPushOp(p)).ToArray())));
 }
Пример #17
0
 internal int FindAndDelete(Op op)
 {
     return(op == null ? 0 : FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData)));
 }
Пример #18
0
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length < 3)
				return false;

			var sigCount = ops[0];
			if(!sigCount.IsSmallUInt)
				return false;
			var pubKeyCount = ops[ops.Length - 2];
			if(!pubKeyCount.IsSmallUInt)
				return false;
			var keyCount = (uint)pubKeyCount.GetValue();
			if(1 + keyCount + 1 + 1 != ops.Length)
				return false;
			for(int i = 1; i < keyCount + 1; i++)
			{
				if(ops[i].PushData == null)
					return false;
			}
			return ops[ops.Length - 1].Code == OpcodeType.OP_CHECKMULTISIG;
		}
Пример #19
0
        internal static byte[] ReadData(Op op, Stream stream, bool ignoreWrongPush = false)
        {
            var opcode = op.Code;
            uint len = 0;
            BitcoinStream bitStream = new BitcoinStream(stream, false);
            if(opcode == 0)
                return new byte[0];

            if((byte)OpcodeType.OP_1 <= (byte)opcode && (byte)opcode <= (byte)OpcodeType.OP_16)
            {
                return new byte[] { (byte)(opcode - OpcodeType.OP_1 + 1) };
            }

            if(opcode == OpcodeType.OP_1NEGATE)
            {
                return new byte[] { 0x81 };
            }

            if(0x01 <= (byte)opcode && (byte)opcode <= 0x4b)
                len = (uint)opcode;
            else if(opcode == OpcodeType.OP_PUSHDATA1)
                len = bitStream.ReadWrite((byte)0);
            else if(opcode == OpcodeType.OP_PUSHDATA2)
                len = bitStream.ReadWrite((ushort)0);
            else if(opcode == OpcodeType.OP_PUSHDATA4)
                len = bitStream.ReadWrite((uint)0);
            else
                throw new FormatException("Invalid opcode for pushing data : " + opcode);

            byte[] data = new byte[len];
            var readen = stream.Read(data, 0, data.Length);
            if(readen != data.Length && !ignoreWrongPush)
                throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + readen);
            else if(readen != data.Length)
            {
                op.IncompleteData = true;
                Array.Resize(ref data, readen);
            }
            return data;
        }
Пример #20
0
 public int FindAndDelete(Op op)
 {
     if(op == null)
         return 0;
     return FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData));
 }
Пример #21
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			throw new NotImplementedException();
		}
Пример #22
0
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			if(scriptPubKeyOps.Length != 2)
				return false;
			var allPush = scriptPubKeyOps.All(o => o.PushData != null);
			if(!allPush)
				return false;
			return true;
		}
Пример #23
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			if(!scriptSig.IsPushOnly)
				return false;
			if(scriptSigOps[0].Code != OpcodeType.OP_0)
				return false;
			if(scriptSigOps.Length == 1)
				return false;
			if(!scriptSigOps.Skip(1).All(s => TransactionSignature.ValidLength(s.PushData.Length) || s.Code == OpcodeType.OP_0))
				return false;
			if(scriptPubKeyOps != null)
			{
				if(!CheckScriptPubKeyCore(scriptPubKey, scriptPubKeyOps))
					return false;
				var sigCountExpected = scriptPubKeyOps[0].GetValue();
				return sigCountExpected == scriptSigOps.Length + 1;
			}
			return true;

		}
Пример #24
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			return scriptSig.Length == 0;
		}
Пример #25
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptSigOps;
			if(ops.Length == 0)
				return false;
			if(!scriptSig.IsPushOnly)
				return false;
			if(scriptPubKey != null)
			{
				var expectedHash = ExtractScriptPubKeyParameters(scriptPubKey);
				if(expectedHash == null)
					return false;
				if(expectedHash != Script.FromBytesUnsafe(ops[ops.Length - 1].PushData).Hash)
					return false;
			}

			var redeemBytes = ops[ops.Length - 1].PushData;
			if(redeemBytes.Length > 520)
				return false;
			return Script.FromBytesUnsafe(ops[ops.Length - 1].PushData).IsValid;
		}
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length != 3)
				return false;
			return ops[0].Code == OpcodeType.OP_HASH160 &&
				   ops[1].Code == (OpcodeType)0x14 &&
				   ops[2].Code == OpcodeType.OP_EQUAL;
		}
Пример #27
0
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			return scriptPubKeyOps.Skip(1).All(o => o.PushData != null && !o.IsInvalid);
		}
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length != 2)
				return false;
			return ops[0].PushData != null && PubKey.Check(ops[0].PushData, false) &&
				   ops[1].Code == OpcodeType.OP_CHECKSIG;
		}
Пример #29
0
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptSigOps;
			if(ops.Length != 2)
				return false;
			return ops[0].PushData != null &&
				   ((ops[0].Code == OpcodeType.OP_0) || TransactionSignature.IsValid(ops[0].PushData, ScriptVerify.None)) &&
				   ops[1].PushData != null && PubKey.Check(ops[1].PushData, false);
		}
		protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptPubKeyOps;
			if(ops.Length != 5)
				return false;
			return ops[0].Code == OpcodeType.OP_DUP &&
				   ops[1].Code == OpcodeType.OP_HASH160 &&
				   ops[2].PushData != null && ops[2].PushData.Length == 0x14 &&
				   ops[3].Code == OpcodeType.OP_EQUALVERIFY &&
				   ops[4].Code == OpcodeType.OP_CHECKSIG;
		}
Пример #31
0
		protected abstract bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps);
		protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps)
		{
			var ops = scriptSigOps;
			if(ops.Length != 2)
				return false;
			return ops[0].PushData != null &&
				   ops[1].PushData != null && PubKey.Check(ops[1].PushData, false);
		}
Пример #33
0
		public WitScript GenerateWitScript(Op[] scriptSig, Script redeemScript)
		{
			if(redeemScript == null)
				throw new ArgumentNullException("redeemScript");
			if(scriptSig == null)
				throw new ArgumentNullException("scriptSig");
			return GenerateWitScript(new Script(scriptSig), redeemScript);
		}
Пример #34
0
 public Script GenerateScriptSig(Op[] ops, Script script)
 {
     var pushScript = Op.GetPushOp(script._Script);
     return new Script(ops.Concat(new[] { pushScript }).ToArray());
 }
Пример #35
0
		public Op Read()
		{
			var b = Inner.ReadByte();
			if(b == -1)
				return null;
			var opcode = (OpcodeType)b;
			if(Op.IsPushCode(opcode))
			{
				Op op = new Op();
				op.Code = opcode;
				op.PushData = op.ReadData(Inner);
				return op;
			}
			return new Op()
			{
				Code = opcode
			};
		}
Пример #36
0
        private static Script CombineMultisig(Script scriptPubKey, Transaction transaction, int n, byte[][] sigs1, byte[][] sigs2)
        {
            // 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.ToBytes(), pubkey.ToBytes(), scriptPubKey, transaction, n))
                    {
                        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);
        }