forked from cerc-io/plugeth
Updated rlp encoding. (requires verification!)
This commit is contained in:
parent
df0fe67fce
commit
323ba36869
91
rlp.go
91
rlp.go
@ -6,29 +6,51 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EncodeSlice(slice []interface{}) []byte {
|
func BinaryLength(n uint64) uint64 {
|
||||||
var buff bytes.Buffer
|
if n == 0 { return 0 }
|
||||||
|
|
||||||
for _, val := range slice {
|
return 1 + BinaryLength(n / 256)
|
||||||
switch t := val.(type) {
|
|
||||||
case []interface{}, []string:
|
|
||||||
buff.Write(Encode(t))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return buff.Bytes()
|
func ToBinarySlice(n uint64, length uint64) []uint64 {
|
||||||
|
if length == 0 {
|
||||||
|
length = BinaryLength(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 { return make([]uint64, 1) }
|
||||||
|
|
||||||
|
slice := ToBinarySlice(n / 256, 0)
|
||||||
|
slice = append(slice, n % 256)
|
||||||
|
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToBin(n uint64, length uint64) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for _, val := range ToBinarySlice(n, length) {
|
||||||
|
buf.WriteString(string(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromBin(data []byte) uint64 {
|
||||||
|
if len(data) == 0 { return 0 }
|
||||||
|
|
||||||
|
return FromBin(data[:len(data)-1]) * 256 + uint64(data[len(data)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
func Decode(data []byte, pos int) {
|
||||||
|
char := int(data[pos])
|
||||||
|
switch {
|
||||||
|
case char < 24:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Encode(object interface{}) []byte {
|
func Encode(object interface{}) []byte {
|
||||||
var buff bytes.Buffer
|
var buff bytes.Buffer
|
||||||
|
|
||||||
switch t := object.(type) {
|
switch t := object.(type) {
|
||||||
case string:
|
|
||||||
if len(t) < 56 {
|
|
||||||
buff.WriteString(string(len(t) + 64) + t)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
case uint32, uint64:
|
case uint32, uint64:
|
||||||
var num uint64
|
var num uint64
|
||||||
if _num, ok := t.(uint64); ok {
|
if _num, ok := t.(uint64); ok {
|
||||||
@ -40,12 +62,49 @@ func Encode(object interface{}) []byte {
|
|||||||
if num >= 0 && num < 24 {
|
if num >= 0 && num < 24 {
|
||||||
buff.WriteString(string(num))
|
buff.WriteString(string(num))
|
||||||
} else if num <= uint64(math.Pow(2, 256)) {
|
} else if num <= uint64(math.Pow(2, 256)) {
|
||||||
|
b := ToBin(num, 0)
|
||||||
|
buff.WriteString(string(len(b) + 23) + b)
|
||||||
|
} else {
|
||||||
|
b := ToBin(num, 0)
|
||||||
|
b2 := ToBin(uint64(len(b)), 0)
|
||||||
|
buff.WriteString(string(len(b2) + 55) + b2 + b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case string:
|
||||||
|
if len(t) < 56 {
|
||||||
|
buff.WriteString(string(len(t) + 64) + t)
|
||||||
|
} else {
|
||||||
|
b2 := ToBin(uint64(len(t)), 0)
|
||||||
|
buff.WriteString(string(len(b2) + 119) + b2 + t)
|
||||||
|
}
|
||||||
|
|
||||||
case []byte:
|
case []byte:
|
||||||
// Cast the byte slice to a string
|
// Cast the byte slice to a string
|
||||||
buff.Write(Encode(string(t)))
|
buff.Write(Encode(string(t)))
|
||||||
case []interface{}:
|
|
||||||
buff.Write(EncodeSlice(t))
|
case []interface{}, []string:
|
||||||
|
// Inline function for writing the slice header
|
||||||
|
WriteSliceHeader := func(length int) {
|
||||||
|
if length < 56 {
|
||||||
|
buff.WriteString(string(length + 128))
|
||||||
|
} else {
|
||||||
|
b2 := ToBin(uint64(length), 0)
|
||||||
|
buff.WriteString(string(len(b2) + 183) + b2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME How can I do this "better"?
|
||||||
|
if interSlice, ok := t.([]interface{}); ok {
|
||||||
|
WriteSliceHeader(len(interSlice))
|
||||||
|
for _, val := range interSlice {
|
||||||
|
buff.Write(Encode(val))
|
||||||
|
}
|
||||||
|
} else if stringSlice, ok := t.([]string); ok {
|
||||||
|
WriteSliceHeader(len(stringSlice))
|
||||||
|
for _, val := range stringSlice {
|
||||||
|
buff.Write(Encode(val))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buff.Bytes()
|
return buff.Bytes()
|
||||||
|
20
rlp_test.go
Normal file
20
rlp_test.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEncode(t *testing.T) {
|
||||||
|
strRes := "Cdog"
|
||||||
|
str := string(Encode("dog"))
|
||||||
|
if str != strRes {
|
||||||
|
t.Error(fmt.Sprintf("Expected %q, got %q", strRes, str))
|
||||||
|
}
|
||||||
|
|
||||||
|
sliceRes := "\u0083CdogCgodCcat"
|
||||||
|
slice := string(Encode([]string{"dog", "god", "cat"}))
|
||||||
|
if slice != sliceRes {
|
||||||
|
t.Error(fmt.Sprintf("Expected %q, got %q", sliceRes, slice))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user