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; }
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; }
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; }
protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { return false; }
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); }
protected override bool CheckScriptPubKeyCore(Script scriptPubKey, Op[] scriptPubKeyOps) { return true; }
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); }
public Script GenerateScriptSig(Op[] ops, Script redeemScript) { var pushScript = Op.GetPushOp(redeemScript._Script); return new Script(ops.Concat(new[] { pushScript })); }
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); }
internal int FindAndDelete(Op op) { return op == null ? 0 : FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData)); }
/// <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); }
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); }
public Script GenerateScriptSig(TransactionSignature signature) { return(new Script( Op.GetPushOp(signature.ToBytes()) )); }
public Script GenerateScriptSig(Op[] ops, Script redeemScript) { var pushScript = Op.GetPushOp(redeemScript._Script); return(new Script(ops.Concat(new[] { pushScript }))); }
public TransactionSignature[] GetMultisigSignatures() { return(PayToMultiSigTemplate.Instance.ExtractScriptSigParameters(new Script(Pushes.Select(p => Op.GetPushOp(p)).ToArray()))); }
internal int FindAndDelete(Op op) { return(op == null ? 0 : FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData))); }
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; }
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; }
public int FindAndDelete(Op op) { if(op == null) return 0; return FindAndDelete(o => o.Code == op.Code && Utils.ArrayEqual(o.PushData, op.PushData)); }
protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { throw new NotImplementedException(); }
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; }
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; }
protected override bool CheckScriptSigCore(Script scriptSig, Op[] scriptSigOps, Script scriptPubKey, Op[] scriptPubKeyOps) { return scriptSig.Length == 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; }
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; }
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; }
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); }
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); }
public Script GenerateScriptSig(Op[] ops, Script script) { var pushScript = Op.GetPushOp(script._Script); return new Script(ops.Concat(new[] { pushScript }).ToArray()); }
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 }; }
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); }