@Test public void emptyByteString() { final RLPInput in = RLP.input(h("0x80")); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(BytesValue.EMPTY); assertThat(in.isDone()).isTrue(); }
@Test public void simpleListwithBytesValue() { final RLPInput in = RLP.input(h("0xc28180")); assertThat(in.isDone()).isFalse(); assertThat(in.enterList()).isEqualTo(1); assertThat(in.readBytesValue()).isEqualTo(h("0x80")); in.leaveList(); assertThat(in.isDone()).isTrue(); }
@Test public void singleBarelyLongElement() { final RLPInput in = RLP.input(h("0xb838" + times("2b", 56))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("2b", 56))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElement() { final RLPInput in = RLP.input(h("0xb908c1" + times("3c", 2241))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 2241))); assertThat(in.isDone()).isTrue(); }
@Test public void decodeValueWithLeadingZerosAsBytesValue() { RLPInput in = RLP.input(h("0x8800000000000000D0")); assertThat(BytesValues.extractLong(in.readBytesValue())).isEqualTo(208); } }
private static Object decode(final RLPInput in) { if (!in.nextIsList()) { return in.readBytesValue(); } final int size = in.enterList(); final List<Object> l = new ArrayList<>(size); for (int i = 0; i < size; i++) l.add(decode(in)); in.leaveList(); return l; }
@Test public void singleLongElementBoundaryCase_4() { final RLPInput in = RLP.input(h("0xba010000" + times("3c", 65536))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 65536))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElementBoundaryCase_6() { // A RLPx Frame can have a maximum length of 0xffffff, so boundary above this // will be not be real world scenarios. final RLPInput in = RLP.input(h("0xbb01000000" + times("3c", 16777216))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 16777216))); assertThat(in.isDone()).isTrue(); }
@Test public void singleBarelyShortElement() { final RLPInput in = RLP.input(h("0xb7" + times("2b", 55))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("2b", 55))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElementBoundaryCase_3() { final RLPInput in = RLP.input(h("0xb9ffff" + times("3c", 65535))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 65535))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElementBoundaryCase_1() { final RLPInput in = RLP.input(h("0xb8ff" + times("3c", 255))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 255))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElementBoundaryCase_2() { final RLPInput in = RLP.input(h("0xb90100" + times("3c", 256))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 256))); assertThat(in.isDone()).isTrue(); }
@Test public void singleLongElementBoundaryCase_5() { final RLPInput in = RLP.input(h("0xbaffffff" + times("3c", 16777215))); assertThat(in.isDone()).isFalse(); assertThat(in.readBytesValue()).isEqualTo(h(times("3c", 16777215))); assertThat(in.isDone()).isTrue(); }
@Test public void rlpListSizeHoldsMaxValue() { // Size value encode max positive int. So, size is decoded, but // RLP is malformed because the actual payload is not present AssertionsForClassTypes.assertThatThrownBy(() -> RLP.input(h("0xFB7FFFFFFF")).readBytesValue()) .isInstanceOf(CorruptedRLPInputException.class) .hasMessageContaining( "Input doesn't have enough data for RLP encoding: encoding advertise a payload ending at byte 2147483652 but input has size 5"); }
@Test public void rlpItemSizeHoldsMaxValue() { // Size value encode max positive int. So, size is decoded, but // RLP is malformed because the actual payload is not present AssertionsForClassTypes.assertThatThrownBy(() -> RLP.input(h("0xBB7FFFFFFF")).readBytesValue()) .isInstanceOf(CorruptedRLPInputException.class) .hasMessageContaining("payload should start at offset 5 but input has only 5 bytes"); }
@Test public void failsWhenPayloadSizeHasLeadingZeroes() { // Sanity check correctly encoded value: a byte string of 56 bytes, requiring 1 byte to encode // size 56 final BytesValue correctBytes = h( "0xB8380102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738"); assertThat( h( "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738")) .isEqualTo(RLP.input(correctBytes).readBytesValue()); // Encode same value, but use 2 bytes to represent the size, and pad size value with leading // zeroes final BytesValue incorrectBytes = h( "0xB900380102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738"); assertThatThrownBy(() -> RLP.input(incorrectBytes)) .isInstanceOf(RLPException.class) .hasRootCauseInstanceOf(MalformedRLPInputException.class) .hasMessageContaining("size of payload has leading zeros"); }
@Test public void failsWhenShortByteStringEncodedAsLongByteString() { // Sanity check correctly encoded value: a byte string of 55 bytes encoded as short byte string final BytesValue correctBytes = h( "0xB70102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"); assertThat( h( "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637")) .isEqualTo(RLP.input(correctBytes).readBytesValue()); // Encode same value using long format final BytesValue incorrectBytes = h( "0xB8370102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f3031323334353637"); assertThatThrownBy(() -> RLP.input(incorrectBytes)) .isInstanceOf(RLPException.class) .hasRootCauseInstanceOf(MalformedRLPInputException.class) .hasMessageContaining("written as a long item, but size 55 < 56 bytes"); }