protected virtual byte[] SerializeOutputTransaction(Transaction tx) { var withDefaultWitnessCommitment = !string.IsNullOrEmpty(BlockTemplate.DefaultWitnessCommitment); var outputCount = (uint)tx.Outputs.Count; if (withDefaultWitnessCommitment) { outputCount++; } using (var stream = new MemoryStream()) { var bs = new SonoStream(stream, true); // write output count bs.ReadWriteAsVarInt(ref outputCount); long amount; byte[] raw; uint rawLength; // serialize witness (segwit) if (withDefaultWitnessCommitment) { amount = 0; raw = BlockTemplate.DefaultWitnessCommitment.HexToByteArray(); rawLength = (uint)raw.Length; bs.ReadWrite(ref amount); bs.ReadWriteAsVarInt(ref rawLength); bs.ReadWrite(ref raw); } // serialize outputs foreach (var output in tx.Outputs) { amount = output.Value.Satoshi; var outScript = output.ScriptPubKey; raw = outScript.ToBytes(true); rawLength = (uint)raw.Length; bs.ReadWrite(ref amount); bs.ReadWriteAsVarInt(ref rawLength); bs.ReadWrite(ref raw); } return(stream.ToArray()); } }
protected virtual byte[] SerializeBlock(byte[] header, byte[] coinbase) { var transactionCount = (uint)BlockTemplate.Transactions.Length + 1; // +1 for prepended coinbase tx var rawTransactionBuffer = BuildRawTransactionBuffer(); using (var stream = new MemoryStream()) { var bs = new SonoStream(stream, true); bs.ReadWrite(ref header); bs.ReadWriteAsVarInt(ref transactionCount); bs.ReadWrite(ref coinbase); bs.ReadWrite(ref rawTransactionBuffer); // POS coins require a zero byte appended to block which the daemon replaces with the signature if (isPoS) { bs.ReadWrite((byte)0); } return(stream.ToArray()); } }
protected virtual void BuildCoinbase() { // generate script parts var sigScriptInitial = GenerateScriptSigInitial(); var sigScriptInitialBytes = sigScriptInitial.ToBytes(); var sigScriptLength = (uint)( sigScriptInitial.Length + extraNoncePlaceHolderLength + scriptSigFinalBytes.Length); // output transaction txOut = CreateOutputTransaction(); // build coinbase initial using (var stream = new MemoryStream()) { var bs = new SonoStream(stream, true); // version bs.ReadWrite(ref txVersion); // timestamp for POS coins if (isPoS) { var timestamp = BlockTemplate.CurTime; bs.ReadWrite(ref timestamp); } // serialize (simulated) input transaction bs.ReadWriteAsVarInt(ref txInputCount); bs.ReadWrite(ref sha256Empty); bs.ReadWrite(ref txInPrevOutIndex); // signature script initial part bs.ReadWriteAsVarInt(ref sigScriptLength); bs.ReadWrite(ref sigScriptInitialBytes); // done coinbaseInitial = stream.ToArray(); coinbaseInitialHex = coinbaseInitial.ToHexString(); } // build coinbase final using (var stream = new MemoryStream()) { var bs = new SonoStream(stream, true); // signature script final part bs.ReadWrite(ref scriptSigFinalBytes); // tx in sequence bs.ReadWrite(ref txInSequence); // serialize output transaction var txOutBytes = SerializeOutputTransaction(txOut); bs.ReadWrite(ref txOutBytes); // misc bs.ReadWrite(ref txLockTime); // done coinbaseFinal = stream.ToArray(); coinbaseFinalHex = coinbaseFinal.ToHexString(); } }