Beispiel #1
0
            //public TXInput(
            //  byte[] tXIDOutput,
            //  int outputIndex)
            //{
            //  TXIDOutput = tXIDOutput;
            //  PrimaryKeyTXIDOutput = BitConverter.ToInt32(tXIDOutput, 0);
            //  OutputIndex = outputIndex;
            //}


            public TXInput(byte[] buffer, ref int index)
            {
                TXIDOutput = new byte[HASH_BYTE_SIZE];

                Array.Copy(
                    buffer,
                    index,
                    TXIDOutput,
                    0,
                    HASH_BYTE_SIZE);

                TXIDOutputShort = BitConverter.ToInt32(
                    buffer,
                    index);

                index += HASH_BYTE_SIZE;

                OutputIndex = BitConverter.ToInt32(
                    buffer,
                    index);

                index += 4;

                LengthScript = VarInt.GetInt32(
                    buffer,
                    ref index);

                StartIndexScript = index;

                index += LengthScript;

                index += 4; // sequence
            }
Beispiel #2
0
            List <TX> ParseTXs(
                byte[] hashMerkleRoot)
            {
                List <TX> tXs = new List <TX>();

                int tXCount = VarInt.GetInt32(
                    Buffer,
                    ref IndexBuffer);

                if (tXCount == 0)
                {
                }
                else if (tXCount == 1)
                {
                    TX tX = ParseTX(isCoinbase: true);

                    tXs.Add(tX);

                    if (!tX.Hash.IsEqual(hashMerkleRoot))
                    {
                        throw new ProtocolException(
                                  "Payload merkle root corrupted");
                    }
                }
                else
                {
                    int tXsLengthMod2 = tXCount & 1;
                    var merkleList    = new byte[tXCount + tXsLengthMod2][];

                    TX tX = ParseTX(true);
                    tXs.Add(tX);

                    merkleList[0] = tX.Hash;

                    for (int t = 1; t < tXCount; t += 1)
                    {
                        tX = ParseTX(false);
                        tXs.Add(tX);

                        merkleList[t] = tX.Hash;
                    }

                    if (tXsLengthMod2 != 0)
                    {
                        merkleList[tXCount] = merkleList[tXCount - 1];
                    }

                    if (!GetRoot(merkleList).IsEqual(hashMerkleRoot))
                    {
                        throw new ProtocolException(
                                  "Payload hash unequal with merkle root.");
                    }
                }

                return(tXs);
            }
Beispiel #3
0
        public AddressMessage(byte[] messagePayload)
            : base("addr", messagePayload)
        {
            int startIndex = 0;

            int addressesCount = VarInt.GetInt32(
                Payload,
                ref startIndex);

            for (int i = 0; i < addressesCount; i++)
            {
                NetworkAddresses.Add(
                    NetworkAddress.ParseAddress(
                        Payload, ref startIndex));
            }
        }
Beispiel #4
0
        public GetDataMessage(NetworkMessage message)
            : base("getdata", message.Payload)
        {
            int startIndex = 0;

            int inventoryCount = VarInt.GetInt32(
                Payload,
                ref startIndex);

            for (int i = 0; i < inventoryCount; i += 1)
            {
                Inventories.Add(
                    Inventory.Parse(
                        Payload,
                        ref startIndex));
            }
        }
Beispiel #5
0
        public InvMessage(byte[] buffer)
            : base(
                "inv",
                buffer)
        {
            int startIndex = 0;

            int inventoryCount = VarInt.GetInt32(
                Payload,
                ref startIndex);

            for (int i = 0; i < inventoryCount; i++)
            {
                Inventories.Add(
                    Inventory.Parse(
                        Payload,
                        ref startIndex));
            }
        }
Beispiel #6
0
            public TXOutput(
                byte[] buffer,
                ref int index)
            {
                Value = BitConverter.ToUInt64(
                    buffer,
                    index);

                index += 8;

                Buffer = buffer;

                LengthScript = VarInt.GetInt32(
                    Buffer,
                    ref index);

                StartIndexScript = index;
                index           += LengthScript;
            }
            void LoadCollisionData(byte[] buffer)
            {
                int index = 0;
                int uintLength;

                uint[] value;

                while (index < buffer.Length)
                {
                    byte[] key = new byte[HASH_BYTE_SIZE];
                    Array.Copy(buffer, index, key, 0, HASH_BYTE_SIZE);
                    index += HASH_BYTE_SIZE;

                    int byteLength = VarInt.GetInt32(buffer, ref index);
                    uintLength = byteLength >> 2;
                    value      = new uint[uintLength];
                    Buffer.BlockCopy(buffer, index, value, 0, byteLength);
                    index += byteLength;

                    CollisionTable.Add(key, value);
                }
            }
            void LoadPrimaryData(byte[] buffer)
            {
                int index = 0;

                int key;
                int uintLength;

                uint[] value;

                while (index < buffer.Length)
                {
                    key    = BitConverter.ToInt32(buffer, index);
                    index += 4;

                    int byteLength = VarInt.GetInt32(buffer, ref index);
                    uintLength = byteLength >> 2;
                    value      = new uint[uintLength];
                    Buffer.BlockCopy(buffer, index, value, 0, byteLength);
                    index += byteLength;

                    PrimaryTable.Add(key, value);
                }
            }
        public GetHeadersMessage(NetworkMessage message)
            : base("getheaders", message.Payload)
        {
            int startIndex = 0;

            var protocolVersionRemote = BitConverter.ToUInt32(Payload, startIndex);

            startIndex += 4;

            int headersCount = VarInt.GetInt32(Payload, ref startIndex);

            for (int i = 0; i < headersCount; i++)
            {
                byte[] hash = new byte[32];
                Array.Copy(Payload, startIndex, hash, 0, 32);

                ((List <byte[]>)HeaderLocator).Add(hash);

                startIndex += 32;
            }

            Array.Copy(Payload, startIndex, StopHash, 0, 32);
            startIndex += 32;
        }
Beispiel #10
0
            public override bool TryParse()
            {
                StopwatchParse.Start();

                try
                {
                    BufferIndex = 0;

                    BufferStartIndexesBlocks.Add(BufferIndex);

                    HeaderHash =
                        SHA256.ComputeHash(
                            SHA256.ComputeHash(
                                Buffer,
                                BufferIndex,
                                COUNT_HEADER_BYTES));

                    BufferIndex += COUNT_HEADER_BYTES;
                    TXCount      = VarInt.GetInt32(Buffer, ref BufferIndex);

                    if (Header == null)
                    {
                        if (!Headerchain.TryReadHeader(
                                HeaderHash,
                                SHA256,
                                out Header))
                        {
                            throw new ChainException(string.Format(
                                                         "Header hash {0} not in chain.",
                                                         HeaderHash.ToHexString()));
                        }
                    }
                    else
                    {
                        ValidateHeaderHash(
                            HeaderHash,
                            Header.HeaderHash);
                    }

                    Headers.Add(Header);

                    HeaderPrevious = Header.HeaderPrevious;

                    ParseBlock(OFFSET_INDEX_MERKLE_ROOT);
                    BlockCount += 1;
                    CountItems += TXCount;

                    while (BufferIndex < Buffer.Length)
                    {
                        BufferStartIndexesBlocks.Add(BufferIndex);

                        HeaderHash =
                            SHA256.ComputeHash(
                                SHA256.ComputeHash(
                                    Buffer,
                                    BufferIndex,
                                    COUNT_HEADER_BYTES));

                        int merkleRootIndex = BufferIndex + OFFSET_INDEX_MERKLE_ROOT;
                        BufferIndex += COUNT_HEADER_BYTES;
                        TXCount      = VarInt.GetInt32(Buffer, ref BufferIndex);

                        Header = Header.HeadersNext[0];

                        ValidateHeaderHash(
                            HeaderHash,
                            Header.HeaderHash);

                        Headers.Add(Header);

                        ParseBlock(merkleRootIndex);
                        BlockCount += 1;
                        CountItems += TXCount;
                    }

                    ConvertTablesToArrays();
                }
                catch (Exception ex)
                {
                    IsValid = false;

                    Console.WriteLine(
                        "Exception {0} loading archive {1}: {2}",
                        ex.GetType().Name,
                        Index,
                        ex.Message);

                    return(false);
                }

                StopwatchParse.Stop();

                return(true);
            }
Beispiel #11
0
            byte[] ParseTX(bool isCoinbase)
            {
                try
                {
                    int tXStartIndex = BufferIndex;

                    BufferIndex += BYTE_LENGTH_VERSION;

                    bool isWitnessFlagPresent = Buffer[BufferIndex] == 0x00;
                    if (isWitnessFlagPresent)
                    {
                        throw new NotImplementedException("Parsing of segwit txs not implemented");
                        //BufferIndex += 2;
                    }

                    int countInputs = VarInt.GetInt32(Buffer, ref BufferIndex);

                    if (isCoinbase)
                    {
                        new TXInput(Buffer, ref BufferIndex);
                    }
                    else
                    {
                        for (int i = 0; i < countInputs; i += 1)
                        {
                            TXInput input = new TXInput(Buffer, ref BufferIndex);

                            AddInput(input);
                        }
                    }

                    int countTXOutputs = VarInt.GetInt32(Buffer, ref BufferIndex);

                    for (int i = 0; i < countTXOutputs; i += 1)
                    {
                        BufferIndex += BYTE_LENGTH_OUTPUT_VALUE;
                        int lengthLockingScript = VarInt.GetInt32(Buffer, ref BufferIndex);
                        BufferIndex += lengthLockingScript;
                    }

                    //if (isWitnessFlagPresent)
                    //{
                    //var witnesses = new TXWitness[countInputs];
                    //for (int i = 0; i < countInputs; i += 1)
                    //{
                    //  witnesses[i] = TXWitness.Parse(Buffer, ref BufferIndex);
                    //}
                    //}

                    BufferIndex += BYTE_LENGTH_LOCK_TIME;

                    int tXLength = BufferIndex - tXStartIndex;

                    byte[] tXHash = SHA256.ComputeHash(
                        SHA256.ComputeHash(
                            Buffer,
                            tXStartIndex,
                            tXLength));

                    AddOutput(
                        tXHash,
                        countTXOutputs);

                    return(tXHash);
                }
                catch (ArgumentOutOfRangeException)
                {
                    throw new ChainException();
                }
            }
Beispiel #12
0
            public TX ParseTX(
                bool isCoinbase,
                byte[] buffer,
                ref int indexBuffer)
            {
                TX tX = new TX();

                try
                {
                    int tXStartIndex = indexBuffer;

                    indexBuffer += 4; // BYTE_LENGTH_VERSION

                    bool isWitnessFlagPresent = buffer[indexBuffer] == 0x00;
                    if (isWitnessFlagPresent)
                    {
                        throw new NotImplementedException(
                                  "Parsing of segwit txs not implemented");
                        //BufferIndex += 2;
                    }

                    int countInputs = VarInt.GetInt32(
                        buffer, ref indexBuffer);

                    if (isCoinbase)
                    {
                        new TXInput(buffer, ref indexBuffer);
                    }
                    else
                    {
                        for (int i = 0; i < countInputs; i += 1)
                        {
                            tX.TXInputs.Add(
                                new TXInput(
                                    buffer,
                                    ref indexBuffer));
                        }
                    }

                    int countTXOutputs = VarInt.GetInt32(
                        buffer,
                        ref indexBuffer);

                    for (int i = 0; i < countTXOutputs; i += 1)
                    {
                        tX.TXOutputs.Add(
                            new TXOutput(
                                buffer,
                                ref indexBuffer));
                    }

                    //if (isWitnessFlagPresent)
                    //{
                    //var witnesses = new TXWitness[countInputs];
                    //for (int i = 0; i < countInputs; i += 1)
                    //{
                    //  witnesses[i] = TXWitness.Parse(Buffer, ref BufferIndex);
                    //}
                    //}

                    indexBuffer += 4; //BYTE_LENGTH_LOCK_TIME

                    tX.Hash = SHA256.ComputeHash(
                        SHA256.ComputeHash(
                            buffer,
                            tXStartIndex,
                            indexBuffer - tXStartIndex));

                    tX.TXIDShort = BitConverter.ToInt32(tX.Hash, 0);

                    int lengthUTXOBits =
                        COUNT_NON_OUTPUT_BITS + countTXOutputs;

                    return(tX);
                }
                catch (ArgumentOutOfRangeException)
                {
                    throw new BitcoinException(
                              "ArgumentOutOfRangeException thrown in ParseTX.");
                }
            }
Beispiel #13
0
                public async Task StartMessageListener()
                {
                    try
                    {
                        while (true)
                        {
                            await ReadMessage(Cancellation.Token);

                            string.Format(
                                "{0} received message {1}",
                                GetID(),
                                Command)
                            .Log(LogFile);

                            switch (Command)
                            {
                            case "ping":
                                await SendMessage(new PongMessage(
                                                      BitConverter.ToUInt64(Payload, 0)));

                                break;

                            case "addr":
                                AddressMessage addressMessage =
                                    new AddressMessage(Payload);
                                break;

                            case "sendheaders":
                                await SendMessage(new SendHeadersMessage());

                                break;

                            case "feefilter":
                                FeeFilterMessage feeFilterMessage =
                                    new FeeFilterMessage(Payload);
                                FeeFilterValue = feeFilterMessage.FeeFilterValue;
                                break;

                            case "block":

                                byte[] blockBytes = Payload
                                                    .Take(PayloadLength)
                                                    .ToArray();

                                Block block = BlockParser.ParseBlock(blockBytes);

                                string.Format(
                                    "{0}: Receives block {1}.",
                                    GetID(),
                                    block.Header.Hash.ToHexString())
                                .Log(LogFile);

                                if (IsStateIdle())
                                {
                                    // Received unsolicited block
                                }
                                else if (IsStateAwaitingBlock())
                                {
                                    BlockDownload.InsertBlock(block);

                                    if (BlockDownload.IsDownloadCompleted)
                                    {
                                        SignalProtocolTaskCompleted.Post(true);

                                        Cancellation = new CancellationTokenSource();

                                        break;
                                    }

                                    Cancellation.CancelAfter(
                                        TIMEOUT_BLOCKDOWNLOAD_MILLISECONDS);
                                }

                                break;

                            case "headers":

                                Header header = null;
                                int    index  = 0;

                                int countHeaders = VarInt.GetInt32(
                                    Payload,
                                    ref index);

                                string.Format(
                                    "{0}: Receiving {1} headers.",
                                    GetID(),
                                    countHeaders)
                                .Log(LogFile);

                                if (IsStateIdle())
                                {
                                    header = BlockParser.ParseHeader(
                                        Payload,
                                        ref index);

                                    index += 1;

                                    if (!Blockchain.TryLock())
                                    {
                                        break;
                                    }

                                    try
                                    {
                                        string.Format(
                                            "Received unsolicited header {0}",
                                            header.Hash.ToHexString())
                                        .Log(LogFile);

                                        if (Blockchain.ContainsHeader(header.Hash))
                                        {
                                            Header headerContained = Blockchain.HeaderTip;

                                            var headerDuplicates          = new List <byte[]>();
                                            int depthDuplicateAcceptedMax = 3;
                                            int depthDuplicate            = 0;

                                            while (depthDuplicate < depthDuplicateAcceptedMax)
                                            {
                                                if (headerContained.Hash.IsEqual(header.Hash))
                                                {
                                                    if (headerDuplicates.Any(h => h.IsEqual(header.Hash)))
                                                    {
                                                        throw new ProtocolException(
                                                                  string.Format(
                                                                      "Received duplicate header {0} more than once.",
                                                                      header.Hash.ToHexString()));
                                                    }

                                                    headerDuplicates.Add(header.Hash);
                                                    if (headerDuplicates.Count > depthDuplicateAcceptedMax)
                                                    {
                                                        headerDuplicates = headerDuplicates.Skip(1)
                                                                           .ToList();
                                                    }

                                                    break;
                                                }

                                                if (headerContained.HeaderPrevious != null)
                                                {
                                                    break;
                                                }

                                                headerContained = header.HeaderPrevious;
                                                depthDuplicate += 1;
                                            }

                                            if (depthDuplicate == depthDuplicateAcceptedMax)
                                            {
                                                throw new ProtocolException(
                                                          string.Format(
                                                              "Received duplicate header {0} with depth greater than {1}.",
                                                              header.Hash.ToHexString(),
                                                              depthDuplicateAcceptedMax));
                                            }
                                        }
                                        else
                                        if (header.HashPrevious.IsEqual(
                                                Blockchain.HeaderTip.Hash))
                                        {
                                            header.HeaderPrevious = Blockchain.HeaderTip;

                                            Blockchain.ValidateHeaders(header);

                                            await Blockchain.Network
                                            .SynchronizeUTXO(header, this);

                                            Blockchain.ReleaseLock();

                                            break;
                                        }
                                        else
                                        {
                                            IsSynchronized = false;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        Blockchain.ReleaseLock();

                                        throw ex;
                                    }

                                    Blockchain.ReleaseLock();
                                }
                                else if (IsStateAwaitingHeader())
                                {
                                    if (countHeaders > 0)
                                    {
                                        header = BlockParser.ParseHeader(
                                            Payload,
                                            ref index);

                                        index += 1;

                                        HeaderDownload.InsertHeader(header);

                                        while (index < PayloadLength)
                                        {
                                            header = BlockParser.ParseHeader(
                                                Payload,
                                                ref index);

                                            index += 1;

                                            HeaderDownload.InsertHeader(header);
                                        }
                                    }

                                    string.Format(
                                        "{0}: Signal getheaders task complete.",
                                        GetID())
                                    .Log(LogFile);

                                    SignalProtocolTaskCompleted.Post(true);

                                    Cancellation = new CancellationTokenSource();

                                    break;
                                }

                                break;

                            case "notfound":

                                Console.WriteLine(
                                    "Command notfound not implemented yet.");

                                break;

                            case "inv":

                                var invMessage = new InvMessage(Payload);
                                if (invMessage.Inventories.First().IsTX())
                                {
                                    throw new ProtocolException(
                                              "Received TX inv message despite TX-disable signaled.");
                                }

                                break;


                            default:
                                // Send message unknown
                                break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        FlagDispose = true;

                        Cancellation.Cancel();

                        string.Format(
                            "Peer {0} experienced error " +
                            "in message listener: \n{1}",
                            GetID(),
                            "message: " + ex.Message +
                            "stack trace: " + ex.StackTrace)
                        .Log(LogFile);
                    }
                }