/// <summary> /// Logs all non-standard transactions. /// This is useful for detecting which blockfiles/block are likely to contain hidden data. /// </summary> private static void LogNonStdTransactions(string[] files) { var sb = new StringBuilder(); var sb_transactions = new StringBuilder(); string current_file = null; try { int block_height = 0; foreach (var file in files) { current_file = file; foreach (var block in Block.ParseAll(file)) { block.Height = block_height++; Console.WriteLine(string.Format("processing block #{0}", block.Height)); foreach (var transaction in block.Transactions) { foreach (var txout in transaction.Outs) { var text_script = txout.Script.ToString(); if (DataChunkExtractor.Filter(text_script)) { continue; } sb.AppendFormat("block {0} - transaction https://blockchain.info/tx/{1}", block.Height, transaction.TransactionHash); sb.AppendLine(); sb.AppendLine(text_script); sb.AppendLine(); sb_transactions.AppendLine(transaction.TransactionHash.ToString()); } } } var folder = Path.Combine(Path.GetDirectoryName(file), "non-std scripts"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } var newfile = Path.Combine(folder, Path.ChangeExtension(Path.GetFileName(file), "txt")); File.WriteAllText(newfile, sb.ToString()); newfile = Path.ChangeExtension(newfile, ".transactions.txt"); File.WriteAllText(newfile, sb_transactions.ToString()); } } catch (Exception ex) { throw new FormatException($"An error occured reading the file {current_file}. File might be corrupted or contain extra data. This also occurs when reading block files from old version of bitcoin core.", ex); } }
/// <summary> /// Logs all transactions that contains text strings. /// </summary> private static void LogTransactionScriptsTexts(string[] files, string output_file_inputscripts = @"e:\inputs_scripts_as_text.txt", string output_file_outputscripts = @"e:\outputs_scripts_as_text.txt") { string current_file = null; foreach (var file in new[] { output_file_inputscripts, output_file_outputscripts }) { if (File.Exists(file)) { File.Delete(file); } } try { int block_height = 0; foreach (var file in files) { current_file = file; var sb_in = new StringBuilder(); var sb_out = new StringBuilder(); try { foreach (var block in Block.ParseAll(file)) { block.Height = block_height++; Console.WriteLine(string.Format("processing block #{0}", block.Height)); foreach (var transaction in block.Transactions) { foreach (var txin in transaction.Ins) { // input scripts have to be valid, however, there is no doc for how they are formatted // so we do this awful hack of attempting to extract text from it var text = Helper.ExtractText(txin.Script.Raw); if (text == null) { continue; } sb_in.AppendFormat("block ~{0} ({1:yyyy-MM-dd HH:mm:ss}) - https://blockchain.info/tx/{2} - {3}", block.Height, block.Timestamp, transaction.TransactionHash, text); sb_in.AppendLine(); } foreach (var txout in transaction.Outs) { // output scripts are not required to be valid, but any currency going to them will end up lost if they arent // because of this, there are 2 interpretation of every output script: // 1- the script is valid (money is received), meaning the data will be encoded within relevant chunks // 2- the script is invalid (money will be lost), meaning to interpret the script as raw binary data // read the raw binary, convert to text var text = Helper.ExtractText(txout.Script.Raw); if (text != null) { // they always begin with 'v??' here, so remove that sb_out.AppendFormat("block ~{0} ({1:yyyy-MM-dd HH:mm:ss}) - https://blockchain.info/tx/{2} - {3}", block.Height, block.Timestamp, transaction.TransactionHash, text); sb_out.AppendLine(); } var text_script = txout.Script.ToString(); if (DataChunkExtractor.Filter(text_script)) { continue; } // merge all chunks of data, that are hex encoded, into just one chunk var all_chunks = Helper.ExtractScriptChunks(text_script); text = Helper.ExtractText(Helper.HexDecode(all_chunks)); if (text != null) { sb_out.AppendFormat("block ~{0} ({1:yyyy-MM-dd HH:mm:ss}) - https://blockchain.info/tx/{2} - {3}", block.Height, block.Timestamp, transaction.TransactionHash, text); sb_out.AppendLine(); } } } } } finally { File.AppendAllText(output_file_inputscripts, sb_in.ToString(), Encoding.UTF8); File.AppendAllText(output_file_outputscripts, sb_out.ToString(), Encoding.UTF8); } } } catch (Exception ex) { throw new FormatException($"An error occured reading the file {current_file}. File might be corrupted or contain extra data. This also occurs when reading block files from old version of bitcoin core.", ex); } }