コード例 #1
0
        /// <exception cref="BitCoinSharp.ProtocolException" />
        protected override void Parse()
        {
            _version = ReadUint32();
            // First come the inputs.
            var numInputs = ReadVarInt();

            _inputs = new List <TransactionInput>((int)numInputs);
            for (var i = 0UL; i < numInputs; i++)
            {
                var input = new TransactionInput(Params, this, Bytes, Cursor);
                _inputs.Add(input);
                Cursor += input.MessageSize;
            }
            // Now the outputs
            var numOutputs = ReadVarInt();

            _outputs = new List <TransactionOutput>((int)numOutputs);
            for (var i = 0UL; i < numOutputs; i++)
            {
                var output = new TransactionOutput(Params, this, Bytes, Cursor);
                _outputs.Add(output);
                Cursor += output.MessageSize;
            }
            _lockTime = ReadUint32();

            // Store a hash, it may come in useful later (want to avoid re-serialization costs).
            _hash = new Sha256Hash(Utils.ReverseBytes(Utils.DoubleDigest(Bytes, Offset, Cursor - Offset)));
        }
コード例 #2
0
ファイル: Block.cs プロジェクト: nikserdev/BitcoinSharp
        /// <exception cref="BitCoinSharp.ProtocolException" />
        protected override void Parse()
        {
            _version          = ReadUint32();
            _prevBlockHash    = ReadHash();
            _merkleRoot       = ReadHash();
            _time             = ReadUint32();
            _difficultyTarget = ReadUint32();
            _nonce            = ReadUint32();

            _hash = Utils.ReverseBytes(Utils.DoubleDigest(Bytes, 0, Cursor));

            if (Cursor == Bytes.Length)
            {
                // This message is just a header, it has no transactions.
                return;
            }

            var numTransactions = (int)ReadVarInt();

            Transactions = new List <Transaction>(numTransactions);
            for (var i = 0; i < numTransactions; i++)
            {
                var tx = new Transaction(Params, Bytes, Cursor);
                Transactions.Add(tx);
                Cursor += tx.MessageSize;
            }
        }
コード例 #3
0
        /// <summary>
        /// Writes message to to the output stream.
        /// </summary>
        /// <exception cref="System.IO.IOException" />
        public void Serialize(Message message, Stream @out)
        {
            string name;

            if (!_names.TryGetValue(message.GetType(), out name))
            {
                throw new Exception("BitcoinSerializer doesn't currently know how to serialize " + message.GetType());
            }

            var header = new byte[4 + _commandLen + 4 + (_usesChecksumming ? 4 : 0)];

            Utils.Uint32ToByteArrayBe(_params.PacketMagic, header, 0);

            // The header array is initialized to zero so we don't have to worry about
            // NULL terminating the string here.
            for (var i = 0; i < name.Length && i < _commandLen; i++)
            {
                header[4 + i] = (byte)name[i];
            }

            var payload = message.BitcoinSerialize();

            Utils.Uint32ToByteArrayLe((uint)payload.Length, header, 4 + _commandLen);

            if (_usesChecksumming)
            {
                var hash = Utils.DoubleDigest(payload);
                Array.Copy(hash, 0, header, 4 + _commandLen + 4, 4);
            }

            @out.Write(header);
            @out.Write(payload);

            _log.DebugFormat("Sending {0} message: {1}", name, Utils.BytesToHexString(header) + Utils.BytesToHexString(payload));
        }
コード例 #4
0
ファイル: Block.cs プロジェクト: nikserdev/BitcoinSharp
 /// <summary>
 /// Calculates the block hash by serializing the block and hashing the resulting bytes.
 /// </summary>
 private byte[] CalculateHash()
 {
     using (var bos = new MemoryStream())
     {
         WriteHeader(bos);
         return(Utils.ReverseBytes(Utils.DoubleDigest(bos.ToArray())));
     }
 }
コード例 #5
0
        public override string ToString()
        {
            // A stringified address is:
            //   1 byte version + 20 bytes hash + 4 bytes check code (itself a truncated hash)
            var addressBytes = new byte[1 + 20 + 4];

            addressBytes[0] = (byte)Version;
            Array.Copy(Bytes, 0, addressBytes, 1, 20);
            var check = Utils.DoubleDigest(addressBytes, 0, 21);

            Array.Copy(check, 0, addressBytes, 21, 4);
            return(Base58.Encode(addressBytes));
        }
コード例 #6
0
        public override string ToString()
        {
            // A stringified buffer is:
            //   1 byte version + data bytes hash + 4 bytes check code (itself a truncated hash)
            var addressBytes = new byte[1 + Bytes.Length + 4];

            addressBytes[0] = (byte)Version;
            Array.Copy(Bytes, 0, addressBytes, 1, Bytes.Length);
            var check = Utils.DoubleDigest(addressBytes, 0, Bytes.Length + 1);

            Array.Copy(check, 0, addressBytes, Bytes.Length + 1, 4);
            return(Base58.Encode(addressBytes));
        }
コード例 #7
0
ファイル: Transaction.cs プロジェクト: mavrol/bitcoinsharpev
 private byte[] HashTransactionForSignature(SigHash type, bool anyoneCanPay)
 {
     using (var bos = new MemoryStream())
     {
         BitcoinSerializeToStream(bos);
         // We also have to write a hash type.
         var hashType = (uint)type + 1;
         if (anyoneCanPay)
         {
             hashType |= 0x80;
         }
         Utils.Uint32ToByteStreamLe(hashType, bos);
         // Note that this is NOT reversed to ensure it will be signed correctly. If it were to be printed out
         // however then we would expect that it is IS reversed.
         return(Utils.DoubleDigest(bos.ToArray()));
     }
 }
コード例 #8
0
        /// <summary>
        /// Uses the checksum in the last 4 bytes of the decoded data to verify the rest are correct. The checksum is
        /// removed from the returned data.
        /// </summary>
        /// <exception cref="AddressFormatException">If the input is not base 58 or the checksum does not validate.</exception>
        public static byte[] DecodeChecked(string input)
        {
            var tmp = Decode(input);

            if (tmp.Length < 4)
            {
                throw new AddressFormatException("Input too short");
            }
            var checksum = new byte[4];

            Array.Copy(tmp, tmp.Length - 4, checksum, 0, 4);
            var bytes = new byte[tmp.Length - 4];

            Array.Copy(tmp, 0, bytes, 0, tmp.Length - 4);
            tmp = Utils.DoubleDigest(bytes);
            var hash = new byte[4];

            Array.Copy(tmp, 0, hash, 0, 4);
            if (!hash.SequenceEqual(checksum))
            {
                throw new AddressFormatException("Checksum does not validate");
            }
            return(bytes);
        }
コード例 #9
0
        /// <summary>
        /// Reads a message from the given InputStream and returns it.
        /// </summary>
        /// <exception cref="BitCoinSharp.ProtocolException" />
        /// <exception cref="System.IO.IOException" />
        public Message Deserialize(Stream @in)
        {
            // A BitCoin protocol message has the following format.
            //
            //   - 4 byte magic number: 0xfabfb5da for the testnet or
            //                          0xf9beb4d9 for production
            //   - 12 byte command in ASCII
            //   - 4 byte payload size
            //   - 4 byte checksum
            //   - Payload data
            //
            // The checksum is the first 4 bytes of a SHA256 hash of the message payload. It isn't
            // present for all messages, notably, the first one on a connection.
            //
            // Satoshi's implementation ignores garbage before the magic header bytes. We have to do the same because
            // sometimes it sends us stuff that isn't part of any message.
            SeekPastMagicBytes(@in);
            // Now read in the header.
            var header     = new byte[_commandLen + 4 + (_usesChecksumming ? 4 : 0)];
            var readCursor = 0;

            while (readCursor < header.Length)
            {
                var bytesRead = @in.Read(header, readCursor, header.Length - readCursor);
                if (bytesRead == -1)
                {
                    // There's no more data to read.
                    throw new IOException("Socket is disconnected");
                }
                readCursor += bytesRead;
            }

            var cursor = 0;

            // The command is a NULL terminated string, unless the command fills all twelve bytes
            // in which case the termination is implicit.
            var mark = cursor;

            for (; header[cursor] != 0 && cursor - mark < _commandLen; cursor++)
            {
            }
            var commandBytes = new byte[cursor - mark];

            Array.Copy(header, mark, commandBytes, 0, cursor - mark);
            var command = Encoding.UTF8.GetString(commandBytes);

            cursor = mark + _commandLen;

            var size = Utils.ReadUint32(header, cursor);

            cursor += 4;

            if (size > Message.MaxSize)
            {
                throw new ProtocolException("Message size too large: " + size);
            }

            // Old clients don't send the checksum.
            var checksum = new byte[4];

            if (_usesChecksumming)
            {
                // Note that the size read above includes the checksum bytes.
                Array.Copy(header, cursor, checksum, 0, 4);
            }

            // Now try to read the whole message.
            readCursor = 0;
            var payloadBytes = new byte[size];

            while (readCursor < payloadBytes.Length - 1)
            {
                var bytesRead = @in.Read(payloadBytes, readCursor, (int)(size - readCursor));
                if (bytesRead == -1)
                {
                    throw new IOException("Socket is disconnected");
                }
                readCursor += bytesRead;
            }

            // Verify the checksum.
            if (_usesChecksumming)
            {
                var hash = Utils.DoubleDigest(payloadBytes);
                if (checksum[0] != hash[0] || checksum[1] != hash[1] ||
                    checksum[2] != hash[2] || checksum[3] != hash[3])
                {
                    throw new ProtocolException("Checksum failed to verify, actual " +
                                                Utils.BytesToHexString(hash) +
                                                " vs " + Utils.BytesToHexString(checksum));
                }
            }

            if (_log.IsDebugEnabled)
            {
                _log.DebugFormat("Received {0} byte '{1}' message: {2}",
                                 size,
                                 command,
                                 Utils.BytesToHexString(payloadBytes)
                                 );
            }

            try
            {
                Func <NetworkParameters, byte[], Message> c;
                if (!_messageConstructors.TryGetValue(command, out c))
                {
                    throw new ProtocolException("No support for deserializing message with name " + command);
                }
                return(c.Invoke(_params, payloadBytes));
            }
            catch (Exception e)
            {
                throw new ProtocolException("Error deserializing message " + Utils.BytesToHexString(payloadBytes) + Environment.NewLine + e.Message, e);
            }
        }