public byte[] TxSignature(ImmutableArray <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 = new 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 : empty); newInputs[i] = 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.ToImmutableArray()); // return wire-encoded simplified transaction with the 4-byte hashType tacked onto the end var stream = new MemoryStream(); using (var writer = new BinaryWriter(stream)) { writer.WriteBytes(DataCalculator.EncodeTransaction(newTx)); writer.Write4Bytes(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()); }