geth rlp

최호준·2022년 10월 9일
0

rlp 방식을 사용하는 이유

  • 구현의 단순성과 언제나 일관된 바이트 형태를 보장하기 때문에 사용한다.
  • key/value 맵 구조는 순서가 정해져 있지 않다. 따라서 데이터의 순서에 따라 결과가 달라질 수 있다. 그래서 인코딩에 사용할 수 없다.
  • float의 경우는 어디까지 소수점을 적용할지, 올림, 반올림은 어떻게 처리할지 등등 이슈가 존재한다.
  • 따라서 항상 일관된 결괏값을 보장하기 위해서 rlp 방식을 이용한다.

golnag으로 작성한 example

func Example_단일바이트() {
	result, _ := rlp.EncodeToBytes("a")
	fmt.Println(toHexs(result))

	result, _ = rlp.EncodeToBytes("1")
	fmt.Println(toHexs(result))
	// Output:
	// [61]
	// [31]

}

func ExampleShort_55바이트이하() {
	result, _ := rlp.EncodeToBytes("foobar")
	// 문자열의 길이 6
	// prefix = 0x80 + 0x06 = 0x86
	fmt.Println(toHexs(result))
	// Output:
	// [86 66 6f 6f 62 61 72]
}

func Example_55바이트초과() {
	tartget := strings.Repeat("a", 100)
	// 문자열의 길이 = 100 => 0b0110_0100 (길이는 바이트 단위로 계산) => 1
	// prefix = [0xb7 + 0x01][6(0b 0110)][4(0b 0100)] => b8 64
	result, _ := rlp.EncodeToBytes(tartget)
	fmt.Println(toHexs(result))
	// Output:
	// [b8 64 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61]
}

func Example_배열의_모든_아이템들의_rlp_인코딩된_값들의_길이가_55보다_작은경우_1() {
	target := []string{"ab"}
	// 1. 먼저 "ab"를 인코딩
	// 문자열 길이 2
	// prefix = 0x80 + 2 = 0x82
	// 인코딩된 값 = 0x82 0x61 0x62
	// ab 인코딩된 값 길이 =  3 = 0x03
	// prefix = 0xc0 + 0x03 = 0xc3
	// 인코딩된 값 = 0xc3 0x82 0x61 0x62
	result, _ := rlp.EncodeToBytes(target)
	fmt.Println(toHexs(result))
	// Output:
	// [c3 82 61 62]의
}

func Example_배열의_모든_아이템들의_rlp_인코딩된_값들의_길이가_55보다_작은경우_2() {
	target := []string{"ab", "cd"}
	// 1. 먼저 "ab"를 인코딩
	// 문자열 길이 2
	// prefix = 0x80 + 2 = 0x82
	// 인코딩된 값 = 0x82 0x61 0x62
	// 2. "cd" 인코딩
	// 문자열 길이 2
	// prefix = 0x80 + 2 = 0x82
	// 인코딩된 값 = 0x82 + 0x63 + 0x64
	// 인코딩된 값들의 길이 =  6 = 0x06
	// prefix = 0xc0 + 0x06 = 0xc6
	// 인코딩된 값 = 0xc6 0x82 0x61 0x62 0x82 0x63 0x64
	result, _ := rlp.EncodeToBytes(target)
	fmt.Println(toHexs(result))
	// Output:
	// [c6 82 61 62 82 63 64]
}

func toHexs(bytes []byte) []string {
	var result []string
	for _, x := range bytes {
		result = append(result, fmt.Sprintf("%x", x))
	}
	return result
}

func Example_첫_바이트가_00_7f() {
	var a string
	rlp.DecodeBytes([]byte{97}, &a)
	fmt.Println(a)

	var b string
	rlp.DecodeBytes([]byte{98}, &b)
	fmt.Println(b)

	// Output:
	// a
	// b
}

func Example_첫_바이트가_80_b7() {
	// ab is "ab"
	var ab string
	rlp.DecodeBytes([]byte{130, 97, 98}, &ab)
	fmt.Println(ab)

	// Output:
	// ab
}

func Example_첫_바이트가_b8_bf() {
	// longA is strings.Repeat("a", 100)
	var longA string
	rlp.DecodeBytes([]byte{184, 100, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97}, &longA)
	fmt.Println(longA)

	// Output:
	// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
}

func Example_첫_바이트가_c0_f7() {
	// result is [ ab,cd ]
	var result []string
	rlp.DecodeBytes([]byte{198, 130, 97, 98, 130, 99, 100}, &result)
	fmt.Println(result)

	// Output:
	// [ab cd]
}

0개의 댓글