private static string ConvertSigHashTypeToString(SigHashType sigHashType) { if (sigHashType.Equals(SigHashType.All)) { return("ALL"); } if (sigHashType.Equals(SigHashType.None)) { return("NONE"); } if (sigHashType.Equals(SigHashType.Single)) { return("SINGLE"); } if (sigHashType.Equals(SigHashType.AllOrAnyoneCanPay)) { return("ALL|ANYONECANPAY"); } if (sigHashType.Equals(SigHashType.NoneOrAnyoneCanPay)) { return("NONE|ANYONECANPAY"); } if (sigHashType.Equals(SigHashType.SingleOrAnyoneCanPay)) { return("SINGLE|ANYONECANPAY"); } throw new Exception("SigHashType " + sigHashType.ToString() + " is unsupported in ConvertSigHashTypeToString!"); }
public static IEnumerable <object[]> GetSignCases(TxCaseType mode) { // Transactions are signed with bitcoin-core version 0.19.0.1 (bitcoin-0.19.0.1-x86_64-linux-gnu.tar) // All transactions are broadcast and are included in blocks on testnet. JArray jar = Helper.ReadResource <JArray>("SignedTxTestData"); foreach (var Case in jar) { Transaction prevTx = new Transaction(); prevTx.TryDeserialize(new FastStreamReader(Helper.HexToBytes(Case["TxToSpend"].ToString())), out string _); foreach (var item in Case["Cases"]) { if (mode == TxCaseType.BytesToSign || mode == TxCaseType.FinalSignedTx) { Transaction tx = new Transaction(); FastStreamReader stream = new FastStreamReader(Helper.HexToBytes(item["TxToSign"].ToString())); if (!tx.TryDeserialize(stream, out string err)) { throw new ArgumentException($"Could not deseralize the given tx case: " + $"{item["TestName"]}. Error: {err}"); } SigHashType sht = (SigHashType)(uint)item["SigHashType"]; int[] indexes = item["Indexes"].ToObject <int[]>(); if (mode == TxCaseType.BytesToSign) { string[] hashes = item["BytesToSign"].ToObject <string[]>(); yield return(new object[] { tx, prevTx, sht, indexes, hashes }); } else { string key = item["PrivateKey"].ToString(); byte[] signedTx = Helper.HexToBytes(item["SignedTx"].ToString()); yield return(new object[] { key, tx, prevTx, sht, indexes, signedTx }); } } else if (mode == TxCaseType.TxId) { Transaction tx = new Transaction(); FastStreamReader stream = new FastStreamReader(Helper.HexToBytes(item["SignedTx"].ToString())); if (!tx.TryDeserialize(stream, out string err)) { throw new ArgumentException($"Could not deseralize the given tx case: " + $"{item["TestName"]}. Error: {err}"); } string txId = item["TxId"].ToString(); string wtxId = item["WTxId"].ToString(); yield return(new object[] { tx, txId, wtxId }); } else { throw new ArgumentException("Undefined mode"); } } } }
public void GetBytesToSignTest(ITransaction tx, ITransaction prvTx, SigHashType sht, int[] indexes, string[] expBytes) { Assert.Equal(indexes.Length, expBytes.Length); for (int i = 0; i < indexes.Length; i++) { byte[] actualBytes = tx.GetBytesToSign(prvTx, indexes[i], sht, null, null); Assert.Equal(Helper.HexToBytes(expBytes[i]), actualBytes); } }
public void TryReadLooseTest(byte[] data, BigInteger expR, BigInteger expS, SigHashType expSH) { bool b = Signature.TryReadLoose(data, out Signature sig, out string error); Assert.True(b, error); Assert.Null(error); Assert.Equal(expR, sig.R); Assert.Equal(expS, sig.S); Assert.Equal(expSH, sig.SigHash); }
public static IEnumerable <object[]> GetSignCases(TxCaseType mode) { // Transactions are signed with bitcoin-core version 0.19.0.1 (bitcoin-0.19.0.1-x86_64-linux-gnu.tar) // All transactions are broadcast and are included in blocks on testnet. JArray jar = Helper.ReadResource <JArray>("SignedTxTestData"); foreach (var Case in jar) { var prevTx = new Transaction(Case["TxToSpend"].ToString()); foreach (var item in Case["Cases"]) { if (mode == TxCaseType.BytesToSign || mode == TxCaseType.FinalSignedTx) { var tx = new Transaction(item["TxToSign"].ToString()); SigHashType sht = (SigHashType)(uint)item["SigHashType"]; int[] indexes = item["Indexes"].ToObject <int[]>(); if (mode == TxCaseType.BytesToSign) { string[] hashes = item["BytesToSign"].ToObject <string[]>(); yield return(new object[] { tx, prevTx, sht, indexes, hashes }); } else { string key = item["PrivateKey"].ToString(); byte[] signedTx = Helper.HexToBytes(item["SignedTx"].ToString()); yield return(new object[] { key, tx, prevTx, sht, indexes, signedTx }); } } else if (mode == TxCaseType.TxId) { var tx = new Transaction(item["SignedTx"].ToString()); string txId = item["TxId"].ToString(); string wtxId = item["WTxId"].ToString(); yield return(new object[] { tx, txId, wtxId }); } else if (mode == TxCaseType.Size) { string hex = item["SignedTx"].ToString(); var tx = new Transaction(hex); int totalSize = hex.Length / 2; int baseSize = (int)item["BaseSize"]; int weight = (int)item["Weight"]; int virtualSize = (int)item["VirtualSize"]; yield return(new object[] { tx, totalSize, baseSize, weight, virtualSize }); } else { throw new ArgumentException("Undefined mode"); } } } }
public void ToByteArrayTest(byte[] expBytes, BigInteger r, BigInteger s, SigHashType sh) { Signature sig = new Signature() { R = r, S = s, SigHash = sh }; byte[] actualBytes = sig.ToByteArray(); Assert.Equal(expBytes, actualBytes); }
public void Key_SignTxTest(string wif, ITransaction tx, ITransaction prvTx, SigHashType sht, int[] indexes, byte[] expSer) { using PrivateKey key = new(wif, NetworkType.TestNet); for (int i = 0; i < indexes.Length; i++) { key.Sign(tx, prvTx, indexes[i], sht); } var stream = new FastStream(expSer.Length); tx.Serialize(stream); byte[] actualSer = stream.ToByteArray(); Assert.Equal(expSer, actualSer); }
public static string GetSigHashType(SigHashType hashType) { switch (hashType) { case SigHashType.ALL: { return("ALL"); } case SigHashType.NONE: { return("NONE"); } case SigHashType.SINGLE: { return("SINGLE"); } case SigHashType.ALL_ANYONECANPAY: { return("ALL|ANYONECANPAY"); } case SigHashType.NONE_ANYONECANPAY: { return("NONE|ANYONECANPAY"); } case SigHashType.SINGLE_ANYONECANPAY: { return("SINGLE|ANYONECANPAY"); } default: { return(null); } } }
public async Task <byte[]> ComputeSigHash(Transaction transaction, TransactionInput input, SigHashType sigHashType) { var priorOutput = await fetcher.FetchPriorOutput(input); return(ComputeSigHash(transaction, input, priorOutput, sigHashType)); }
public byte[] ComputeSigHash(Transaction transaction, TransactionInput input, TransactionOutput priorOutput, SigHashType sigHashType) { if (sigHashType != SigHashType.All) { throw new NotImplementedException("Only supports SigHashType.All"); } var hashingScript = IsPayToScriptHash(input.SigScript, priorOutput.ScriptPubKey) ? DecodeRedeemScript((byte[])input.SigScript.Commands[^ 1]) :
/// <summary> /// Sign inputs for raw transaction (serialized, hex-encoded). /// </summary> /// <param name="hexstring">The transaction hex string.</param> /// <param name="privkeys">The base58-encoded private keys for signing.</param> /// <param name="prevTxs">The previous dependent transaction outputs.</param> /// <param name="sigHashType">The signature hash type.</param> /// <returns></returns> public async Task <string> SignRawTransactionWithKey(string hexstring, List <string> privkeys, List <PrevTxs> prevTxs, SigHashType sigHashType) { SignRawTransactionWithKey signRawTransactionWithKey = new SignRawTransactionWithKey() { Hexstring = hexstring, PrivKeys = privkeys, PrevTxs = prevTxs, HashType = sigHashType }; string response = await httpRequest.SendReq(MethodName.signrawtransactionwithkey, signRawTransactionWithKey); return(response); }
public async Task <byte[]> ComputeSigHash(Transaction transaction, int inputIndex, SigHashType sigHashType) { CheckInputIndex(transaction, inputIndex); return(await ComputeSigHash(transaction, transaction.Inputs[inputIndex], sigHashType)); }
public void IsSingleTest(SigHashType sht, bool expected) { Assert.Equal(expected, sht.IsSingle()); }
public override async Task <Script> CreateSigScript(PrivateKey privateKey, Transaction transaction, TransactionInput input, SigHashType sigHashType) { var signature = await ComputeSignatureBytes(privateKey, transaction, input, sigHashType); var sec = privateKey.PublicKey.ToSec(); return(new Script(signature, sec)); }
public static string SignRawTransaction(String txHex, RawTxInput[] inputs = null, string[] privateKeys = null, SigHashType sigHashType = SigHashType.All) { if (inputs == null) return SimpleStringRequest ("signrawtransaction", qt + txHex + qt, false); string inputInfo = ConvertTxsToString (inputs); if (privateKeys == null) return SimpleStringRequest ("signrawtransaction", qt + txHex + qt + ", " + inputInfo, false); string privateKeysFormatted = "["; bool firstOne = true; foreach (string key in privateKeys) { if (firstOne) firstOne = false; else privateKeysFormatted += ","; privateKeysFormatted += qt + key + qt; } privateKeysFormatted += "]"; return SimpleStringRequest ("signrawtransaction", qt + txHex + qt + ", " + inputInfo + ", " + privateKeysFormatted + ", " + qt + ConvertSigHashTypeToString(sigHashType) + qt, false); }
public async Task <Transaction> SignTransaction(Wallet wallet, Transaction transaction, SigHashType sigHashType, bool ignoreKeyNotFound = false) { foreach (var input in transaction.Inputs) { var priorOutput = await fetcher.FetchPriorOutput(input); var scriptType = scriptClassifier.GetScriptType(priorOutput.ScriptPubKey); var signer = signerMap[scriptType]; if (signer != null) { try { var sigScript = await signer.CreateSigScript(wallet, transaction, input, sigHashType); transaction = transaction.CloneWithReplacedSigScript(input, sigScript); } catch (PrivateKeyNotFoundException) { if (!ignoreKeyNotFound) { throw; } } } else if (!ignoreKeyNotFound) { throw new InvalidOperationException($"Unknown script type for prior output {input.PreviousTransaction}:{input.PreviousIndex}"); } } return(transaction); }
/// <summary> /// Initializes a new instance of <see cref="Signature"/> using the given parameters. /// </summary> /// <param name="r">R value</param> /// <param name="s">S value</param> /// <param name="sigHash">Signature hash type</param> public Signature(BigInteger r, BigInteger s, SigHashType sigHash) { R = r; S = s; SigHash = sigHash; }
public static string SignRawTransaction(String txHex, RawTxInput[] inputs = null, string[] privateKeys = null, SigHashType sigHashType = SigHashType.All) { if (inputs == null) { return(SimpleStringRequest("signrawtransaction", qt + txHex + qt, false)); } string inputInfo = ConvertTxsToString(inputs); if (privateKeys == null) { return(SimpleStringRequest("signrawtransaction", qt + txHex + qt + ", " + inputInfo, false)); } string privateKeysFormatted = "["; bool firstOne = true; foreach (string key in privateKeys) { if (firstOne) { firstOne = false; } else { privateKeysFormatted += ","; } privateKeysFormatted += qt + key + qt; } privateKeysFormatted += "]"; return(SimpleStringRequest("signrawtransaction", qt + txHex + qt + ", " + inputInfo + ", " + privateKeysFormatted + ", " + qt + ConvertSigHashTypeToString(sigHashType) + qt, false)); }
public void TryReadLoose_FromStrictCases_Test(byte[] data, BigInteger expR, BigInteger expS, SigHashType expSH) { // Reading with loose rules must still pass on strict cases bool b = Signature.TryReadLoose(data, out Signature sig, out string error); Assert.True(b, error); Assert.Null(error); Assert.Equal(expR, sig.R); Assert.Equal(expS, sig.S); Assert.Equal(expSH, sig.SigHash); }
public abstract Task <Script> CreateSigScript(PrivateKey privateKey, Transaction transaction, TransactionInput input, SigHashType sigHashType);
public abstract Task <Script> CreateSigScript(Wallet wallet, Transaction transaction, TransactionInput input, SigHashType sigHashType);
private static string ConvertSigHashTypeToString(SigHashType sigHashType) { if (sigHashType.Equals (SigHashType.All)) return "ALL"; if (sigHashType.Equals (SigHashType.None)) return "NONE"; if (sigHashType.Equals (SigHashType.Single)) return "SINGLE"; if (sigHashType.Equals (SigHashType.AllOrAnyoneCanPay)) return "ALL|ANYONECANPAY"; if (sigHashType.Equals (SigHashType.NoneOrAnyoneCanPay)) return "NONE|ANYONECANPAY"; if (sigHashType.Equals (SigHashType.SingleOrAnyoneCanPay)) return "SINGLE|ANYONECANPAY"; throw new Exception ("SigHashType " + sigHashType.ToString () + " is unsupported in ConvertSigHashTypeToString!"); }
protected async Task <byte[]> ComputeSignatureBytes(PrivateKey privateKey, Transaction transaction, TransactionInput input, SigHashType sigHashType) { var hash = await hasher.ComputeSigHash(transaction, input, sigHashType); return(privateKey.Sign(hash).ToDer().Concat((byte)sigHashType)); }
public override async Task <Script> CreateSigScript(Wallet wallet, Transaction transaction, TransactionInput input, SigHashType sigHashType) { var priorOutput = await Fetcher.FetchPriorOutput(input); if (priorOutput.ScriptPubKey.Commands.Count < 3 || !(priorOutput.ScriptPubKey.Commands[2] is byte[] hash)) { throw new FormatException("Unexpected opcode in output script"); } var privateKey = wallet.FindByHash(hash); if (privateKey == null) { throw new PrivateKeyNotFoundException("Key not found in wallet"); } return(await CreateSigScript(privateKey, transaction, input, sigHashType)); }
public void IsAnyoneCanPayTest(SigHashType sht, bool expected) { Assert.Equal(expected, sht.IsAnyoneCanPay()); }