public bool VerifyScript(UInt256 blockHash, int txIndex, byte[] scriptPubKey, Transaction tx, int inputIndex, byte[] script) { if (logger.IsTraceEnabled) logger.Trace( @"++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Verifying script for block {0}, transaction {1}, input {2} {3} ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" , blockHash, txIndex, inputIndex, script.ToArray().ToHexDataString()); Stack stack, altStack; if ( ExecuteOps(scriptPubKey, tx, inputIndex, script, out stack, out altStack) && stack.Count == 1 && altStack.Count == 0) { var success = stack.PeekBool(); //TODO Pop? does it matter? // Additional validation for spend-to-script-hash transactions: //TODO return success; } else { return false; } }
public void TestCalculateTransactionHash() { var expectedHash = UInt256.ParseHex("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); var tx = new Transaction ( version: 1, inputs: ImmutableArray.Create( new TxInput ( previousTxOutputKey: new TxOutputKey(txHash: UInt256.Zero, txOutputIndex: 4294967295), scriptSignature: "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73".HexToByteArray().ToImmutableArray(), sequence: 4294967295 )), outputs: ImmutableArray.Create( new TxOutput ( value: (UInt64)(50L * 100.MILLION()), scriptPublicKey: "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac".HexToByteArray().ToImmutableArray() )), lockTime: 0 ); Assert.AreEqual(expectedHash, DataCalculator.CalculateTransactionHash(tx)); Assert.AreEqual(expectedHash, DataCalculator.CalculateTransactionHash(tx.Version, tx.Inputs, tx.Outputs, tx.LockTime)); }
public Transaction CreateCoinbaseTransaction(ECPublicKeyParameters publicKey, byte[] coinbase) { var tx = new Transaction ( version: 1, inputs: ImmutableArray.Create ( new TxInput ( previousTxOutputKey: new TxOutputKey ( txHash: UInt256.Zero, txOutputIndex: 0 ), scriptSignature: coinbase.ToImmutableArray(), sequence: 0 ) ), outputs: ImmutableArray.Create ( new TxOutput ( value: 50L * (100 * 1000 * 1000), scriptPublicKey: CreatePublicKeyScript(publicKey).ToImmutableArray() ) ), lockTime: 0 ); return tx; }
public override void ValidationTransactionScript(ChainedHeader chainedHeader, Transaction tx, int txIndex, TxInput txInput, int txInputIndex, TxOutput prevTxOutput) { if (ValidationTransactionScriptAction == null) base.ValidationTransactionScript(chainedHeader, tx, txIndex, txInput, txInputIndex, prevTxOutput); else ValidationTransactionScriptAction(chainedHeader, tx, txIndex, txInput, txInputIndex, prevTxOutput); }
public LoadingTx(int txIndex, Transaction transaction, ChainedHeader chainedHeader, ImmutableArray<TxLookupKey> prevOutputTxKeys) { Transaction = transaction; TxIndex = txIndex; ChainedHeader = chainedHeader; PrevOutputTxKeys = prevOutputTxKeys; InputTxes = new CompletionArray<DecodedTx>(txIndex != 0 ? transaction.Inputs.Length : 0); }
public static DecodedBlockTx Create(int txIndex, Transaction tx) { if (tx == null) throw new ArgumentNullException(nameof(tx)); var decodedTx = DataEncoder.EncodeTransaction(tx); return new DecodedBlockTx(txIndex, decodedTx); }
public byte[] TxSignature(byte[] scriptPubKey, Transaction tx, int inputIndex, byte hashType) { ///TODO Debug.Assert(inputIndex < tx.Inputs.Length); // Blank out other inputs' signatures var empty = ImmutableArray.Create<byte>(); var newInputs = ImmutableArray.CreateBuilder<TxInput>(tx.Inputs.Length); for (var i = 0; i < tx.Inputs.Length; i++) { var oldInput = tx.Inputs[i]; var newInput = oldInput.With(scriptSignature: i == inputIndex ? scriptPubKey.ToImmutableArray() : empty); newInputs.Add(newInput); } //// Blank out some of the outputs //if ((hashType & 0x1F) == (int)ScriptHashType.SIGHASH_NONE) //{ // //TODO // Debug.Assert(false); // // Wildcard payee // // Let the others update at will //} //else if ((hashType & 0x1F) == (int)ScriptHashType.SIGHASH_SINGLE) //{ // //TODO // Debug.Assert(false); // // Only lock-in the txout payee at same index as txin // // Let the others update at will //} //// Blank out other inputs completely, not recommended for open transactions //if ((hashType & 0x80) == (int)ScriptHashType.SIGHASH_ANYONECANPAY) //{ // //TODO // Debug.Assert(false); //} // create simplified transaction var newTx = tx.With(Inputs: newInputs.ToImmutable()); // return wire-encoded simplified transaction with the 4-byte hashType tacked onto the end using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.WriteBytes(DataEncoder.EncodeTransaction(newTx)); writer.WriteUInt32(hashType); return stream.ToArray(); } }
public void TestReadOneLoadingTx() { var coreStorageMock = new Mock<ICoreStorage>(); // create a fake transaction with 4 inputs var prevTxCount = 4; var txIndex = 1; var chainedHeader = RandomData.RandomChainedHeader(); // create previous transactions for 4 inputs var prevTxes = new Transaction[prevTxCount]; var inputs = new TxInput[prevTxCount]; for (var i = 0; i < prevTxCount; i++) { var prevTx = RandomData.RandomTransaction(); var prevBlockTx = (BlockTx)BlockTx.Create(i, prevTx); prevTxes[i] = prevTx; inputs[i] = new TxInput(prevTx.Hash, 0, ImmutableArray.Create<byte>(), 0); // mock retrieval of the previous transaction coreStorageMock.Setup(coreStorage => coreStorage.TryGetTransaction(UInt256.Zero, i, out prevBlockTx)).Returns(true); } // create a loading tx with the 4 inputs referencing block hash 0 var tx = RandomData.RandomTransaction(new RandomDataOptions { TxOutputCount = 1 }) .CreateWith(Inputs: inputs.ToImmutableArray()).Transaction; var prevOutputTxKeys = ImmutableArray.CreateRange( Enumerable.Range(0, prevTxCount).Select(x => new TxLookupKey(UInt256.Zero, x))); var loadingTx = new LoadingTx(txIndex, tx, chainedHeader, prevOutputTxKeys); // begin queuing transactions to load var loadingTxes = new BufferBlock<LoadingTx>(); loadingTxes.Post(loadingTx); loadingTxes.Complete(); // begin transaction loading var txLoader = TxLoader.LoadTxes(coreStorageMock.Object, loadingTxes); // verify the loaded transaction var loadedTxesBuffer = new BufferBlock<LoadedTx>(); txLoader.LinkTo(loadedTxesBuffer, new DataflowLinkOptions { PropagateCompletion = true }); txLoader.Completion.Wait(); IList<LoadedTx> actualLoadedTxes; Assert.IsTrue(loadedTxesBuffer.TryReceiveAll(out actualLoadedTxes)); var actualLoadedTx = actualLoadedTxes.Single(); Assert.AreEqual(loadingTx.TxIndex, actualLoadedTx.TxIndex); Assert.AreEqual(loadingTx.Transaction, actualLoadedTx.Transaction); CollectionAssert.AreEqual(prevTxes.Select(x => x.Hash).ToArray(), actualLoadedTx.InputTxes.Select(x => x.Hash).ToArray()); }
/// <summary> /// Initializes a new instance of <see cref="LoadedTx"/> with the specified transaction and each input's previous transaction. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="txIndex">The index of the transaction.</param> /// <param name="inputTxes">The array of transactions corresponding to each input's previous transaction.</param> public LoadedTx(Transaction transaction, int txIndex, ImmutableArray<DecodedTx> inputTxes) { Transaction = transaction; TxIndex = txIndex; InputTxes = inputTxes; if (TxIndex == 0) { if (inputTxes.Length != 0) throw new InvalidOperationException($"Coinbase InputTxes.Length: {inputTxes.Length}"); } else { if (inputTxes.Length != transaction.Inputs.Length) throw new InvalidOperationException($"Transaction.Inputs.Length: {transaction.Inputs.Length}, InputTxes.Length: {inputTxes.Length}"); } }
private void Mint(IChainStateCursor chainStateCursor, Transaction tx, int txIndex, ChainedHeader chainedHeader) { // add transaction to the utxo var unspentTx = new UnspentTx(tx.Hash, chainedHeader.Height, txIndex, tx.Version, tx.IsCoinbase, tx.Outputs.Length, OutputState.Unspent); if (!chainStateCursor.TryAddUnspentTx(unspentTx)) { // duplicate transaction logger.Warn($"Duplicate transaction at block {chainedHeader.Height:N0}, {chainedHeader.Hash}, coinbase"); throw new ValidationException(chainedHeader.Hash); } // add transaction outputs to the utxo for (var outputIndex = 0; outputIndex < tx.Outputs.Length; outputIndex++) { var output = tx.Outputs[outputIndex]; if (!chainStateCursor.TryAddUnspentTxOutput(new TxOutputKey(tx.Hash, (uint)outputIndex), output)) throw new ValidationException(chainedHeader.Hash); } }
public byte[] CreatePrivateKeyScript(Transaction tx, int inputIndex, byte hashType, ECPrivateKeyParameters privateKey, ECPublicKeyParameters publicKey) { //TODO var scriptEngine = new ScriptEngine(); var publicAddress = CreatePublicAddress(publicKey); var publicKeyScript = CreatePublicKeyScript(publicAddress); var txSignature = scriptEngine.TxSignature(publicKeyScript, tx, inputIndex, hashType); var txSignatureHash = SHA256Static.ComputeDoubleHash(txSignature); //Debug.WriteLine("Signing Tx: {0}".Format2(txSignature.ToHexDataString())); //Debug.WriteLine("Signing Tx Hash: {0}".Format2(txSignatureHash.ToHexDataString())); var signer = new ECDsaSigner(); signer.Init(forSigning: true, parameters: privateKey); var signature = signer.GenerateSignature(txSignatureHash); var r = signature[0]; var s = signature[1]; byte[] sigEncoded; using (var stream = new MemoryStream()) { using (var asn1Stream = new Asn1OutputStream(stream)) { asn1Stream.WriteObject(new DerSequence(new DerInteger(r), new DerInteger(s))); } sigEncoded = stream.ToArray().Concat(hashType); } //Debug.WriteLine("Sig R: {0}".Format2(r.ToHexNumberStringUnsigned())); //Debug.WriteLine("Sig S: {0}".Format2(s.ToHexNumberStringUnsigned())); //Debug.WriteLine("Sig Encoded: {0}".Format2(sigEncoded.ToHexDataString())); using (var privateKeyScript = new ScriptBuilder()) { privateKeyScript.WritePushData(sigEncoded); privateKeyScript.WritePushData(publicAddress); //Debug.WriteLine("Private Script: {0}".Format2(privateKeyScript.GetScript().ToHexDataString())); return privateKeyScript.GetScript(); } }
public bool TryGetTransaction(UInt256 blockHash, int txIndex, out Transaction transaction) { int blockId; if (!this.TryGetBlockId(blockHash, out blockId)) { transaction = default(Transaction); return(false); } using (var handle = this.cursorCache.TakeItem()) { var cursor = handle.Item; using (var jetTx = cursor.jetSession.BeginTransaction()) { Api.JetSetCurrentIndex(cursor.jetSession, cursor.blocksTableId, "IX_BlockIdTxIndex"); Api.MakeKey(cursor.jetSession, cursor.blocksTableId, blockId, MakeKeyGrbit.NewKey); Api.MakeKey(cursor.jetSession, cursor.blocksTableId, txIndex, MakeKeyGrbit.None); if (Api.TrySeek(cursor.jetSession, cursor.blocksTableId, SeekGrbit.SeekEQ)) { var txBytes = Api.RetrieveColumn(cursor.jetSession, cursor.blocksTableId, cursor.blockTxBytesColumnId); if (txBytes != null) { transaction = DataEncoder.DecodeTransaction(txBytes); return(true); } else { transaction = default(Transaction); return(false); } } else { transaction = default(Transaction); return(false); } } } }
private void TestTransactionSignature(byte[][] expectedSignatures, Transaction tx, IDictionary<UInt256, Transaction> txLookup) { var scriptEngine = new ScriptEngine(); for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; var prevOutput = txLookup[input.PreviousTxOutputKey.TxHash].Outputs[input.PreviousTxOutputKey.TxOutputIndex.ToIntChecked()]; var hashType = GetHashTypeFromScriptSig(input.ScriptSignature.ToArray()); var actual = scriptEngine.TxSignature(prevOutput.ScriptPublicKey.ToArray(), tx, inputIndex, hashType); CollectionAssert.AreEqual(expectedSignatures[inputIndex].ToList(), actual.ToList()); } }
public static DecodedTx EncodeTransaction(Transaction tx) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { EncodeTransaction(writer, tx); var txBytes = stream.ToArray(); return new DecodedTx(txBytes.ToImmutableArray(), tx); } }
public static DecodedTx EncodeTransaction(UInt32 Version, ImmutableArray<TxInput> Inputs, ImmutableArray<TxOutput> Outputs, UInt32 LockTime) { using (var stream = new MemoryStream()) using (var writer = new BinaryWriter(stream)) { writer.WriteUInt32(Version); writer.WriteList(Inputs, input => EncodeTxInput(writer, input)); writer.WriteList(Outputs, output => EncodeTxOutput(writer, output)); writer.WriteUInt32(LockTime); var txBytes = stream.ToArray(); var txHash = new UInt256(SHA256Static.ComputeDoubleHash(txBytes)); var tx = new Transaction(Version, Inputs, Outputs, LockTime, txHash); return new DecodedTx(txBytes.ToImmutableArray(), tx); } }
public static void EncodeTransaction(BinaryWriter writer, Transaction tx) { writer.WriteUInt32(tx.Version); writer.WriteList(tx.Inputs, input => EncodeTxInput(writer, input)); writer.WriteList(tx.Outputs, output => EncodeTxOutput(writer, output)); writer.WriteUInt32(tx.LockTime); }
//TODO only used by tests public BlockTx(int txIndex, Transaction tx) : this(txIndex, 0, tx.Hash, false, tx) { }
public static void GetTransaction(MainnetBlockProvider blockProvider, int blockIndex, int txIndex, out Block block, out Transaction tx) { block = blockProvider.GetBlock(blockIndex); tx = block.Transactions[txIndex]; }
public bool VerifySignature(byte[] scriptPubKey, Transaction tx, byte[] sig, byte[] pubKey, int inputIndex, out byte hashType, out byte[] txSignature, out byte[] txSignatureHash) { // get the 1-byte hashType off the end of sig hashType = sig[sig.Length - 1]; // get the DER encoded portion of sig, which is everything except the last byte (the last byte being hashType) var sigDER = sig.Take(sig.Length - 1).ToArray(); // get the simplified/signing version of the transaction txSignature = TxSignature(scriptPubKey, tx, inputIndex, hashType); // get the hash of the simplified/signing version of the transaction txSignatureHash = SHA256Static.ComputeDoubleHash(txSignature); if (this.ignoreSignatures) { return true; } else { #if SECP256K1_DLL // verify that signature is valid for pubKey and the simplified/signing transaction's hash return Signatures.Verify(txSignatureHash, sigDER, pubKey) == Signatures.VerifyResult.Verified; #else return true; #endif } }
public BlockTx(int index, int depth, UInt256 hash, bool pruned, Transaction transaction) : base(index, depth, hash, pruned) { Transaction = transaction; }
public static void GetFirstMultiInputTransaction(MainnetBlockProvider blockProvider, out Block block, out Transaction tx, out IDictionary<UInt256, Transaction> txLookup) { txLookup = new Dictionary<UInt256, Transaction>(); // prior outputs for first transaction GetTransaction(blockProvider, 360, 0, out block, out tx); txLookup.Add(tx.Hash, tx); GetTransaction(blockProvider, 187, 1, out block, out tx); txLookup.Add(tx.Hash, tx); GetTransaction(blockProvider, 248, 1, out block, out tx); txLookup.Add(tx.Hash, tx); // first transaction // do this last so its output is what is returned GetTransaction(blockProvider, 496, 1, out block, out tx); txLookup.Add(tx.Hash, tx); }
public bool TryGetTransaction(UInt256 blockHash, int txIndex, out Transaction transaction) { ImmutableSortedDictionary<int, BlockTx> blockTxes; BlockTx blockTx; if (this.allBlockTxes.TryGetValue(blockHash, out blockTxes) && blockTxes.TryGetValue(txIndex, out blockTx)) { transaction = blockTx.Transaction; return true; } else { transaction = default(Transaction); return false; } }
public bool TryGetTransaction(UInt256 blockHash, int txIndex, out Transaction transaction) { return GetStorage(blockHash).TryGetTransaction(blockHash, txIndex, out transaction); }
private void TestTransactionVerifyScript(Transaction tx, IDictionary<UInt256, Transaction> txLookup) { var scriptEngine = new ScriptEngine(); for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; var prevOutput = txLookup[input.PreviousTxOutputKey.TxHash].Outputs[input.PreviousTxOutputKey.TxOutputIndex.ToIntChecked()]; var script = GetScriptFromInputPrevOutput(input, prevOutput); var result = scriptEngine.VerifyScript(UInt256.Zero /*blockHash*/, -1 /*txIndex*/, prevOutput.ScriptPublicKey.ToArray(), tx, inputIndex, script); Assert.IsTrue(result); } }
private bool ExecuteOps(byte[] scriptPubKey, Transaction tx, int inputIndex, byte[] script, out Stack stack, out Stack altStack) { stack = new Stack(); altStack = new Stack(); using (var scriptStream = new MemoryStream(script)) using (var opReader = new BinaryReader(scriptStream)) { while (opReader.BaseStream.Position < script.Length) { var opByte = opReader.ReadByte(); var op = (ScriptOp)Enum.ToObject(typeof(ScriptOp), opByte); if (logger.IsTraceEnabled) logger.Trace("Executing {0} with stack count: {1}", OpName(opByte), stack.Count); switch (op) { // Constants case ScriptOp.OP_PUSHDATA1: { if (opReader.BaseStream.Position + 1 >= script.Length) return false; var length = opReader.ReadByte(); stack.PushBytes(opReader.ReadBytes(length)); } break; case ScriptOp.OP_PUSHDATA2: { if (opReader.BaseStream.Position + 2 >= script.Length) return false; var length = opReader.ReadUInt16(); stack.PushBytes(opReader.ReadBytes(length)); } break; case ScriptOp.OP_PUSHDATA4: { if (opReader.BaseStream.Position + 4 >= script.Length) return false; var length = opReader.ReadUInt32(); stack.PushBytes(opReader.ReadBytes(length.ToIntChecked())); } break; // Flow control case ScriptOp.OP_NOP: { } break; // Stack case ScriptOp.OP_DROP: { if (stack.Count < 1) return false; var value = stack.PopBytes(); if (logger.IsTraceEnabled) logger.Trace("{0} dropped {1}", OpName(opByte), value); } break; case ScriptOp.OP_DUP: { if (stack.Count < 1) return false; var value = stack.PeekBytes(); stack.PushBytes(value); if (logger.IsTraceEnabled) logger.Trace("{0} duplicated {2}", OpName(opByte), value); } break; // Splice // Bitwise logic case ScriptOp.OP_EQUAL: case ScriptOp.OP_EQUALVERIFY: { if (stack.Count < 2) return false; var value1 = stack.PopBytes(); var value2 = stack.PopBytes(); var result = value1.SequenceEqual(value2); stack.PushBool(result); if (logger.IsTraceEnabled) logger.Trace( @"{0} compared values: value1: {1} value2: {2} result: {3}", OpName(opByte), value1, value2, result); if (op == ScriptOp.OP_EQUALVERIFY) { if (result) stack.PopBool(); else return false; } } break; // Arithmetic // Note: Arithmetic inputs are limited to signed 32-bit integers, but may overflow their output. // Crypto case ScriptOp.OP_SHA256: { if (stack.Count < 1) return false; var value = stack.PopBytes().ToArray(); var hash = SHA256Static.ComputeHash(value); stack.PushBytes(hash); if (logger.IsTraceEnabled) logger.Trace( @"{0} hashed value: value: {1} hash: {2}", OpName(opByte), value, hash); } break; case ScriptOp.OP_HASH160: { if (stack.Count < 1) return false; var value = stack.PopBytes().ToArray(); var hash = RIPEMD160Static.ComputeHash(SHA256Static.ComputeHash(value)); stack.PushBytes(hash); if (logger.IsTraceEnabled) logger.Trace( @"{0} hashed value: value: {1} hash: {2}", OpName(opByte), value, hash); } break; case ScriptOp.OP_CHECKSIG: case ScriptOp.OP_CHECKSIGVERIFY: { if (stack.Count < 2) return false; var pubKey = stack.PopBytes().ToArray(); var sig = stack.PopBytes().ToArray(); var startTime = DateTime.UtcNow; byte hashType; byte[] txSignature, txSignatureHash; var result = VerifySignature(scriptPubKey, tx, sig, pubKey, inputIndex, out hashType, out txSignature, out txSignatureHash); stack.PushBool(result); var finishTime = DateTime.UtcNow; if (logger.IsTraceEnabled) logger.Trace( @"{0} executed in {9} ms: tx: {1} inputIndex: {2} pubKey: {3} sig: {4} hashType: {5} txSignature: {6} txSignatureHash: {7} result: {8}", OpName(opByte), new byte[0] /*tx.ToRawBytes()*/, inputIndex, pubKey, sig, hashType, txSignature, txSignatureHash, result, (finishTime - startTime).TotalMilliseconds.ToString("0")); if (op == ScriptOp.OP_CHECKSIGVERIFY) { if (result) stack.PopBool(); else return false; } } break; // Pseudo-words // These words are used internally for assisting with transaction matching. They are invalid if used in actual scripts. // Reserved words // Any opcode not assigned is also reserved. Using an unassigned opcode makes the transaction invalid. default: //OP_PUSHBYTES1-75 if (opByte >= (int)ScriptOp.OP_PUSHBYTES1 && opByte <= (int)ScriptOp.OP_PUSHBYTES75) { stack.PushBytes(opReader.ReadBytes(opByte)); if (logger.IsTraceEnabled) logger.Trace("{0} loaded {1} bytes onto the stack: {2}", OpName(opByte), opByte, stack.PeekBytes()); } // Unknown op else { var message = $"Invalid operation in tx {tx.Hash} input {inputIndex}: {new[] { opByte }.ToHexNumberString()} {OpName(opByte)}"; //logger.Warn(message); throw new Exception(message); } break; } if (logger.IsTraceEnabled) logger.Trace(new string('-', 80)); } } // TODO verify no if/else blocks left over // TODO not entirely sure what default return should be return true; }
private void TestTransactionVerifySignature(byte[] expectedHashTypes, byte[][] expectedSignatures, byte[][] expectedSignatureHashes, Transaction tx, IDictionary<UInt256, Transaction> txLookup) { var scriptEngine = new ScriptEngine(); for (var inputIndex = 0; inputIndex < tx.Inputs.Length; inputIndex++) { var input = tx.Inputs[inputIndex]; var prevOutput = txLookup[input.PreviousTxOutputKey.TxHash].Outputs[input.PreviousTxOutputKey.TxOutputIndex.ToIntChecked()]; var scriptSigBytes = input.ScriptSignature.ToArray(); var hashType = GetHashTypeFromScriptSig(scriptSigBytes); var sig = GetSigFromScriptSig(scriptSigBytes); var pubKey = GetPubKeyFromScripts(scriptSigBytes, prevOutput.ScriptPublicKey.ToArray()); byte[] txSignature, txSignatureHash; var result = scriptEngine.VerifySignature(prevOutput.ScriptPublicKey.ToArray(), tx, sig.ToArray(), pubKey.ToArray(), inputIndex, out hashType, out txSignature, out txSignatureHash); Assert.AreEqual(expectedHashTypes[inputIndex], hashType); CollectionAssert.AreEqual(expectedSignatures[inputIndex].ToList(), txSignature.ToList()); CollectionAssert.AreEqual(expectedSignatureHashes[inputIndex].ToList(), txSignatureHash.ToList()); Assert.IsTrue(result); } }
public static void GetFirstHash160Transaction(MainnetBlockProvider blockProvider, out Block block, out Transaction tx, out IDictionary<UInt256, Transaction> txLookup) { txLookup = new Dictionary<UInt256, Transaction>(); // prior outputs for first OP_HASH160 transaction GetTransaction(blockProvider, 2676, 0, out block, out tx); txLookup.Add(tx.Hash, tx); GetTransaction(blockProvider, 2812, 1, out block, out tx); txLookup.Add(tx.Hash, tx); // first OP_HASH160 transaction // do this last so its output is what is returned GetTransaction(blockProvider, 2812, 2, out block, out tx); txLookup.Add(tx.Hash, tx); }
public bool TryGetTransaction(UInt256 blockHash, int txIndex, out Transaction transaction) { using (var txn = this.jetInstance.BeginTransaction(TransactionBeginFlags.ReadOnly)) { byte[] blockTxBytes; if (txn.TryGet(blocksTableId, DbEncoder.EncodeBlockHashTxIndex(blockHash, txIndex), out blockTxBytes)) { var blockTx = DataEncoder.DecodeBlockTx(blockTxBytes); transaction = blockTx.Transaction; return transaction != null; } else { transaction = default(Transaction); return false; } } }
/// <summary> /// Initializes a new instance of <see cref="LoadedTx"/> with the specified transaction and each input's previous transaction. /// </summary> /// <param name="transaction">The transaction.</param> /// <param name="txIndex">The index of the transaction.</param> /// <param name="inputTxes">The array of transactions corresponding to each input's previous transaction.</param> public LoadedTx(Transaction transaction, int txIndex, ImmutableArray<Transaction> inputTxes) { Transaction = transaction; TxIndex = txIndex; InputTxes = inputTxes; }
public EncodedTx(ImmutableArray<byte> txBytes, Transaction transaction) { Hash = transaction.Hash; TxBytes = txBytes; lazyTx = new Lazy<Transaction>(() => transaction).Force(); }
public DecodedTx CreateSpendTransaction(Transaction prevTx, int prevInputIndex, byte hashType, UInt64 value, ECPrivateKeyParameters fromPrivateKey, ECPublicKeyParameters fromPublicKey, ECPublicKeyParameters toPublicKey) { var tx = Transaction.Create ( version: 1, inputs: ImmutableArray.Create ( new TxInput ( prevTxHash: prevTx.Hash, prevTxOutputIndex: (UInt32)prevInputIndex, scriptSignature: ImmutableArray.Create<byte>(), sequence: 0 ) ), outputs: ImmutableArray.Create ( new TxOutput ( value: value, scriptPublicKey: CreatePublicKeyScript(toPublicKey).ToImmutableArray() ) ), lockTime: 0 ); // sign the transaction var scriptSignature = CreatePrivateKeyScript(tx.Transaction, 0, hashType, fromPrivateKey, fromPublicKey).ToImmutableArray(); // add the signature script to the transaction tx = tx.Transaction.CreateWith(Inputs: ImmutableArray.Create(tx.Transaction.Inputs[0].With(scriptSignature: scriptSignature))); return tx; }