decodeRLP function

(RLPItem, int) decodeRLP(
  1. Uint8List input, {
  2. int offset = 0,
})

Implementation

(RLPItem, int) decodeRLP(
  Uint8List input, {
  int offset = 0,
}) {
  final bytes = input.buffer.asByteData();
  if (offset >= input.length) {
    throw RLPException("offset out of bounds");
  }
  final firstByte = bytes.getUint8(offset);

  switch (firstByte) {
    case >= 0xf8:
      final lengthLength = firstByte - 0xf7;
      if (offset + 1 + lengthLength > input.length) {
        throw RLPException("insufficient data for length bytes");
      }

      final length = decodeLength(input, lengthLength, offset + 1);

      if (length < 56) {
        throw RLPException("encoded list too short");
      }

      final totalLength = 1 + lengthLength + length;
      if (offset + totalLength > input.length) {
        throw RLPException("insufficient data length");
      }

      // For Root Lists we can enforce a stric length check
      if (offset == 0) {
        if (offset + totalLength != input.length) {
          throw RLPException("Given input is longer than specified length");
        }
      }

      return (
        RLPList.fromBuffer(
          input,
          offset,
          offset + 1 + lengthLength,
          lengthLength + length,
        ),
        1 + lengthLength + length
      );
    case >= 0xc0:
      final length = firstByte - 0xc0;

      if (offset + 1 + length > input.length) {
        throw RLPException("insufficient data length");
      }

      // For Root Lists we can enforce a stric length check
      if (offset == 0) {
        if (1 + length != input.length) {
          throw RLPException("Given input is longer than specified length");
        }
      }

      return (
        RLPList.fromBuffer(
          input,
          offset,
          offset + 1,
          length,
        ),
        1 + length
      );
    case >= 0xb8:
      final lengthLength = firstByte - 0xb7;
      if (offset + 1 + lengthLength > input.length) {
        throw RLPException("insufficient data for length bytes");
      }
      final length = decodeLength(input, lengthLength, offset + 1);

      if (length < 56) {
        throw RLPException("Invalid RLP: length is too short");
      }
      if (offset + 1 + lengthLength + length > input.length) {
        throw RLPException("insufficient data length");
      }
      final result = input.sublist(
        offset + 1 + lengthLength,
        offset + 1 + lengthLength + length,
      );
      return (RLPBytes(result), 1 + lengthLength + length);
    case >= 0x80:
      final length = firstByte - 0x80;
      if (offset + 1 + length > input.length) {
        throw RLPException("insufficient data length");
      }
      final result = input.sublist(
        offset + 1,
        offset + 1 + length,
      );
      if (length == 1 && result[0] < 0x80) {
        throw RLPException(
          "invalid RLP encoding: invalid prefix, single byte < 0x80 are not prefixed",
        );
      }
      return (RLPBytes(result), 1 + length);
    default:
      final result = input.sublist(offset, offset + 1);
      return (RLPBytes(result), 1);
  }
}