public static string CreateNewRawTx(BitcoinTransaction btx) { StringBuilder rawTx = new StringBuilder(); // 1) 4 byte - version // *Now CompactSize UInt32 version = btx.Version; rawTx.Append(MakeCompactSize(version)); // 2) ? byte - tx_in count (compactSize uint) rawTx.Append(MakeCompactSize(btx.TxInCount)); for (UInt64 i = 0; i < btx.TxInCount; i++) { // 3) 32 byte - TX hash (reverse) string txToSend = btx.TxInList[i].TxId; rawTx.Append(ReverseTx(txToSend)); // 4) 4 byte - output Index // *Now CompactSize rawTx.Append(MakeCompactSize(btx.TxInList[i].OutIndex)); // 5) ? byte - scriptSig length (compactSize uint) (Maximum value is 10,000 bytes) rawTx.Append(MakeCompactSize((UInt64)btx.TxInList[i].ScriptSigLength)); // 6) ? byte - scriptSig which is filled with scriptPubkey temporarily (20 is half the length of address hash160) rawTx.Append(btx.TxInList[i].ScriptSig); //7) 4 byte - sequence - max is 0xffffffff - can change for RBF transactions UInt32 sequence = UInt32.MaxValue; rawTx.Append(IntToHex(sequence, 4)); } //8) ? byte - tx_out count (compactSize uint) rawTx.Append(MakeCompactSize(btx.TxOutCount)); for (UInt64 i = 0; i < btx.TxOutCount; i++) { //9) 8 byte - amout to transfer rawTx.Append(MakeCompactSize(btx.TxOutList[i].Amount)); //10) ? byte - pk_script length (compactSize uint) rawTx.Append(MakeCompactSize((UInt64)btx.TxOutList[i].PkScriptLength)); //11) ? byte - pk_script rawTx.Append(btx.TxOutList[i].PkScript); } //12) 4 byte - lock time // *Now CompactSize rawTx.Append(MakeCompactSize(btx.LockTime)); return(rawTx.ToString()); }
static List <BitcoinTransaction> Deserialize(string raw, ref int index, UInt64 loopCount) { List <BitcoinTransaction> result = new List <BitcoinTransaction>(); List <int> txSize = new List <int>(); for (UInt64 j = 0; j < loopCount; j++) { BitcoinTransaction btx = new BitcoinTransaction(); int size = index; // 1) 4 byte - version string version = raw.Substring(index, 8); btx.Version = (UInt32)HexToUInt(version); index += 8; // 2) ? byte - tx_in count (CompactSize uint) btx.TxInCount = ReadCompactSize(raw, ref index); // Initialize the array btx.TxInList = new TxIn[btx.TxInCount]; for (UInt64 i = 0; i < btx.TxInCount; i++) { TxIn temp = new TxIn(); // 3) 32 byte - TX hash (reverse) temp.TxId = raw.Substring(index, 64); temp.TxId = ReverseTx(temp.TxId); index += 64; // 4) 4 byte - output Index string outIndex = raw.Substring(index, 8); temp.OutIndex = (UInt32)HexToUInt(outIndex); index += 8; // 5) ? byte - scriptSig length (CompactSize uint) (Maximum value is 10,000 bytes) string scriptSigLength = raw.Substring(index, 2); temp.ScriptSigLength = (int)ReadCompactSize(raw, ref index); // 6) ? byte - scriptSig or a placeholder for unsigned (can be empty too) temp.ScriptSig = raw.Substring(index, temp.ScriptSigLength * 2); index += temp.ScriptSigLength * 2; //7) 4 byte - sequence - max is 0xffffffff - can change for RBF transactions string sequence = raw.Substring(index, 8); temp.Sequence = (UInt32)HexToUInt(sequence); index += 8; btx.TxInList[i] = temp; } //8) ? byte - tx_out count (compactSize uint) btx.TxOutCount = ReadCompactSize(raw, ref index); // Initialize the array btx.TxOutList = new TxOut[btx.TxOutCount]; for (UInt64 i = 0; i < btx.TxOutCount; i++) { TxOut temp = new TxOut(); //9) 8 byte - amout to transfer string amount = raw.Substring(index, 16); temp.Amount = HexToUInt(amount); index += 16; //10) ? byte - pk_script length (compactSize uint) string pkScriptLength = raw.Substring(index, 2); temp.PkScriptLength = (Int32)HexToUInt(pkScriptLength); index += 2; //11) ? byte - pk_script temp.PkScript = raw.Substring(index, temp.PkScriptLength * 2); index += temp.PkScriptLength * 2; btx.TxOutList[i] = temp; } //12) 4 byte - lock time string lockTime = raw.Substring(index, 8); btx.LockTime = (UInt32)HexToUInt(lockTime); index += 8; result.Add(btx); txSize.Add((index - size) / 2); } AverageSize = txSize.Average(); return(result); }