Exemple #1
0
        static uint256 GetHashToSign(Transaction tx, int index, Script scriptCode, long amount)
        {
            const SigHash sigHash = SigHash.All;

            uint256 hashPrevouts = GetHashPrevouts(tx);
            uint256 hashSequence = GetHashSequence(tx);
            uint256 hashOutputs  = GetHashOutputs(tx);

            BitcoinStream stream = CreateHashWriter(HashVersion.Witness);

            stream.ReadWrite(tx.Version);
            // Input prevouts/nSequence (none/all, depending on flags)
            stream.ReadWrite(hashPrevouts);
            stream.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.
            stream.ReadWrite(tx.Inputs[index].PrevOut);
            stream.ReadWrite(scriptCode);
            stream.ReadWrite(amount);
            // ReSharper disable once RedundantCast
            stream.ReadWrite((uint)tx.Inputs[index].Sequence);
            // Outputs (none/one/all, depending on flags)
            stream.ReadWrite(hashOutputs);
            // Locktime
            stream.ReadWriteStruct(tx.LockTime);
            // Sighash type
            stream.ReadWrite((uint)sigHash);

            return(GetHash(stream));
        }
Exemple #2
0
            private void SerializeTxn(BitcoinStream stream)
            {
                var version = this.Version;

                stream.ReadWrite(ref version);

                // POS Timestamp
                var time = this.Time;

                stream.ReadWrite(ref time);

                TxInList vin = this.Inputs;

                stream.ReadWrite(ref vin);
                vin.Transaction = this;

                TxOutList vout = this.Outputs;

                stream.ReadWrite(ref vout);
                vout.Transaction = this;

                LockTime lockTime = this.LockTime;

                stream.ReadWriteStruct(ref lockTime);
            }
Exemple #3
0
            private void DeserializeTxn(BitcoinStream stream)
            {
                UInt32 nVersionTemp = 0;

                stream.ReadWrite(ref nVersionTemp);

                // POS time stamp
                UInt32 nTimeTemp = 0;

                stream.ReadWrite(ref nTimeTemp);

                TxInList  vinTemp  = null;
                TxOutList voutTemp = null;

                // Try to read the vin.
                stream.ReadWrite(ref vinTemp);
                vinTemp.Transaction = this;
                // Assume a normal vout follows.
                stream.ReadWrite(ref voutTemp);
                voutTemp.Transaction = this;

                LockTime lockTimeTemp = LockTime.Zero;

                stream.ReadWriteStruct(ref lockTimeTemp);

                this.Version = nVersionTemp;
                this.Time    = nTimeTemp;              // POS Timestamp
                vinTemp.ForEach(i => this.Inputs.Add(i));
                voutTemp.ForEach(i => this.Outputs.Add(i));
                this.LockTime = lockTimeTemp;
            }
Exemple #4
0
            private void SerializeTxn(BitcoinStream stream, bool witSupported)
            {
                byte flags   = 0;
                var  version = (witSupported && (this.Inputs.Count == 0 && this.Outputs.Count > 0)) ? this.Version | NoDummyInput : this.Version;

                stream.ReadWrite(ref version);

                // POS Timestamp
                var time = this.Time;

                stream.ReadWrite(ref time);

                if (witSupported)
                {
                    // Check whether witnesses need to be serialized.
                    if (HasWitness)
                    {
                        flags |= 1;
                    }
                }
                if (flags != 0)
                {
                    // Use extended format in case witnesses are to be serialized.
                    TxInList vinDummy = new TxInList();
                    stream.ReadWrite <TxInList, TxIn>(ref vinDummy);
                    stream.ReadWrite(ref flags);
                }
                TxInList vin = this.Inputs;

                stream.ReadWrite <TxInList, TxIn>(ref vin);
                vin.Transaction = this;
                TxOutList vout = this.Outputs;

                stream.ReadWrite <TxOutList, TxOut>(ref vout);
                vout.Transaction = this;
                if ((flags & 1) != 0)
                {
                    StratisWitness wit = new StratisWitness(this.Inputs);
                    wit.ReadWrite(stream);
                }
                LockTime lockTime = this.LockTime;

                stream.ReadWriteStruct(ref lockTime);
            }
Exemple #5
0
            public override void ReadWrite(BitcoinStream stream)
            {
                stream.ReadWrite(ref nVersion);
                stream.ReadWriteStruct(ref nLockTime);

                stream.ReadWrite <TxInList, TxIn>(ref vin);
                vin.Transaction = this;

                stream.ReadWrite <TxOutList, TxOut>(ref vout);
                vout.Transaction = this;

                if (stream.Type != SerializationType.Hash)
                {
                    Witness wit = new Witness(Inputs);
                    try
                    {
                        wit.ReadWrite(stream);
                    } catch (FormatException e) {
                        Console.Out.WriteLine(e.Message);
                    }
                }
            }
        public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, TxOut spentOutput, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
        {
            uint nForkHashType = (uint)nHashType;

            if (UsesForkId(nHashType))
            {
                nForkHashType |= ForkId << 8;
            }

            if ((SupportSegwit && sigversion == HashVersion.Witness) || UsesForkId(nHashType))
            {
                if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
                {
                    throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
                }
                uint256 hashPrevouts = uint256.Zero;
                uint256 hashSequence = uint256.Zero;
                uint256 hashOutputs  = uint256.Zero;

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

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

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

                BitcoinStream sss = CreateHashWriter(sigversion);
                // Version
                sss.ReadWrite(this.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(Inputs[nIn].PrevOut);
                sss.ReadWrite(scriptCode);
                sss.ReadWrite(spentOutput.Value.Satoshi);
                sss.ReadWrite((uint)Inputs[nIn].Sequence);
                // Outputs (none/one/all, depending on flags)
                sss.ReadWrite(hashOutputs);
                // Locktime
                sss.ReadWriteStruct(LockTime);
                // Sighash type
                sss.ReadWrite((uint)nForkHashType);

                return(GetHash(sss));
            }



            if (nIn >= Inputs.Count)
            {
                return(uint256.One);
            }

            var hashType = nHashType & (SigHash)31;

            // Check for invalid use of SIGHASH_SINGLE
            if (hashType == SigHash.Single)
            {
                if (nIn >= Outputs.Count)
                {
                    return(uint256.One);
                }
            }

            var scriptCopy = scriptCode.Clone();

            scriptCode = scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR);

            var txCopy = GetConsensusFactory().CreateTransaction();

            txCopy.FromBytes(this.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 (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)nForkHashType);
            return(GetHash(stream));
        }
Exemple #7
0
            private void DeserializeTxn(BitcoinStream stream, bool witSupported)
            {
                byte flags = 0;

                UInt32 nVersionTemp = 0;

                stream.ReadWrite(ref nVersionTemp);

                // POS time stamp
                uint nTimeTemp = 0;

                stream.ReadWrite(ref nTimeTemp);

                TxInList  vinTemp  = new TxInList();
                TxOutList voutTemp = new TxOutList();

                // Try to read the vin. In case the dummy is there, this will be read as an empty vector.
                stream.ReadWrite <TxInList, TxIn>(ref vinTemp);

                var hasNoDummy = (nVersionTemp & NoDummyInput) != 0 && vinTemp.Count == 0;

                if (witSupported && hasNoDummy)
                {
                    nVersionTemp = nVersionTemp & ~NoDummyInput;
                }

                if (vinTemp.Count == 0 && witSupported && !hasNoDummy)
                {
                    // We read a dummy or an empty vin.
                    stream.ReadWrite(ref flags);
                    if (flags != 0)
                    {
                        // Assume we read a dummy and a flag.
                        stream.ReadWrite <TxInList, TxIn>(ref vinTemp);
                        vinTemp.Transaction = this;
                        stream.ReadWrite <TxOutList, TxOut>(ref voutTemp);
                        voutTemp.Transaction = this;
                    }
                    else
                    {
                        // Assume read a transaction without output.
                        voutTemp             = new TxOutList();
                        voutTemp.Transaction = this;
                    }
                }
                else
                {
                    // We read a non-empty vin. Assume a normal vout follows.
                    stream.ReadWrite <TxOutList, TxOut>(ref voutTemp);
                    voutTemp.Transaction = this;
                }
                if (((flags & 1) != 0) && witSupported)
                {
                    // The witness flag is present, and we support witnesses.
                    flags ^= 1;
                    StratisWitness wit = new StratisWitness(vinTemp);
                    wit.ReadWrite(stream);
                }
                if (flags != 0)
                {
                    // Unknown flag in the serialization
                    throw new FormatException("Unknown transaction optional data");
                }
                LockTime lockTimeTemp = LockTime.Zero;

                stream.ReadWriteStruct(ref lockTimeTemp);

                this.Version = nVersionTemp;
                this.Time    = nTimeTemp; // POS Timestamp
                vinTemp.ForEach(i => this.AddInput(i));
                voutTemp.ForEach(i => this.AddOutput(i));
                this.LockTime = lockTimeTemp;
            }
Exemple #8
0
            public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, TxOut spentOutput, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData)
            {
                if (sigversion == HashVersion.WitnessV0)
                {
                    if (spentOutput?.Value == null || spentOutput.Value == TxOut.NullMoney)
                    {
                        throw new ArgumentException("The output being signed with the amount must be provided", nameof(spentOutput));
                    }
                    uint256 hashPrevouts = uint256.Zero;
                    uint256 hashSequence = uint256.Zero;
                    uint256 hashOutputs  = uint256.Zero;

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

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

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

                    BitcoinStream sss = CreateHashWriter(sigversion);
                    // Version
                    sss.ReadWrite(this.Version);
                    // PoS Time
                    sss.ReadWrite(this.Time);
                    // 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(Inputs[nIn].PrevOut);
                    sss.ReadWrite(scriptCode);
                    sss.ReadWrite(spentOutput.Value.Satoshi);
                    sss.ReadWrite(Inputs[nIn].Sequence);
                    // Outputs (none/one/all, depending on flags)
                    sss.ReadWrite(hashOutputs);
                    // Locktime
                    sss.ReadWriteStruct(LockTime);
                    // Sighash type
                    sss.ReadWrite((uint)nHashType);

                    return(GetHash(sss));
                }

                bool fAnyoneCanPay = (nHashType & SigHash.AnyoneCanPay) != 0;
                bool fHashSingle   = ((byte)nHashType & 0x1f) == (byte)SigHash.Single;
                bool fHashNone     = ((byte)nHashType & 0x1f) == (byte)SigHash.None;

                if (nIn >= Inputs.Count)
                {
                    return(uint256.One);
                }
                if (fHashSingle)
                {
                    if (nIn >= Outputs.Count)
                    {
                        return(uint256.One);
                    }
                }

                var stream = CreateHashWriter(sigversion);

                stream.ReadWrite(Version);
                stream.ReadWrite(Time);
                uint nInputs = (uint)(fAnyoneCanPay ? 1 : Inputs.Count);

                stream.ReadWriteAsVarInt(ref nInputs);
                for (int nInput = 0; nInput < nInputs; nInput++)
                {
                    if (fAnyoneCanPay)
                    {
                        nInput = nIn;
                    }
                    stream.ReadWrite(Inputs[nInput].PrevOut);
                    if (nInput != nIn)
                    {
                        stream.ReadWrite(Script.Empty);
                    }
                    else
                    {
                        WriteScriptCode(stream, scriptCode);
                    }

                    if (nInput != nIn && (fHashSingle || fHashNone))
                    {
                        stream.ReadWrite((uint)0);
                    }
                    else
                    {
                        stream.ReadWrite(Inputs[nInput].Sequence);
                    }
                }

                uint nOutputs = (uint)(fHashNone ? 0 : (fHashSingle ? nIn + 1 : Outputs.Count));

                stream.ReadWriteAsVarInt(ref nOutputs);
                for (int nOutput = 0; nOutput < nOutputs; nOutput++)
                {
                    if (fHashSingle && nOutput != nIn)
                    {
                        this.Outputs.CreateNewTxOut().ReadWrite(stream);
                    }
                    else
                    {
                        Outputs[nOutput].ReadWrite(stream);
                    }
                }

                stream.ReadWriteStruct(LockTime);
                stream.ReadWrite((uint)nHashType);
                return(GetHash(stream));
            }
Exemple #9
0
        public override void ReadWrite(BitcoinStream stream)
        {
            bool witSupported = (((uint)stream.TransactionOptions & (uint)TransactionOptions.Witness) != 0) &&
                                stream.ProtocolVersion >= ProtocolVersion.WITNESS_VERSION;

            byte flags = 0;

            if (!stream.Serializing)
            {
                stream.ReadWrite(ref this.nVersion);

                // POS time stamp
                stream.ReadWrite(ref this.nTime);

                /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */
                stream.ReadWrite <TxInList, TxIn>(ref this.vin);

                bool hasNoDummy = (this.nVersion & NoDummyInput) != 0 && this.vin.Count == 0;
                if (witSupported && hasNoDummy)
                {
                    this.nVersion = this.nVersion & ~NoDummyInput;
                }

                if (this.vin.Count == 0 && witSupported && !hasNoDummy)
                {
                    /* We read a dummy or an empty vin. */
                    stream.ReadWrite(ref flags);
                    if (flags != 0)
                    {
                        /* Assume we read a dummy and a flag. */
                        stream.ReadWrite <TxInList, TxIn>(ref this.vin);
                        this.vin.Transaction = this;
                        stream.ReadWrite <TxOutList, TxOut>(ref this.vout);
                        this.vout.Transaction = this;
                    }
                    else
                    {
                        /* Assume read a transaction without output. */
                        this.vout             = new TxOutList();
                        this.vout.Transaction = this;
                    }
                }
                else
                {
                    /* We read a non-empty vin. Assume a normal vout follows. */
                    stream.ReadWrite <TxOutList, TxOut>(ref this.vout);
                    this.vout.Transaction = this;
                }

                if (((flags & 1) != 0) && witSupported)
                {
                    /* The witness flag is present, and we support witnesses. */
                    flags ^= 1;
                    var wit = new Witness(this.Inputs);
                    wit.ReadWrite(stream);
                }

                if (flags != 0)
                {
                    /* Unknown flag in the serialization */
                    throw new FormatException("Unknown transaction optional data");
                }
            }
            else
            {
                uint version = (witSupported && (this.vin.Count == 0 && this.vout.Count > 0)) ? this.nVersion | NoDummyInput : this.nVersion;
                stream.ReadWrite(ref version);

                // the POS time stamp
                stream.ReadWrite(ref this.nTime);

                if (witSupported)
                {
                    /* Check whether witnesses need to be serialized. */
                    if (this.HasWitness)
                    {
                        flags |= 1;
                    }
                }

                if (flags != 0)
                {
                    /* Use extended format in case witnesses are to be serialized. */
                    var vinDummy = new TxInList();
                    stream.ReadWrite <TxInList, TxIn>(ref vinDummy);
                    stream.ReadWrite(ref flags);
                }

                stream.ReadWrite <TxInList, TxIn>(ref this.vin);
                this.vin.Transaction = this;
                stream.ReadWrite <TxOutList, TxOut>(ref this.vout);
                this.vout.Transaction = this;
                if ((flags & 1) != 0)
                {
                    var wit = new Witness(this.Inputs);
                    wit.ReadWrite(stream);
                }
            }

            stream.ReadWriteStruct(ref this.nLockTime);
        }