Exemple #1
0
        public void ReadWrite(BitcoinStream stream)
        {
            bool verifyChechksum = false;

            if (stream.Serializing || (!stream.Serializing && !_SkipMagic))
            {
                stream.ReadWrite(ref magic);
            }
            stream.ReadWrite(ref command);
            stream.ReadWrite(ref length);
            if (stream.ProtocolVersion >= ProtocolVersion.MEMPOOL_GD_VERSION)
            {
                stream.ReadWrite(ref checksum);
                verifyChechksum = true;
            }
            if (stream.Serializing)
            {
                stream.ReadWrite(ref payload);
            }
            else
            {
                NodeServerTrace.Trace.TraceEvent(TraceEventType.Verbose, 0, "Message type readen : " + Command);
                if (length > 0x02000000)                //MAX_SIZE 0x02000000 Serialize.h
                {
                    throw new FormatException("Message payload too big ( > 0x02000000 bytes)");
                }
                payload = new byte[length];
                stream.ReadWrite(ref payload);

                if (verifyChechksum)
                {
                    if (!VerifyChecksum())
                    {
                        NodeServerTrace.Trace.TraceEvent(TraceEventType.Verbose, 0, "Invalid message checksum bytes : "
                                                         + Encoders.Hex.EncodeData(this.ToBytes()));
                        throw new FormatException("Message checksum invalid");
                    }
                }
                BitcoinStream payloadStream = new BitcoinStream(payload);
                payloadStream.CopyParameters(stream);

                var payloadType = PayloadAttribute.GetCommandType(Command);
                if (payloadType == typeof(UnknowPayload))
                {
                    NodeServerTrace.Trace.TraceEvent(TraceEventType.Warning, 0, "Unknown command received : " + Command);
                }
                payloadStream.ReadWrite(payloadType, ref _PayloadObject);
                NodeServerTrace.Verbose("Payload : " + _PayloadObject);
            }
        }
Exemple #2
0
        public void ReadWrite(BitcoinStream stream)
        {
            if (Payload == null && stream.Serializing)
            {
                throw new InvalidOperationException("Payload not affected");
            }
            if (stream.Serializing || (!stream.Serializing && !_SkipMagic))
            {
                stream.ReadWrite(ref magic);
            }
            stream.ReadWrite(ref command);
            int  length      = 0;
            uint checksum    = 0;
            bool hasChecksum = false;

            byte[] payloadBytes = stream.Serializing ? GetPayloadBytes(stream.ProtocolVersion, out length) : null;
            length = payloadBytes == null ? 0 : length;
            stream.ReadWrite(ref length);

            if (stream.ProtocolVersion >= ProtocolVersion.MEMPOOL_GD_VERSION)
            {
                if (stream.Serializing)
                {
                    checksum = Hashes.Hash256(payloadBytes, 0, length).GetLow32();
                }
                stream.ReadWrite(ref checksum);
                hasChecksum = true;
            }
            if (stream.Serializing)
            {
                stream.ReadWrite(ref payloadBytes, 0, length);
            }
            else
            {
                if (length > 0x02000000)                //MAX_SIZE 0x02000000 Serialize.h
                {
                    throw new FormatException("Message payload too big ( > 0x02000000 bytes)");
                }

                payloadBytes = _Buffer == null || _Buffer.Length < length ? new byte[length] : _Buffer;
                stream.ReadWrite(ref payloadBytes, 0, length);

                if (hasChecksum)
                {
                    if (!VerifyChecksum(checksum, payloadBytes, length))
                    {
                        if (NodeServerTrace.Trace.Switch.ShouldTrace(TraceEventType.Verbose))
                        {
                            NodeServerTrace.Trace.TraceEvent(TraceEventType.Verbose, 0, "Invalid message checksum bytes");
                        }
                        throw new FormatException("Message checksum invalid");
                    }
                }
                BitcoinStream payloadStream = new BitcoinStream(payloadBytes);
                payloadStream.CopyParameters(stream);

                var payloadType = PayloadAttribute.GetCommandType(Command);
                var unknown     = payloadType == typeof(UnknowPayload);
                if (unknown)
                {
                    NodeServerTrace.Trace.TraceEvent(TraceEventType.Warning, 0, "Unknown command received : " + Command);
                }
                object payload = _PayloadObject;
                payloadStream.ReadWrite(payloadType, ref payload);
                if (unknown)
                {
                    ((UnknowPayload)payload)._Command = Command;
                }
                Payload = (Payload)payload;
            }
        }
Exemple #3
0
        // We use this for big blocks, because the default array pool would allocate a new array. We do not need lot's of bucket such arrays are short lived.
        //readonly static Lazy<ArrayPool<byte>> BigArrayPool = new Lazy<ArrayPool<byte>>(() => ArrayPool<byte>.Create(0x02000000, 5), false);
        //ArrayPool<byte> GetArrayPool(int size) => size < 1_048_576 ? ArrayPool<byte>.Shared : BigArrayPool.Value;

        public void ReadWrite(BitcoinStream stream)
        {
            if (Payload == null && stream.Serializing)
            {
                throw new InvalidOperationException("Payload not affected");
            }
            if (stream.Serializing || (!stream.Serializing && !_SkipMagic))
            {
                stream.ReadWrite(ref magic);
            }

            stream.ReadWrite(ref command);

            if (stream.Serializing)
            {
                // We can optimize by calculating the length at the same time we calculate the checksum
                if (stream.ProtocolCapabilities.SupportCheckSum)
                {
                    var hashStream = stream.ProtocolCapabilities.GetChecksumHashStream();
                    var bsStream   = new BitcoinStream(hashStream, true);
                    bsStream.CopyParameters(stream);
                    Payload.ReadWrite(bsStream);
                    var length   = (int)bsStream.Counter.WrittenBytes;
                    var checksum = hashStream.GetHash().GetLow32();
                    stream.ReadWrite(ref length);
                    stream.ReadWrite(ref checksum);
                }
                else
                {
                    var bitcoinStream = new BitcoinStream(Stream.Null, true);
                    bitcoinStream.CopyParameters(stream);
                    Payload.ReadWrite(bitcoinStream);
                    var length = (int)bitcoinStream.Counter.WrittenBytes;
                    stream.ReadWrite(ref length);
                }
                stream.ReadWrite(Payload);
            }
            else
            {
                int length = 0;
                stream.ReadWrite(ref length);
                if (length < 0 || length > 0x02000000)                 //MAX_SIZE 0x02000000 Serialize.h
                {
                    throw new FormatException("Message payload too big ( > 0x02000000 bytes)");
                }

                //var arrayPool = GetArrayPool(length);
                var payloadBytes = new byte[length];                 // arrayPool.Rent(length);
                try
                {
                    uint expectedChecksum = 0;
                    if (stream.ProtocolCapabilities.SupportCheckSum)
                    {
                        stream.ReadWrite(ref expectedChecksum);
                    }

                    stream.ReadWrite(ref payloadBytes, 0, length);

                    //  We do not verify the checksum anymore because for 1000 blocks, it takes 80 seconds.

                    BitcoinStream payloadStream = new BitcoinStream(new MemoryStream(payloadBytes, 0, length, false), false);
                    payloadStream.CopyParameters(stream);

                    var payloadType = PayloadAttribute.GetCommandType(Command);
                    var unknown     = payloadType == typeof(UnknowPayload);
                    if (unknown)
                    {
                        Logs.NodeServer.LogWarning("Unknown command received {command}", Command);
                    }

                    IBitcoinSerializable payload = null;
                    if (!stream.ConsensusFactory.TryCreateNew(payloadType, out payload))
                    {
                        payload = (IBitcoinSerializable)Activator.CreateInstance(payloadType);
                    }
                    payload.ReadWrite(payloadStream);
                    if (unknown)
                    {
                        ((UnknowPayload)payload)._Command = Command;
                    }
                    Payload = (Payload)payload;
                }
                finally
                {
                    payloadBytes = null;
                    // arrayPool.Return(payloadBytes);
                }
            }
        }