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); }
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; }
private List <string> GetReceiverAddressByOutputs(TxOutList outputs) { var receivers = new List <string>(); foreach (var output in outputs) { if (output.ScriptPubKey != null) { var addr = output.ScriptPubKey.GetDestinationAddress(NetworkOperator.Instance.Network); if (addr != null) { receivers.Add(addr.ToString()); } } } return(receivers.Distinct().ToList()); }
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); }
public ElementsWitness(TxInList inputs, TxOutList outputs) { _Inputs = inputs; _Outputs = outputs; }
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; }
public async Task <IEnumerable <CoinJoinDay> > GetDailyStatsAsync() { Console.WriteLine($"{coinJoinHashes.Length} coinjoins will be analyzed."); var days = new List <CoinJoinDay>(); int processedCoinJoinCount = 0; var allInputs = new HashSet <OutPoint>(); foreach (var batch in coinJoinHashes.Batch(8)) { var txqueries = new List <Task <RawTransactionInfo> >(); foreach (var cjHash in batch) { txqueries.Add(Client.GetRawTransactionInfoWithCacheAsync(cjHash)); } foreach (var query in txqueries) { var txi = await query; if (txi.Confirmations == 0) { continue; } if (!txi.BlockTime.HasValue) { continue; // Idk, shouldn't happen. } var blockTime = txi.BlockTime.Value; var blockTimeDay = new DateTimeOffset(blockTime.Year, blockTime.Month, blockTime.Day, 0, 0, 0, TimeSpan.Zero); var day = days.FirstOrDefault(x => x.BlockTimeDay == blockTimeDay); if (day is null) { day = new CoinJoinDay(blockTimeDay); days.Add(day); } foreach (var input in txi.Transaction.Inputs.Select(x => x.PrevOut)) { allInputs.Add(input); var inputHash = input.Hash; if (IsCoinJoin(inputHash)) { continue; } var inputTxi = await Client.GetRawTransactionInfoWithCacheAsync(inputHash); day.AddNonMixedInputAmount(inputTxi.Transaction.Outputs[input.N].Value); } decimal coinJoinHashesPer100 = coinJoinHashes.Length / 100m; processedCoinJoinCount++; PercentageDone = processedCoinJoinCount / coinJoinHashesPer100; bool displayProgress = (PercentageDone - PreviousPercentageDone) >= 1; if (displayProgress) { Console.WriteLine($"Progress: {(int)PercentageDone}%"); PreviousPercentageDone = PercentageDone; } } } foreach (var cjHash in coinJoinHashes) { // It should be always getting the tx out of memory cache, so shouldn't be a performance issue. var txi = await Client.GetRawTransactionInfoWithCacheAsync(cjHash); if (txi.Confirmations == 0) { continue; } if (!txi.BlockTime.HasValue) { continue; // Idk, shouldn't happen. } var blockTime = txi.BlockTime.Value; var blockTimeDay = new DateTimeOffset(blockTime.Year, blockTime.Month, blockTime.Day, 0, 0, 0, TimeSpan.Zero); var day = days.First(x => x.BlockTimeDay == blockTimeDay); var mixedValues = txi.Transaction.GetIndistinguishableOutputs(includeSingle: false).Select(x => x.value); var mixedValues2AnonTreshold = txi.Transaction.GetIndistinguishableOutputs(includeSingle: false).Where(x => x.count > 2).Select(x => x.value); var mixedValues5AnonTreshold = txi.Transaction.GetIndistinguishableOutputs(includeSingle: false).Where(x => x.count > 5).Select(x => x.value); var mixedValues10AnonTreshold = txi.Transaction.GetIndistinguishableOutputs(includeSingle: false).Where(x => x.count > 10).Select(x => x.value); TxOutList outputs = txi.Transaction.Outputs; for (int i = 0; i < outputs.Count; i++) { var output = outputs[i]; if (mixedValues10AnonTreshold.Contains(output.Value)) { continue; // This is mixed. } var outPoint = new OutPoint(cjHash, i); if (allInputs.Contains(outPoint)) { continue; } var txoutResponse = await Client.GetTxOutAsync(cjHash, i, includeMempool : false); if (txoutResponse is { })
public Transaction SendWallMessage(string sourceTxId, string sourcePublicAddress, string stratPrivateKey, string destinationAddress, double amountTx, double feeTx, byte[] bytesMsg) { // RPC Connection to Stratis Blockchain var rpc = GetRPC(); // Can either use the raw transaction hex from a wallet's getrawtransaction CLI command, or look up the equivalent information via RPC Transaction tx = rpc.GetRawTransaction(uint256.Parse(sourceTxId)); // The destination address will receive 0.0001 STRAT BitcoinAddress destAddress = BitcoinAddress.Create(destinationAddress, Network.StratisMain); // Stratis Source Address - The source address is used to store the 'change' from the transaction - THIS IS THE SIGNATURE for the attestation BitcoinAddress sourceAddress = BitcoinAddress.Create(sourcePublicAddress, Network.StratisMain); // The private key must be the key for the source address to be able to send funds from the source address (String of ~52 ASCII) BitcoinSecret sourcePrivateKey = new BitcoinSecret(stratPrivateKey, Network.StratisMain); int outputIndex = 0; int indexTx = 0; TxOutList listOutTx = tx.Outputs; foreach (var item in listOutTx) { string opCode = item.ScriptPubKey.ToString(); if (opCode.StartsWith("OP_DUP OP_HASH160")) { string sAddress = new Script(opCode).GetDestinationAddress(Network.StratisMain).ToString(); if (sAddress.Equals(sourcePublicAddress)) { outputIndex = indexTx; } } ++indexTx; } // For the fee to be correctly calculated, the quantity of funds in the source transaction needs to be known Money remainingBalance = tx.Outputs[outputIndex].Value; // Now that the source Transaction is obtained, the right output needs to be selected as an input for the new transaction. OutPoint outPoint = new OutPoint(tx, outputIndex); // The source transaction's output (must be unspent) is the input for the new transaction Transaction sendTx = new Transaction(); sendTx.Inputs.Add(new TxIn() { PrevOut = outPoint }); // Can currently only send a maximum of 40 bytes in the null data transaction (bytesMsg) // Also note that a nulldata transaction currently has to have a nonzero value assigned to it. TxOut messageTxOut = new TxOut() { Value = new Money((decimal)0.0001, MoneyUnit.BTC), ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytesMsg) }; // For Attestation amountTx = 0.0001 STRAT is being sent to destAddress TxOut destTxOut = new TxOut() { Value = new Money((decimal)amountTx, MoneyUnit.BTC), ScriptPubKey = destAddress.ScriptPubKey }; double discBalance = feeTx + amountTx + 0.0001; // 0.0001 : nulldata transaction amount // This is what subsequent transactions use to prove ownership of the funds (more specifically, the private key used to create the ScriptPubKey is known) // Send the change back to the originating address. TxOut changeBackTxOut = new TxOut() { Value = new Money(((remainingBalance.ToDecimal(MoneyUnit.BTC) - (decimal)discBalance)), MoneyUnit.BTC), ScriptPubKey = sourceAddress.ScriptPubKey }; // changeBackTxOut = remainingBalance - 0.0001 (sent) - 0.0001 (network fee) - 0.0001 (nulldata) // Transactions without fees may violate consensus rules, or may not be relayed by other nodes on the network. // Add the outputs to the transaction being built sendTx.Outputs.Add(destTxOut); sendTx.Outputs.Add(messageTxOut); sendTx.Outputs.Add(changeBackTxOut); // Signing the transaction sendTx.Inputs[0].ScriptSig = sourceAddress.ScriptPubKey; // Sign the transaction using the specified private key sendTx.Sign(sourcePrivateKey, false); // Broadcast Transaction rpc.SendRawTransactionAsync(sendTx); return(sendTx); }
private static void Main(string[] args) { // create client var client = new QBitNinjaClient(Network.Main); // parse tx id to NBitcoin.uint256 for client var transactionId = uint256.Parse("f13dc48fb035bbf0a6e989a26b3ecb57b84f85e0836e777d6edf60d87a4a2d94"); // query tx GetTransactionResponse transactionResponse = client.GetTransaction(transactionId).Result; // get NBitcoin.Transaction type NBitcoin.Transaction nBitcoinTransaction = transactionResponse.Transaction; var fromTransactionClass = nBitcoinTransaction.GetHash(); var fromGetTransactionResponseClass = transactionResponse.TransactionId; Console.WriteLine(fromTransactionClass == transactionId && fromGetTransactionResponseClass == transactionId); List <ICoin> receivedCoins = transactionResponse.ReceivedCoins; // received coins Console.WriteLine("Begin received coins"); foreach (var coin in receivedCoins) { Money amount = coin.Amount as Money; Console.WriteLine(amount?.ToDecimal(MoneyUnit.BTC)); var paymentScript = coin.TxOut.ScriptPubKey; Console.WriteLine(paymentScript); var address = paymentScript.GetDestinationAddress(Network.Main); Console.WriteLine(address); } // outputs TxOutList outputs = nBitcoinTransaction.Outputs; Console.WriteLine("Begin outputs"); foreach (var output in outputs) { Money amount = output.Value; Console.WriteLine(amount.ToDecimal(MoneyUnit.BTC)); var paymentScript = output.ScriptPubKey; Console.WriteLine(paymentScript); var address = paymentScript.GetDestinationAddress(Network.Main); Console.WriteLine(address); } // inputs TxInList inputs = nBitcoinTransaction.Inputs; Console.WriteLine("Begin inputs"); foreach (var input in inputs) { OutPoint previousOutPoint = input.PrevOut; Console.WriteLine(previousOutPoint); Console.WriteLine(previousOutPoint.Hash); // hash of prev tx Console.WriteLine(previousOutPoint.N); // index of out from prev tx, that has been spent in current tx } // The terms TxOut, Output and out are synonymous. // create a txout with 21 bitcoin from the first ScriptPubKey in our current transaction: Console.WriteLine("Begin txout"); Money twentyBtc = new Money(21, MoneyUnit.BTC); var scriptPubKey = nBitcoinTransaction.Outputs.FirstOrDefault()?.ScriptPubKey; TxOut txOut = new TxOut(twentyBtc, scriptPubKey); Console.WriteLine(txOut.Value.ToDecimal(MoneyUnit.BTC)); Console.WriteLine(txOut.ScriptPubKey); // every TxOut is uniq addressed by at the blockchain level by the id of the tx, including the index // e.g., OutPoint of TxOut is Console.WriteLine("Begin outpoint"); OutPoint firstOutPoint = receivedCoins.FirstOrDefault()?.Outpoint; Console.WriteLine(firstOutPoint?.Hash); Console.WriteLine(firstOutPoint?.N); Console.WriteLine("Begin txin"); // TxIn is composed of the Outpoint of the TxOut being spent and of the ScriptSig (we can see the ScriptSig as the “Proof of Ownership”). // with the previous transaction ID, we can review the info associated with that tx OutPoint firstPreviousOutPoint = nBitcoinTransaction.Inputs.FirstOrDefault()?.PrevOut; if (firstPreviousOutPoint != null) { var firstPreviousTransaction = client.GetTransaction(firstPreviousOutPoint.Hash).Result.Transaction; Console.WriteLine(firstPreviousTransaction.IsCoinBase); } Console.WriteLine("begin coin base hunt"); //TraceCoinBase(nBitcoinTransaction, client); just done as an exercise, do not use Console.WriteLine("begin total output value count"); var spentCoins = transactionResponse.SpentCoins; var spentAmount = spentCoins.Aggregate(Money.Zero, (money, next) => (Money)next.Amount.Add(money)).ToDecimal(MoneyUnit.BTC); Console.WriteLine(spentAmount); var receivedAmount = receivedCoins.Aggregate(Money.Zero, (money, next) => (Money)next.Amount.Add(money)).ToDecimal(MoneyUnit.BTC); Console.WriteLine(receivedAmount); Console.WriteLine(spentAmount - receivedAmount); // fee var fee = nBitcoinTransaction.GetFee(spentCoins.ToArray()).ToDecimal(MoneyUnit.BTC); Console.WriteLine(fee); // note: there are no fee in a coinbase transaction Console.ReadLine(); }