// Stratis kernel protocol // coinstake must meet hash target according to the protocol: // kernel (input 0) must meet the formula // hash(nStakeModifier + txPrev.block.nTime + txPrev.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight // this ensures that the chance of getting a coinstake is proportional to the // amount of coins one owns. // The reason this hash is chosen is the following: // nStakeModifier: scrambles computation to make it very difficult to precompute // future proof-of-stake // txPrev.block.nTime: prevent nodes from guessing a good timestamp to // generate transaction for future advantage, // obsolete since v3 // txPrev.nTime: slightly scrambles computation // txPrev.vout.hash: hash of txPrev, to reduce the chance of nodes // generating coinstake at the same time // txPrev.vout.n: output number of txPrev, to reduce the chance of nodes // generating coinstake at the same time // nTime: current timestamp // block/tx hash should not be used here as they can be generated in vast // quantities so as to generate blocks faster, degrading the system back into // a proof-of-work situation. // private static bool CheckStakeKernelHashV2(ChainedBlock pindexPrev, uint nBits, uint nTimeBlockFrom, Transaction txPrev, OutPoint prevout, uint nTimeTx, out uint256 hashProofOfStake, out uint256 targetProofOfStake, bool fPrintProofOfStake) { targetProofOfStake = null; hashProofOfStake = null; if (nTimeTx < txPrev.Time) // Transaction timestamp violation { return(false); //error("CheckStakeKernelHash() : nTime violation"); } // Base target var bnTarget = new Target(nBits).ToBigInteger(); // Weighted target var nValueIn = txPrev.Outputs[prevout.N].Value.Satoshi; var bnWeight = BigInteger.ValueOf(nValueIn); bnTarget = bnTarget.Multiply(bnWeight); // todo: investigate this issue, is the convertion to uint256 similar to the c++ implementation //targetProofOfStake = Target.ToUInt256(bnTarget); var nStakeModifier = pindexPrev.Header.PosParameters.StakeModifier; uint256 bnStakeModifierV2 = pindexPrev.Header.PosParameters.StakeModifierV2; int nStakeModifierHeight = pindexPrev.Height; var nStakeModifierTime = pindexPrev.Header.Time; // Calculate hash using (var ms = new MemoryStream()) { var serializer = new BitcoinStream(ms, true); if (IsProtocolV3((int)nTimeTx)) { serializer.ReadWrite(bnStakeModifierV2); } else { serializer.ReadWrite(nStakeModifier); serializer.ReadWrite(nTimeBlockFrom); } serializer.ReadWrite(txPrev.Time); serializer.ReadWrite(prevout.Hash); serializer.ReadWrite(prevout.N); serializer.ReadWrite(nTimeTx); hashProofOfStake = Hashes.Hash256(ms.ToArray()); } if (fPrintProofOfStake) { //LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n", // nStakeModifier, nStakeModifierHeight, // DateTimeStrFormat(nStakeModifierTime), // DateTimeStrFormat(nTimeBlockFrom)); //LogPrintf("CheckStakeKernelHash() : check modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n", // nStakeModifier, // nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx, // hashProofOfStake.ToString()); } // Now check if proof-of-stake hash meets target protocol var hashProofOfStakeTarget = new BigInteger(hashProofOfStake.ToBytes(false)); if (hashProofOfStakeTarget.CompareTo(bnTarget) > 0) { return(false); } // if (fDebug && !fPrintProofOfStake) // { // LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n", // nStakeModifier, nStakeModifierHeight, // DateTimeStrFormat(nStakeModifierTime), // DateTimeStrFormat(nTimeBlockFrom)); // LogPrintf("CheckStakeKernelHash() : pass modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n", // nStakeModifier, // nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx, // hashProofOfStake.ToString()); // } return(true); }
//https://en.bitcoin.it/wiki/OP_CHECKSIG public static uint256 SignatureHash(Script scriptCode, Transaction txTo, int nIn, SigHash nHashType, Money amount, HashVersion sigversion, PrecomputedTransactionData precomputedTransactionData) { if (sigversion == HashVersion.Witness) { if (amount == null) { throw new ArgumentException("The amount of the output being signed must be provided", "amount"); } uint256 hashPrevouts = uint256.Zero; uint256 hashSequence = uint256.Zero; uint256 hashOutputs = uint256.Zero; if ((nHashType & SigHash.AnyoneCanPay) == 0) { hashPrevouts = precomputedTransactionData == null? GetHashPrevouts(txTo) : precomputedTransactionData.HashPrevouts; } if ((nHashType & SigHash.AnyoneCanPay) == 0 && ((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None) { hashSequence = precomputedTransactionData == null? GetHashSequence(txTo) : precomputedTransactionData.HashSequence; } if (((uint)nHashType & 0x1f) != (uint)SigHash.Single && ((uint)nHashType & 0x1f) != (uint)SigHash.None) { hashOutputs = precomputedTransactionData == null? GetHashOutputs(txTo) : precomputedTransactionData.HashOutputs; } else if (((uint)nHashType & 0x1f) == (uint)SigHash.Single && nIn < txTo.Outputs.Count) { BitcoinStream ss = CreateHashWriter(sigversion); ss.ReadWrite(txTo.Outputs[nIn]); hashOutputs = GetHash(ss); } BitcoinStream sss = CreateHashWriter(sigversion); // Version sss.ReadWrite(txTo.Version); // Input prevouts/nSequence (none/all, depending on flags) sss.ReadWrite(hashPrevouts); sss.ReadWrite(hashSequence); // The input being signed (replacing the scriptSig with scriptCode + amount) // The prevout may already be contained in hashPrevout, and the nSequence // may already be contain in hashSequence. sss.ReadWrite(txTo.Inputs[nIn].PrevOut); sss.ReadWrite(scriptCode); sss.ReadWrite(amount.Satoshi); sss.ReadWrite((uint)txTo.Inputs[nIn].Sequence); // Outputs (none/one/all, depending on flags) sss.ReadWrite(hashOutputs); // Locktime sss.ReadWriteStruct(txTo.LockTime); // Sighash type sss.ReadWrite((uint)nHashType); return(GetHash(sss)); } if (nIn >= txTo.Inputs.Count) { Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n"); return(uint256.One); } // Check for invalid use of SIGHASH_SINGLE if (nHashType == SigHash.Single) { if (nIn >= txTo.Outputs.Count) { Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); return(uint256.One); } } var scriptCopy = new Script(scriptCode._Script); scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR); var txCopy = new Transaction(txTo.ToBytes()); //Set all TxIn script to empty string foreach (var txin in txCopy.Inputs) { txin.ScriptSig = new Script(); } //Copy subscript into the txin script you are checking txCopy.Inputs[nIn].ScriptSig = scriptCopy; var hashType = nHashType & (SigHash)31; if (hashType == SigHash.None) { //The output of txCopy is set to a vector of zero size. txCopy.Outputs.Clear(); //All other inputs aside from the current input in txCopy have their nSequence index set to zero foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } else if (hashType == SigHash.Single) { //The output of txCopy is resized to the size of the current input index+1. txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1)); //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1. for (var i = 0; i < txCopy.Outputs.Count; i++) { if (i == nIn) { continue; } txCopy.Outputs[i] = new TxOut(); } //All other txCopy inputs aside from the current input are set to have an nSequence index of zero. foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } if ((nHashType & SigHash.AnyoneCanPay) != 0) { //The txCopy input vector is resized to a length of one. var script = txCopy.Inputs[nIn]; txCopy.Inputs.Clear(); txCopy.Inputs.Add(script); //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector. txCopy.Inputs[0].ScriptSig = scriptCopy; } //Serialize TxCopy, append 4 byte hashtypecode var stream = CreateHashWriter(sigversion); txCopy.ReadWrite(stream); stream.ReadWrite((uint)nHashType); return(GetHash(stream)); }
internal byte[] ReadData(Stream stream) { uint len = 0; var bitStream = new BitcoinStream(stream, false); if (this.Code == 0) { return(new byte[0]); } if ((byte)OpcodeType.OP_1 <= (byte)this.Code && (byte)this.Code <= (byte)OpcodeType.OP_16) { return(new byte[] { (byte)(this.Code - OpcodeType.OP_1 + 1) }); } if (this.Code == OpcodeType.OP_1NEGATE) { return(new byte[] { 0x81 }); } try { if (0x01 <= (byte)this.Code && (byte)this.Code <= 0x4b) { len = (uint)this.Code; } else if (this.Code == OpcodeType.OP_PUSHDATA1) { len = bitStream.ReadWrite((byte)0); } else if (this.Code == OpcodeType.OP_PUSHDATA2) { len = bitStream.ReadWrite((ushort)0); } else if (this.Code == OpcodeType.OP_PUSHDATA4) { len = bitStream.ReadWrite((uint)0); } else { this.IsInvalid = true; return(new byte[0]); } byte[] data = null; if (len <= MAX_SCRIPT_ELEMENT_SIZE) //Most of the time { data = new byte[len]; int readen = stream.Read(data, 0, data.Length); if (readen != data.Length) { this.IsInvalid = true; return(new byte[0]); } } else //Mitigate against a big array allocation { var bytes = new List <byte>(); for (int i = 0; i < len; i++) { int b = stream.ReadByte(); if (b < 0) { this.IsInvalid = true; return(new byte[0]); } bytes.Add((byte)b); } data = bytes.ToArray(); } return(data); } catch (EndOfStreamException) { this.IsInvalid = true; return(new byte[0]); } }
//https://en.bitcoin.it/wiki/OP_CHECKSIG public uint256 SignatureHash(Transaction txTo, int nIn, SigHash nHashType) { if (nIn >= txTo.Inputs.Count) { Utils.log("ERROR: SignatureHash() : nIn=" + nIn + " out of range\n"); return(uint256.One); } // Check for invalid use of SIGHASH_SINGLE if (nHashType == SigHash.Single) { if (nIn >= txTo.Outputs.Count) { Utils.log("ERROR: SignatureHash() : nOut=" + nIn + " out of range\n"); return(uint256.One); } } var scriptCopy = new Script(_Script); scriptCopy.FindAndDelete(OpcodeType.OP_CODESEPARATOR); var txCopy = new Transaction(txTo.ToBytes()); //Set all TxIn script to empty string foreach (var txin in txCopy.Inputs) { txin.ScriptSig = new Script(); } //Copy subscript into the txin script you are checking txCopy.Inputs[nIn].ScriptSig = scriptCopy; var hashType = nHashType & (SigHash)31; if (hashType == SigHash.None) { //The output of txCopy is set to a vector of zero size. txCopy.Outputs.Clear(); //All other inputs aside from the current input in txCopy have their nSequence index set to zero foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } else if (hashType == SigHash.Single) { //The output of txCopy is resized to the size of the current input index+1. txCopy.Outputs.RemoveRange(nIn + 1, txCopy.Outputs.Count - (nIn + 1)); //All other txCopy outputs aside from the output that is the same as the current input index are set to a blank script and a value of (long) -1. for (var i = 0; i < txCopy.Outputs.Count; i++) { if (i == nIn) { continue; } txCopy.Outputs[i] = new TxOut(); } //All other txCopy inputs aside from the current input are set to have an nSequence index of zero. foreach (var input in txCopy.Inputs.Where((x, i) => i != nIn)) { input.Sequence = 0; } } if ((nHashType & SigHash.AnyoneCanPay) != 0) { //The txCopy input vector is resized to a length of one. var script = txCopy.Inputs[nIn]; txCopy.Inputs.Clear(); txCopy.Inputs.Add(script); //The subScript (lead in by its length as a var-integer encoded!) is set as the first and only member of this vector. txCopy.Inputs[0].ScriptSig = scriptCopy; } //Serialize TxCopy, append 4 byte hashtypecode var ms = new MemoryStream(); var bitcoinStream = new BitcoinStream(ms, true); txCopy.ReadWrite(bitcoinStream); bitcoinStream.ReadWrite((uint)nHashType); var hashed = ms.ToArray(); return(Hashes.Hash256(hashed)); }
public override void ReadWrite(BitcoinStream stream) { bool witSupported = (((uint)stream.TransactionOptions & (uint)TransactionOptions.Witness) != 0) && stream.ProtocolVersion >= ProtocolVersion.WITNESS_VERSION; byte flags = 0; if (!stream.Serializing) { stream.ReadWrite(ref this.nVersion); // POS time stamp stream.ReadWrite(ref this.nTime); /* Try to read the vin. In case the dummy is there, this will be read as an empty vector. */ stream.ReadWrite <TxInList, TxIn>(ref this.vin); bool hasNoDummy = (this.nVersion & NoDummyInput) != 0 && this.vin.Count == 0; if (witSupported && hasNoDummy) { this.nVersion = this.nVersion & ~NoDummyInput; } if (this.vin.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 this.vin); this.vin.Transaction = this; stream.ReadWrite <TxOutList, TxOut>(ref this.vout); this.vout.Transaction = this; } else { /* Assume read a transaction without output. */ this.vout = new TxOutList(); this.vout.Transaction = this; } } else { /* We read a non-empty vin. Assume a normal vout follows. */ stream.ReadWrite <TxOutList, TxOut>(ref this.vout); this.vout.Transaction = this; } if (((flags & 1) != 0) && witSupported) { /* The witness flag is present, and we support witnesses. */ flags ^= 1; var wit = new Witness(this.Inputs); wit.ReadWrite(stream); } if (flags != 0) { /* Unknown flag in the serialization */ throw new FormatException("Unknown transaction optional data"); } } else { uint version = (witSupported && (this.vin.Count == 0 && this.vout.Count > 0)) ? this.nVersion | NoDummyInput : this.nVersion; stream.ReadWrite(ref version); // the POS time stamp stream.ReadWrite(ref this.nTime); if (witSupported) { /* Check whether witnesses need to be serialized. */ if (this.HasWitness) { flags |= 1; } } if (flags != 0) { /* Use extended format in case witnesses are to be serialized. */ var vinDummy = new TxInList(); stream.ReadWrite <TxInList, TxIn>(ref vinDummy); stream.ReadWrite(ref flags); } stream.ReadWrite <TxInList, TxIn>(ref this.vin); this.vin.Transaction = this; stream.ReadWrite <TxOutList, TxOut>(ref this.vout); this.vout.Transaction = this; if ((flags & 1) != 0) { var wit = new Witness(this.Inputs); wit.ReadWrite(stream); } } stream.ReadWriteStruct(ref this.nLockTime); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref prevout); stream.ReadWrite(ref scriptSig); stream.ReadWrite(ref nSequence); }
//IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref hash); stream.ReadWrite(ref n); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vHave); }
public void Serialize(BitcoinStream stream) { if (stream == null) { throw new ArgumentNullException(nameof(stream)); } // Write the utxo // If there is a non-witness utxo, then don't serialize the witness one. if (witness_utxo != null) { // key stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_WITNESS_UTXO; stream.ReadWrite(ref key); // value var data = witness_utxo.ToBytes(); stream.ReadWriteAsVarString(ref data); } if (non_witness_utxo != null) { // key stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_NON_WITNESS_UTXO; stream.ReadWrite(ref key); // value byte[] data = non_witness_utxo.ToBytes(); stream.ReadWriteAsVarString(ref data); } // Write the sighash type if (sighash_type > 0) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SIGHASH; stream.ReadWrite(ref key); var tmp = Utils.ToBytes((uint)sighash_type, true); stream.ReadWriteAsVarString(ref tmp); } // Write the redeem script if (redeem_script != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_REDEEMSCRIPT; stream.ReadWrite(ref key); var value = redeem_script.ToBytes(); stream.ReadWriteAsVarString(ref value); } // Write the witness script if (witness_script != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_WITNESSSCRIPT; stream.ReadWrite(ref key); var value = witness_script.ToBytes(); stream.ReadWriteAsVarString(ref value); } // Write any partial signatures foreach (var sig_pair in partial_sigs) { var key = new byte[] { PSBTConstants.PSBT_IN_PARTIAL_SIG }.Concat(sig_pair.Key.ToBytes()); stream.ReadWriteAsVarString(ref key); var sig = sig_pair.Value.ToBytes(); stream.ReadWriteAsVarString(ref sig); } // Write any hd keypaths foreach (var pathPair in hd_keypaths) { var key = new byte[] { PSBTConstants.PSBT_IN_BIP32_DERIVATION }.Concat(pathPair.Key.ToBytes()); stream.ReadWriteAsVarString(ref key); var masterFingerPrint = pathPair.Value.MasterFingerprint; var path = pathPair.Value.KeyPath.ToBytes(); var pathInfo = masterFingerPrint.ToBytes().Concat(path); stream.ReadWriteAsVarString(ref pathInfo); } // Write script sig if (final_script_sig != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SCRIPTSIG; stream.ReadWrite(ref key); byte[] value = final_script_sig.ToBytes(); stream.ReadWriteAsVarString(ref value); } // write script witness if (final_script_witness != null) { stream.ReadWriteAsVarInt(ref defaultKeyLen); var key = PSBTConstants.PSBT_IN_SCRIPTWITNESS; stream.ReadWrite(ref key); var stack = final_script_witness.ToBytes(); stream.ReadWriteAsVarString(ref stack); } // Write unknown things foreach (var entry in unknown) { var k = entry.Key; var v = entry.Value; stream.ReadWriteAsVarString(ref k); stream.ReadWriteAsVarString(ref v); } var sep = PSBTConstants.PSBT_SEPARATOR; stream.ReadWrite(ref sep); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref header); stream.ReadWrite(ref _PartialMerkleTree); }
internal static byte[] ReadData(Op op, Stream stream, bool ignoreWrongPush = false) { var opcode = op.Code; uint len = 0; BitcoinStream bitStream = new BitcoinStream(stream, false); if (opcode == 0) { return(new byte[0]); } if ((byte)OpcodeType.OP_1 <= (byte)opcode && (byte)opcode <= (byte)OpcodeType.OP_16) { return(new byte[] { (byte)(opcode - OpcodeType.OP_1 + 1) }); } if (opcode == OpcodeType.OP_1NEGATE) { return(new byte[] { 0x81 }); } try { if (0x01 <= (byte)opcode && (byte)opcode <= 0x4b) { len = (uint)opcode; } else if (opcode == OpcodeType.OP_PUSHDATA1) { len = bitStream.ReadWrite((byte)0); } else if (opcode == OpcodeType.OP_PUSHDATA2) { len = bitStream.ReadWrite((ushort)0); } else if (opcode == OpcodeType.OP_PUSHDATA4) { len = bitStream.ReadWrite((uint)0); } else { throw new FormatException("Invalid opcode for pushing data : " + opcode); } } catch (EndOfStreamException) { if (!ignoreWrongPush) { throw new FormatException("Incomplete script"); } op.IncompleteData = true; return(new byte[0]); } if (stream.CanSeek && stream.Length - stream.Position < len) { len = (uint)(stream.Length - stream.Position); if (!ignoreWrongPush) { throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + len); } op.IncompleteData = true; } byte[] data = new byte[len]; var readen = stream.Read(data, 0, data.Length); if (readen != data.Length && !ignoreWrongPush) { throw new FormatException("Not enough bytes pushed with " + opcode.ToString() + " expected " + len + " but got " + readen); } else if (readen != data.Length) { op.IncompleteData = true; Array.Resize(ref data, readen); } return(data); }
public virtual void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref this.header); stream.ReadWrite(ref this.transactions); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vtxundo); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref vprevout); }
// select a block from the candidate blocks in vSortedByTimestamp, excluding // already selected blocks in vSelectedBlocks, and with timestamp up to // nSelectionIntervalStop. private static bool SelectBlockFromCandidates(ChainedBlock chainIndex, SortedDictionary <uint, uint256> sortedByTimestamp, Dictionary <uint256, ChainedBlock> mapSelectedBlocks, long nSelectionIntervalStop, ulong nStakeModifierPrev, out ChainedBlock pindexSelected) { bool fSelected = false; uint256 hashBest = 0; pindexSelected = null; foreach (var item in sortedByTimestamp) { var pindex = chainIndex.FindAncestorOrSelf(item.Value); if (pindex == null) { return(false); // error("SelectBlockFromCandidates: failed to find block index for candidate block %s", item.second.ToString()); } if (fSelected && pindex.Header.Time > nSelectionIntervalStop) { break; } if (mapSelectedBlocks.Keys.Any(key => key == pindex.HashBlock)) { continue; } // compute the selection hash by hashing its proof-hash and the // previous proof-of-stake modifier uint256 hashSelection; using (var ms = new MemoryStream()) { var serializer = new BitcoinStream(ms, true); serializer.ReadWrite(pindex.Header.PosParameters.HashProof); serializer.ReadWrite(nStakeModifierPrev); hashSelection = Hashes.Hash256(ms.ToArray()); } // the selection hash is divided by 2**32 so that proof-of-stake block // is always favored over proof-of-work block. this is to preserve // the energy efficiency property if (pindex.Header.PosParameters.IsProofOfStake()) { hashSelection >>= 32; } if (fSelected && hashSelection < hashBest) { hashBest = hashSelection; pindexSelected = pindex; } else if (!fSelected) { fSelected = true; hashBest = hashSelection; pindexSelected = pindex; } } //LogPrint("stakemodifier", "SelectBlockFromCandidates: selection hash=%s\n", hashBest.ToString()); return(fSelected); }
public void ReadWrite(BitcoinStream s) { s.ReadWrite(ref this.federationId); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref header); stream.ReadWrite(ref vtx); }
public void ReadWrite(BitcoinStream stream) { if (stream.Serializing) { uint nMaskSize = 0, nMaskCode = 0; CalcMaskSize(ref nMaskSize, ref nMaskCode); bool fFirst = vout.Count > 0 && !vout[0].IsNull; bool fSecond = vout.Count > 1 && !vout[1].IsNull; uint nCode = unchecked ((uint)(8 * (nMaskCode - (fFirst || fSecond ? 0 : 1)) + (fCoinBase ? 1 : 0) + (fFirst ? 2 : 0) + (fSecond ? 4 : 0))); // version stream.ReadWriteAsVarInt(ref nVersion); // size of header code stream.ReadWriteAsVarInt(ref nCode); // spentness bitmask for (uint b = 0; b < nMaskSize; b++) { byte chAvail = 0; for (uint i = 0; i < 8 && 2 + b * 8 + i < vout.Count; i++) { if (!vout[2 + (int)b * 8 + (int)i].IsNull) { chAvail |= (byte)(1 << (int)i); } } stream.ReadWrite(ref chAvail); } // txouts themself for (uint i = 0; i < vout.Count; i++) { if (!vout[(int)i].IsNull) { var compressedTx = new TxOutCompressor(vout[(int)i]); stream.ReadWrite(ref compressedTx); } } // coinbase height stream.ReadWriteAsVarInt(ref nHeight); } else { uint nCode = 0; // version stream.ReadWriteAsVarInt(ref nVersion); //// header code stream.ReadWriteAsVarInt(ref nCode); fCoinBase = (nCode & 1) != 0; List <bool> vAvail = new List <bool>() { false, false }; vAvail[0] = (nCode & 2) != 0; vAvail[1] = (nCode & 4) != 0; uint nMaskCode = unchecked ((uint)((nCode / 8) + ((nCode & 6) != 0 ? 0 : 1))); //// spentness bitmask while (nMaskCode > 0) { byte chAvail = 0; stream.ReadWrite(ref chAvail); for (uint p = 0; p < 8; p++) { bool f = (chAvail & (1 << (int)p)) != 0; vAvail.Add(f); } if (chAvail != 0) { nMaskCode--; } } // txouts themself vout = Enumerable.Range(0, vAvail.Count).Select(_ => new TxOut()).ToList(); for (uint i = 0; i < vAvail.Count; i++) { if (vAvail[(int)i]) { TxOutCompressor compressed = new TxOutCompressor(); stream.ReadWrite(ref compressed); vout[(int)i] = compressed.TxOut; } } //// coinbase height stream.ReadWriteAsVarInt(ref nHeight); Cleanup(); UpdateValue(); } }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref value); stream.ReadWrite(ref publicKey); _MoneyValue = null; //Might been updated }
/// <inheritdoc /> public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref _headers); stream.ReadWrite(ref _graph); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref _value); }
public void ReadWrite(BitcoinStream stream) { stream.ReadWrite(ref this.blocks); }