Example #1
0
        /**
         * Parse wire byte[] message into RLP elements.
         *
         * @param rlpEncoded - RLP encoded byte-array
         * @return recursive RLP structure
         */
        public static RlpList Decode(byte[] rlpEncoded)
        {
            var rlpList = new RlpList();

            Traverse(rlpEncoded, 0, rlpEncoded.Length, rlpList);
            return(rlpList);
        }
Example #2
0
        private static byte[] EncodeList(RlpList values)
        {
            if (values == null || values.Count < 1)
            {
                return(Encode(new byte[] { }, OFFSET_SHORT_LIST));
            }

            byte[] result = new byte[0];
            foreach (IRlpType entry in values)
            {
                result = result.Concat(Encode(entry));
            }

            return(Encode(result, OFFSET_SHORT_LIST));
        }
Example #3
0
        private static void Traverse(byte[] data, int startPos, int endPos, RlpList rlpList)
        {
            try
            {
                if (data == null || data.Length == 0)
                {
                    return;
                }

                while (startPos < endPos)
                {
                    var prefix = data[startPos] & 0xff;

                    if (prefix < OFFSET_SHORT_STRING)
                    {
                        // 1. the data is a string if the range of the
                        // first byte(i.e. prefix) is [0x00, 0x7f],
                        // and the string is the first byte itself exactly;
                        byte[] rlpData = { (byte)prefix };
                        rlpList.Add(RlpString.Create(rlpData));
                        startPos += 1;
                    }
                    else if (prefix == OFFSET_SHORT_STRING)
                    {
                        // null
                        rlpList.Add(RlpString.Create(new byte[0]));
                        startPos += 1;
                    }
                    else if (prefix > OFFSET_SHORT_STRING && prefix <= OFFSET_LONG_STRING)
                    {
                        // 2. the data is a string if the range of the
                        // first byte is [0x80, 0xb7], and the string
                        // which length is equal to the first byte minus 0x80
                        // follows the first byte;

                        byte strLen = (byte)(prefix - OFFSET_SHORT_STRING);

                        byte[] rlpData = new byte[strLen];
                        Unsafe.CopyBlock(ref rlpData[0], ref data[startPos + 1], (uint)strLen);
                        // Array.Copy(data, startPos + 1, rlpData, 0, strLen);

                        rlpList.Add(RlpString.Create(rlpData));
                        startPos += 1 + strLen;
                    }
                    else if (prefix > OFFSET_LONG_STRING && prefix < OFFSET_SHORT_LIST)
                    {
                        // 3. the data is a string if the range of the
                        // first byte is [0xb8, 0xbf], and the length of the
                        // string which length in bytes is equal to the
                        // first byte minus 0xb7 follows the first byte,
                        // and the string follows the length of the string;

                        byte lenOfStrLen = (byte)(prefix - OFFSET_LONG_STRING);
                        int  strLen      = CalcLength(lenOfStrLen, data, startPos);

                        // now we can parse an item for data[1]..data[length]
                        byte[] rlpData = new byte[strLen];
                        Unsafe.CopyBlock(ref rlpData[0], ref data[startPos + lenOfStrLen + 1], (uint)strLen);
                        // Array.Copy(data, startPos + lenOfStrLen + 1, rlpData, 0, strLen);

                        rlpList.Add(RlpString.Create(rlpData));
                        startPos += lenOfStrLen + strLen + 1;
                    }
                    else if (prefix >= OFFSET_SHORT_LIST && prefix <= OFFSET_LONG_LIST)
                    {
                        // 4. the data is a list if the range of the
                        // first byte is [0xc0, 0xf7], and the concatenation of
                        // the RLP encodings of all items of the list which the
                        // total payload is equal to the first byte minus 0xc0 follows the first byte;

                        byte listLen = (byte)(prefix - OFFSET_SHORT_LIST);

                        RlpList newLevelList = new RlpList();
                        Traverse(data, startPos + 1, startPos + listLen + 1, newLevelList);
                        rlpList.Add(newLevelList);

                        startPos += 1 + listLen;
                    }
                    else if (prefix > OFFSET_LONG_LIST)
                    {
                        // 5. the data is a list if the range of the
                        // first byte is [0xf8, 0xff], and the total payload of the
                        // list which length is equal to the
                        // first byte minus 0xf7 follows the first byte,
                        // and the concatenation of the RLP encodings of all items of
                        // the list follows the total payload of the list;

                        byte lenOfListLen = (byte)(prefix - OFFSET_LONG_LIST);
                        int  listLen      = CalcLength(lenOfListLen, data, startPos);

                        RlpList newLevelList = new RlpList();
                        Traverse(data, startPos + lenOfListLen + 1,
                                 startPos + lenOfListLen + listLen + 1, newLevelList);
                        rlpList.Add(newLevelList);

                        startPos += lenOfListLen + listLen + 1;
                    }
                }
            }
            catch (Exception e)
            {
                throw new FormatException("RLP wrong encoding", e);
            }
        }