public TransactionSignature(ECDSASignature signature, SigHash sigHash) { if(sigHash == SigHash.Undefined) throw new ArgumentException("sigHash should not be Undefined"); _SigHash = sigHash; _Signature = signature.MakeCanonical(); }
public TransactionSignature SignInput(Key key, ICoin coin, SigHash sigHash = SigHash.All) { return(Inputs.AsIndexedInputs().ToArray()[GetIndex(coin)].Sign(key, coin, sigHash)); }
public uint256 GetSignatureHash(ICoin coin, SigHash sigHash = SigHash.All) { return(Inputs.AsIndexedInputs().ToArray()[GetIndex(coin)].GetSignatureHash(coin, sigHash)); }
public Transaction SignTransactionInPlace(Transaction transaction, SigHash sigHash) { TransactionSigningContext ctx = new TransactionSigningContext(this, transaction); ctx.SigHash = sigHash; foreach(var input in transaction.Inputs.AsIndexedInputs()) { var coin = FindSignableCoin(input); if(coin != null) { Sign(ctx, coin, input); } } return transaction; }
//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); }
//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); }
public TransactionSignature(byte[] sig, SigHash sigHash) { _Signature = ECDSASignature.FromDER(sig).MakeCanonical(); _SigHash = sigHash; }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, Money value, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var eval = new ScriptEvaluationContext { SigHash = sigHash, ScriptVerify = scriptVerify }; var result = eval.VerifyScript(scriptSig, scriptPubKey, tx, i, value); error = eval.Error; return(result); }
public TransactionSignature Sign(Key key, Script scriptPubKey, SigHash sigHash = SigHash.All) { var hash = GetSignatureHash(scriptPubKey, sigHash); return(key.Sign(hash, sigHash)); }
public Sha256Hash HashTransactionForSignature(SigHash type, int inputIndex, byte[] connectedScript) { throw new NotImplementedException(); }
///** // * Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The // * signature is over the transaction itself, to prove the redeemer actually created that transaction, // * so we have to do this step last.<p> // * <p/> // * This method is similar to SignatureHash in script.cpp // * // * @param hashType This should always be set to SigHash.ALL currently. Other types are unused. // * @param wallet A wallet is required to fetch the keys needed for signing. // */ //public synchronized void signInputs(SigHash hashType, Wallet wallet) throws ScriptException { // Preconditions.checkState(inputs.size() > 0); // Preconditions.checkState(outputs.size() > 0); // // I don't currently have an easy way to test other modes work, as the official client does not use them. // Preconditions.checkArgument(hashType == SigHash.ALL, "Only SIGHASH_ALL is currently supported"); // // The transaction is signed with the input scripts empty except for the input we are signing. In the case // // where addInput has been used to set up a new transaction, they are already all empty. The input being signed // // has to have the connected OUTPUT program in it when the hash is calculated! // // // // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs // // to figure out which key to sign with. // byte[][] signatures = new byte[inputs.size()][]; // ECKey[] signingKeys = new ECKey[inputs.size()]; // for (int i = 0; i < inputs.size(); i++) { // TransactionInput input = inputs[i]; // if (input.getScriptBytes().length != 0) // log.warn("Re-signing an already signed transaction! Be sure this is what you want."); // // Find the signing key we'll need to use. // ECKey key = input.getOutpoint().getConnectedKey(wallet); // // This assert should never fire. If it does, it means the wallet is inconsistent. // Preconditions.checkNotNull(key, "Transaction exists in wallet that we cannot redeem: %s", // input.getOutpoint().getHash()); // // Keep the key around for the script creation step below. // signingKeys[i] = key; // // The anyoneCanPay feature isn't used at the moment. // boolean anyoneCanPay = false; // byte[] connectedPubKeyScript = input.getOutpoint().getConnectedPubKeyScript(); // Sha256Hash hash = hashTransactionForSignature(i, connectedPubKeyScript, hashType, anyoneCanPay); // // Now sign for the output so we can redeem it. We use the keypair to sign the hash, // // and then put the resulting signature in the script along with the public key (below). // try { // // Usually 71-73 bytes. // ByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(73); // bos.write(key.sign(hash).encodeToDER()); // bos.write((hashType.ordinal() + 1) | (anyoneCanPay ? 0x80 : 0)); // signatures[i] = bos.toByteArray(); // bos.close(); // } catch (IOException e) { // throw new RuntimeException(e); // Cannot happen. // } // } // // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists: // // 1) For pay-to-address outputs: a signature (over a hash of the simplified transaction) and the complete // // public key needed to sign for the connected output. The output script checks the provided pubkey hashes // // to the address and then checks the signature. // // 2) For pay-to-key outputs: just a signature. // for (int i = 0; i < inputs.size(); i++) { // TransactionInput input = inputs[i]; // ECKey key = signingKeys[i]; // Script scriptPubKey = input.getOutpoint().getConnectedOutput().getScriptPubKey(); // if (scriptPubKey.isSentToAddress()) { // input.setScriptBytes(Script.createInputScript(signatures[i], key.getPubKey())); // } else if (scriptPubKey.isSentToRawPubKey()) { // input.setScriptBytes(Script.createInputScript(signatures[i])); // } else { // // Should be unreachable - if we don't recognize the type of script we're trying to sign for, we should // // have failed above when fetching the key to sign with. // throw new RuntimeException("Do not understand script type: " + scriptPubKey); // } // } // // Every input is now complete. //} /** * Calculates a signature hash, that is, a hash of a simplified form of the transaction. How exactly the transaction * is simplified is specified by the type and anyoneCanPay parameters.<p> * * You don't normally ever need to call this yourself. It will become more useful in future as the contracts * features of Bitcoin are developed. * * @param inputIndex input the signature is being calculated for. Tx signatures are always relative to an input. * @param connectedScript the bytes that should be in the given input during signing. * @param type Should be SigHash.ALL * @param anyoneCanPay should be false. * @throws ScriptException if connectedScript is invalid */ public Sha256Hash hashTransactionForSignature(int inputIndex,byte[] connectedScript,SigHash type,bool anyoneCanPay) { return hashTransactionForSignature(inputIndex, connectedScript, (byte)((type.ordinal() + 1) | (anyoneCanPay ? 0x80 : 0x00))); }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify = ScriptVerify.StrictEnc | ScriptVerify.P2SH, SigHash sigHash = SigHash.Undefined) { ScriptEvaluationContext eval = new ScriptEvaluationContext(); eval.SigHash = sigHash; eval.ScriptVerify = scriptVerify; return eval.VerifyScript(scriptSig, scriptPubKey, tx, i); }
/// <summary> /// Build the transaction /// </summary> /// <param name="sign">True if signs all inputs with the available keys</param> /// <param name="sigHash">The type of signature</param> /// <returns>The transaction</returns> /// <exception cref="NBitcoin.NotEnoughFundsException">Not enough funds are available</exception> public Transaction BuildTransaction(bool sign, SigHash sigHash) { TransactionBuildingContext ctx = new TransactionBuildingContext(this); if(_CompletedTransaction != null) ctx.Transaction = _CompletedTransaction.Clone(); if(_LockTime != null) ctx.Transaction.LockTime = _LockTime.Value; foreach(var group in _BuilderGroups) { ctx.Group = group; ctx.AdditionalBuilders.Clear(); ctx.AdditionalFees = Money.Zero; ctx.ChangeType = ChangeType.Colored; foreach(var builder in group.IssuanceBuilders) builder(ctx); var buildersByAsset = group.BuildersByAsset.ToList(); foreach(var builders in buildersByAsset) { var coins = group.Coins.Values.OfType<ColoredCoin>().Where(c => c.Amount.Id == builders.Key); ctx.Dust = new AssetMoney(builders.Key); ctx.CoverOnly = null; ctx.ChangeAmount = new AssetMoney(builders.Key); var btcSpent = BuildTransaction(ctx, group, builders.Value, coins, new AssetMoney(builders.Key)) .OfType<IColoredCoin>().Select(c => c.Bearer.Amount).Sum(); ctx.AdditionalFees -= btcSpent; } ctx.AdditionalBuilders.Add(_ => _.AdditionalFees); ctx.Dust = GetDust(); ctx.ChangeAmount = Money.Zero; ctx.CoverOnly = group.CoverOnly; ctx.ChangeType = ChangeType.Uncolored; BuildTransaction(ctx, group, group.Builders, group.Coins.Values.OfType<Coin>(), Money.Zero); } ctx.Finish(); if(sign) { SignTransactionInPlace(ctx.Transaction, sigHash); } return ctx.Transaction; }
public TransactionBuilderSigner(ICoin coin, SigHash sigHash, IndexedTxIn txIn) { this.coin = coin; this.sigHash = sigHash; this.txIn = txIn; }
public uint256 GetSignatureHash(ICoin coin, SigHash sigHash = SigHash.All) { return(Script.SignatureHash(coin.GetScriptCode(), Transaction, (int)Index, sigHash, coin.TxOut.Value, coin.GetHashVersion())); }
public static bool VerifyScript(Script scriptPubKey, Transaction tx, int i, Money value, ScriptVerify scriptVerify = ScriptVerify.Standard, SigHash sigHash = SigHash.Undefined) { ScriptError unused; var scriptSig = tx.Inputs[i].ScriptSig; return(VerifyScript(scriptSig, scriptPubKey, tx, i, value, scriptVerify, sigHash, out unused)); }
public uint256 GetSignatureHash(Script scriptPubKey, int nIn, SigHash sigHash = SigHash.All) { return(Inputs.AsIndexedInputs().ToArray()[nIn].GetSignatureHash(scriptPubKey, sigHash)); }
public TransactionSignature SignInput(ISecret secret, Script scriptPubKey, int nIn, SigHash sigHash = SigHash.All) { return(SignInput(secret.PrivateKey, scriptPubKey, nIn, sigHash)); }
public TransactionSignature SignInput(Key key, Script scriptPubKey, int nIn, SigHash sigHash = SigHash.All) { return(Inputs.AsIndexedInputs().ToArray()[nIn].Sign(key, scriptPubKey, sigHash)); }
private byte[] HashTransactionForSignature(SigHash type, bool anyoneCanPay) { using (var bos = new MemoryStream()) { BitcoinSerializeToStream(bos); // We also have to write a hash type. var hashType = (uint) type + 1; if (anyoneCanPay) hashType |= 0x80; Utils.Uint32ToByteStreamLe(hashType, bos); // Note that this is NOT reversed to ensure it will be signed correctly. If it were to be printed out // however then we would expect that it is IS reversed. return Utils.DoubleDigest(bos.ToArray()); } }
/* * if (nIn >= txTo.vin.size()) * { * printf("ERROR: SignatureHash() : nIn=%d out of range\n", nIn); * return 1; * } * CTransaction txTmp(txTo); * * // In case concatenating two scripts ends up with two codeseparators, * // or an extra one at the end, this prevents all those possible incompatibilities. * scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR)); * * // Blank out other inputs' signatures * for (unsigned int i = 0; i < txTmp.vin.size(); i++) * txTmp.vin[i].scriptSig = CScript(); * txTmp.vin[nIn].scriptSig = scriptCode; * * // Blank out some of the outputs * if ((nHashType & 0x1f) == SIGHASH_NONE) * { * // Wildcard payee * txTmp.vout.clear(); * * // Let the others update at will * for (unsigned int i = 0; i < txTmp.vin.size(); i++) * if (i != nIn) * txTmp.vin[i].nSequence = 0; * } * else if ((nHashType & 0x1f) == SIGHASH_SINGLE) * { * // Only lock-in the txout payee at same index as txin * unsigned int nOut = nIn; * if (nOut >= txTmp.vout.size()) * { * printf("ERROR: SignatureHash() : nOut=%d out of range\n", nOut); * return 1; * } * txTmp.vout.resize(nOut+1); * for (unsigned int i = 0; i < nOut; i++) * txTmp.vout[i].SetNull(); * * // Let the others update at will * for (unsigned int i = 0; i < txTmp.vin.size(); i++) * if (i != nIn) * txTmp.vin[i].nSequence = 0; * } * * // Blank out other inputs completely, not recommended for open transactions * if (nHashType & SIGHASH_ANYONECANPAY) * { * txTmp.vin[0] = txTmp.vin[nIn]; * txTmp.vin.resize(1); * } * * // Serialize and hash * CHashWriter ss(SER_GETHASH, 0); * ss << txTmp << nHashType; * return ss.GetHash(); */ public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData) { if (nIn >= Inputs.Count) { //Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n"); return(uint256.One); } var scriptCopy = new Script(scriptCode.ToBytes()); scriptCopy = scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR); var hashType = nHashType & (SigHash)31; // Check for invalid use of SIGHASH_SINGLE //if (hashType == SigHash.Single) //{ // if (nIn >= Outputs.Count) // { // //Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); // return uint256.One; // } //} var txCopy = (SolarCoinTransaction)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) { if (nIn >= Outputs.Count) { //Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); return(uint256.One); } //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 < nIn; 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; } var previousType = txCopy.NType; txCopy.NType = (uint)PrimaryActions.SER_GETHASH; //Serialize TxCopy, append 4 byte hashtypecode var stream = CreateHashWriter(sigversion); txCopy.ReadWrite(stream); stream.ReadWrite((uint)nHashType); var txHash = GetHash(stream); txCopy.NType = previousType; return(txHash); }
public TransactionSignature UntrustedHashSign(KeyPath keyPath, UserPin pin, LockTime lockTime, SigHash sigHashType) { using(Transport.Lock()) { MemoryStream data = new MemoryStream(); byte[] path = Serializer.Serialize(keyPath); BufferUtils.WriteBuffer(data, path); var pinBytes = pin == null ? new byte[0] : pin.ToBytes(); data.WriteByte((byte)pinBytes.Length); BufferUtils.WriteBuffer(data, pinBytes); BufferUtils.WriteUint32BE(data, (uint)lockTime); data.WriteByte((byte)sigHashType); byte[] response = ExchangeApdu(LedgerWalletConstants.LedgerWallet_CLA, LedgerWalletConstants.LedgerWallet_INS_HASH_SIGN, (byte)0x00, (byte)0x00, data.ToArray(), OK); response[0] = (byte)0x30; return new TransactionSignature(response); } }
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); sss.ReadWrite(this.Time); // Neblio Timestamp!!! // 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)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(this.Time); // Neblio Timestamp!!! 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((uint)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)); }
public static bool VerifyScript(Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var scriptSig = tx.Inputs[i].ScriptSig; return VerifyScript(scriptSig, scriptPubKey, tx, i, scriptVerify, sigHash, out error); }
public static byte[] SignatureHash(Script script, Transaction txTo, int inIdx, SigHash hashtype) { Ensure.InRange(nameof(inIdx), inIdx, 0, txTo.Inputs.Count); var tx = txTo.Clone(); foreach (var input in tx.Inputs) { input.ScriptSig = Empty; } tx.Inputs[inIdx].ScriptSig = FindAndDelete(script, new Op(Opcode.OP_CODESEPARATOR)); switch (hashtype) { case SigHash.None: tx.Outputs.Clear(); foreach (var input in tx.Inputs.Where((x, i) => i != inIdx)) { input.Sequence = 0; } break; case SigHash.Single: var outIdx = inIdx; if (outIdx >= tx.Outputs.Count) { throw new IndexOutOfRangeException(); } var output = tx.Outputs[outIdx]; tx.Outputs.Clear(); for (var i = 0; i < outIdx; i++) { tx.Outputs.Add(new TxOut()); } tx.Outputs.Add(output); foreach (var input in tx.Inputs.Where((x, i) => i != inIdx)) { input.Sequence = 0; } break; case SigHash.AnyoneCanPay: var theInput = tx.Inputs[inIdx]; tx.Inputs = new List <TxIn> { theInput }; break; } var s = Packer.Pack("AI", tx.ToByteArray(), hashtype); return(Hashes.Hash256(s)); }
public TransactionSignature Sign(uint256 hash, SigHash sigHash, bool useLowR = true) { return(new TransactionSignature(Sign(hash, useLowR), sigHash)); }
public TransactionSignature SignInput(ISecret secret, ICoin coin, SigHash sigHash = SigHash.All) { return(SignInput(secret.PrivateKey, coin, sigHash)); }
public TransactionSignature Sign(uint256 hash, SigHash sigHash) { return(new TransactionSignature(Sign(hash), sigHash)); }
public TransactionSignature Sign(Key key, ICoin coin, SigHash sigHash) { var hash = GetSignatureHash(coin, sigHash); return(key.Sign(hash, sigHash)); }
public static bool VerifyScript(Script scriptSig, Transaction tx, int i, TxOut spentOutput, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { if (spentOutput == null) { throw new ArgumentNullException(nameof(spentOutput)); } var eval = new ScriptEvaluationContext { SigHash = sigHash, ScriptVerify = scriptVerify }; var result = eval.VerifyScript(scriptSig, tx, i, spentOutput); error = eval.Error; return(result); }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify = ScriptVerify.Standard, SigHash sigHash = SigHash.Undefined) { ScriptError unused; return(VerifyScript(scriptSig, scriptPubKey, tx, i, null, scriptVerify, sigHash, out unused)); }
public static uint256 SignatureHash(ICoin coin, Transaction txTo, SigHash nHashType = SigHash.All) { return(txTo.GetSignatureHash(coin, nHashType)); }
public static bool VerifyScript(Script scriptPubKey, Transaction tx, int i, Money value, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var scriptSig = tx.Inputs[i].ScriptSig; return(VerifyScript(scriptSig, scriptPubKey, tx, i, value, scriptVerify, sigHash, out error)); }
public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount = null, HashVersion sigversion = HashVersion.Original) { return(txTo.GetSignatureHash(scriptCode, nIn, nHashType, amount, sigversion, null)); }
//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(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(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)); }
public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData) { return(txTo.GetSignatureHash(scriptCode, nIn, nHashType, amount, sigversion, precomputedTransactionData)); }
public TransactionSignature(byte[] sigSigHash) { _Signature = ECDSASignature.FromDER(sigSigHash.Take(sigSigHash.Length - 1).ToArray()).MakeCanonical(); _SigHash = (SigHash)sigSigHash[sigSigHash.Length - 1]; }
public static bool VerifyScript(Transaction tx, int i, TxOut spentOutput, ScriptVerify scriptVerify = ScriptVerify.Standard, SigHash sigHash = SigHash.Undefined) { ScriptError unused; var scriptSig = tx.Inputs[i].ScriptSig; return(VerifyScript(scriptSig, tx, i, spentOutput, scriptVerify, sigHash, out unused)); }
/// <summary> /// Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The /// signature is over the transaction itself, to prove the redeemer actually created that transaction, /// so we have to do this step last. /// </summary> /// <remarks> /// This method is similar to SignatureHash in script.cpp /// </remarks> /// <param name="hashType">This should always be set to SigHash.ALL currently. Other types are unused. </param> /// <param name="wallet">A wallet is required to fetch the keys needed for signing.</param> /// <exception cref="ScriptException"/> public void SignInputs(SigHash hashType, Wallet wallet) { Debug.Assert(_inputs.Count > 0); Debug.Assert(_outputs.Count > 0); // I don't currently have an easy way to test other modes work, as the official client does not use them. Debug.Assert(hashType == SigHash.All); // The transaction is signed with the input scripts empty except for the input we are signing. In the case // where addInput has been used to set up a new transaction, they are already all empty. The input being signed // has to have the connected OUTPUT program in it when the hash is calculated! // // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs // to figure out which key to sign with. var signatures = new byte[_inputs.Count][]; var signingKeys = new EcKey[_inputs.Count]; for (var i = 0; i < _inputs.Count; i++) { var input = _inputs[i]; Debug.Assert(input.ScriptBytes.Length == 0, "Attempting to sign a non-fresh transaction"); // Set the input to the script of its output. input.ScriptBytes = input.Outpoint.ConnectedPubKeyScript; // Find the signing key we'll need to use. var connectedPubKeyHash = input.Outpoint.ConnectedPubKeyHash; var key = wallet.FindKeyFromPubHash(connectedPubKeyHash); // This assert should never fire. If it does, it means the wallet is inconsistent. Debug.Assert(key != null, "Transaction exists in wallet that we cannot redeem: " + Utils.BytesToHexString(connectedPubKeyHash)); // Keep the key around for the script creation step below. signingKeys[i] = key; // The anyoneCanPay feature isn't used at the moment. const bool anyoneCanPay = false; var hash = HashTransactionForSignature(hashType, anyoneCanPay); // Set the script to empty again for the next input. input.ScriptBytes = TransactionInput.EmptyArray; // Now sign for the output so we can redeem it. We use the keypair to sign the hash, // and then put the resulting signature in the script along with the public key (below). using (var bos = new MemoryStream()) { bos.Write(key.Sign(hash)); bos.Write((byte) (((int) hashType + 1) | (anyoneCanPay ? 0x80 : 0))); signatures[i] = bos.ToArray(); } } // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists of // a signature (over a hash of the transaction) and the complete public key needed to sign for the connected // output. for (var i = 0; i < _inputs.Count; i++) { var input = _inputs[i]; Debug.Assert(input.ScriptBytes.Length == 0); var key = signingKeys[i]; input.ScriptBytes = Script.CreateInputScript(signatures[i], key.PubKey); } // Every input is now complete. }
public static bool VerifyScript(Transaction tx, int i, TxOut spentOutput, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var scriptSig = tx.Inputs[i].ScriptSig; return(VerifyScript(scriptSig, tx, i, spentOutput, scriptVerify, sigHash, out error)); }
//https://en.bitcoin.it/wiki/OP_CHECKSIG public static uint256 SignatureHash(ICoin coin, Transaction txTo, SigHash nHashType = SigHash.All) { var input = txTo.Inputs.AsIndexedInputs().FirstOrDefault(i => i.PrevOut == coin.Outpoint); if(input == null) throw new ArgumentException("coin should be spent spent in txTo", "coin"); return input.GetSignatureHash(coin, nHashType); }
private bool UsesForkId(SigHash nHashType) { return(((uint)nHashType & 0x40u) != 0); }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, Money value, ScriptVerify scriptVerify = ScriptVerify.Standard, SigHash sigHash = SigHash.Undefined) { ScriptError unused; return VerifyScript(scriptSig, scriptPubKey, tx, i, value, scriptVerify, sigHash, out unused); }
public override uint256 GetSignatureHash(Script scriptCode, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData) { uint nForkHashType = (uint)nHashType; if (UsesForkId(nHashType)) { nForkHashType |= ForkId << 8; } if ((SupportSegwit && sigversion == HashVersion.Witness) || UsesForkId(nHashType)) { 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() : 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(amount.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)); }
public TransactionSignature Sign(uint256 hash, SigHash sigHash) { return new TransactionSignature(Sign(hash), sigHash); }
//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)); }
public static bool VerifyScript(Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify = ScriptVerify.Standard, SigHash sigHash = SigHash.Undefined) { ScriptError unused; var scriptSig = tx.Inputs[i].ScriptSig; return VerifyScript(scriptSig, scriptPubKey, tx, i, scriptVerify, sigHash, out unused); }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify = ScriptVerify.StrictEnc | ScriptVerify.P2SH, SigHash sigHash = SigHash.Undefined) { ScriptEvaluationContext eval = new ScriptEvaluationContext(); eval.SigHash = sigHash; eval.ScriptVerify = scriptVerify; return(eval.VerifyScript(scriptSig, scriptPubKey, tx, i)); }
public static bool VerifyScript(Script scriptSig, Script scriptPubKey, Transaction tx, int i, ScriptVerify scriptVerify, SigHash sigHash, out ScriptError error) { var eval = new ScriptEvaluationContext { SigHash = sigHash, ScriptVerify = scriptVerify }; var result = eval.VerifyScript(scriptSig, scriptPubKey, tx, i); error = eval.Error; return result; }
public Transaction SignTransaction(Transaction transaction, SigHash sigHash) { var tx = transaction.Clone(); SignTransactionInPlace(tx, sigHash); return tx; }