aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <obscuren@obscura.com>2013-12-28 05:32:55 +0800
committerobscuren <obscuren@obscura.com>2013-12-28 05:32:55 +0800
commit323ba36869126520c294b6c8acacfa9877cde5c7 (patch)
tree1b392cbde4624e0ee79959983191919ed34f3724
parentdf0fe67fce8050dad60f0d0fca28a78da818832f (diff)
downloadgo-tangerine-323ba36869126520c294b6c8acacfa9877cde5c7.tar.gz
go-tangerine-323ba36869126520c294b6c8acacfa9877cde5c7.tar.zst
go-tangerine-323ba36869126520c294b6c8acacfa9877cde5c7.zip
Updated rlp encoding. (requires verification!)
-rw-r--r--rlp.go91
-rw-r--r--rlp_test.go20
2 files changed, 95 insertions, 16 deletions
diff --git a/rlp.go b/rlp.go
index 2c722cf7a..cce839095 100644
--- a/rlp.go
+++ b/rlp.go
@@ -6,29 +6,51 @@ import (
"math"
)
-func EncodeSlice(slice []interface{}) []byte {
- var buff bytes.Buffer
+func BinaryLength(n uint64) uint64 {
+ if n == 0 { return 0 }
- for _, val := range slice {
- switch t := val.(type) {
- case []interface{}, []string:
- buff.Write(Encode(t))
- }
+ return 1 + BinaryLength(n / 256)
+}
+
+func ToBinarySlice(n uint64, length uint64) []uint64 {
+ if length == 0 {
+ length = BinaryLength(n)
}
- return buff.Bytes()
+ 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 {
var buff bytes.Buffer
switch t := object.(type) {
- case string:
- if len(t) < 56 {
- buff.WriteString(string(len(t) + 64) + t)
- } else {
-
- }
case uint32, uint64:
var num uint64
if _num, ok := t.(uint64); ok {
@@ -40,12 +62,49 @@ func Encode(object interface{}) []byte {
if num >= 0 && num < 24 {
buff.WriteString(string(num))
} 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:
// Cast the byte slice to a string
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()
diff --git a/rlp_test.go b/rlp_test.go
new file mode 100644
index 000000000..922b70978
--- /dev/null
+++ b/rlp_test.go
@@ -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))
+ }
+}