From f6d1bfe45bf3709d7bad40bf563b5c09228622e3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 14 Feb 2014 23:56:09 +0100 Subject: The great merge --- ethutil/rlp.go | 418 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 ethutil/rlp.go (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go new file mode 100644 index 000000000..0f88933b3 --- /dev/null +++ b/ethutil/rlp.go @@ -0,0 +1,418 @@ +package ethutil + +import ( + "bytes" + _ "encoding/binary" + "fmt" + _ "log" + _ "math" + "math/big" + "reflect" +) + +/////////////////////////////////////// +type EthEncoder interface { + EncodeData(rlpData interface{}) []byte +} +type EthDecoder interface { + Get(idx int) *RlpValue +} + +////////////////////////////////////// + +type RlpEncoder struct { + rlpData []byte +} + +func NewRlpEncoder() *RlpEncoder { + encoder := &RlpEncoder{} + + return encoder +} +func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte { + return Encode(rlpData) +} + +// Data rlpValueutes are returned by the rlp decoder. The data rlpValueutes represents +// one item within the rlp data structure. It's responsible for all the casting +// It always returns something rlpValueid +type RlpValue struct { + Value interface{} + kind reflect.Value +} + +func (rlpValue *RlpValue) String() string { + return fmt.Sprintf("%q", rlpValue.Value) +} + +func Conv(rlpValue interface{}) *RlpValue { + return &RlpValue{Value: rlpValue, kind: reflect.ValueOf(rlpValue)} +} + +func NewRlpValue(rlpValue interface{}) *RlpValue { + return &RlpValue{Value: rlpValue} +} + +func (rlpValue *RlpValue) Type() reflect.Kind { + return reflect.TypeOf(rlpValue.Value).Kind() +} + +func (rlpValue *RlpValue) IsNil() bool { + return rlpValue.Value == nil +} + +func (rlpValue *RlpValue) Length() int { + //return rlpValue.kind.Len() + if data, ok := rlpValue.Value.([]interface{}); ok { + return len(data) + } + + return 0 +} + +func (rlpValue *RlpValue) AsRaw() interface{} { + return rlpValue.Value +} + +func (rlpValue *RlpValue) AsUint() uint64 { + if Value, ok := rlpValue.Value.(uint8); ok { + return uint64(Value) + } else if Value, ok := rlpValue.Value.(uint16); ok { + return uint64(Value) + } else if Value, ok := rlpValue.Value.(uint32); ok { + return uint64(Value) + } else if Value, ok := rlpValue.Value.(uint64); ok { + return Value + } + + return 0 +} + +func (rlpValue *RlpValue) AsByte() byte { + if Value, ok := rlpValue.Value.(byte); ok { + return Value + } + + return 0x0 +} + +func (rlpValue *RlpValue) AsBigInt() *big.Int { + if a, ok := rlpValue.Value.([]byte); ok { + b := new(big.Int) + b.SetBytes(a) + return b + } + + return big.NewInt(0) +} + +func (rlpValue *RlpValue) AsString() string { + if a, ok := rlpValue.Value.([]byte); ok { + return string(a) + } else if a, ok := rlpValue.Value.(string); ok { + return a + } else { + //panic(fmt.Sprintf("not string %T: %v", rlpValue.Value, rlpValue.Value)) + } + + return "" +} + +func (rlpValue *RlpValue) AsBytes() []byte { + if a, ok := rlpValue.Value.([]byte); ok { + return a + } + + return make([]byte, 0) +} + +func (rlpValue *RlpValue) AsSlice() []interface{} { + if d, ok := rlpValue.Value.([]interface{}); ok { + return d + } + + return []interface{}{} +} + +func (rlpValue *RlpValue) AsSliceFrom(from int) *RlpValue { + slice := rlpValue.AsSlice() + + return NewRlpValue(slice[from:]) +} + +func (rlpValue *RlpValue) AsSliceTo(to int) *RlpValue { + slice := rlpValue.AsSlice() + + return NewRlpValue(slice[:to]) +} + +func (rlpValue *RlpValue) AsSliceFromTo(from, to int) *RlpValue { + slice := rlpValue.AsSlice() + + return NewRlpValue(slice[from:to]) +} + +// Threat the rlpValueute as a slice +func (rlpValue *RlpValue) Get(idx int) *RlpValue { + if d, ok := rlpValue.Value.([]interface{}); ok { + // Guard for oob + if len(d) <= idx { + return NewRlpValue(nil) + } + + if idx < 0 { + panic("negative idx for Rlp Get") + } + + return NewRlpValue(d[idx]) + } + + // If this wasn't a slice you probably shouldn't be using this function + return NewRlpValue(nil) +} + +func (rlpValue *RlpValue) Cmp(o *RlpValue) bool { + return reflect.DeepEqual(rlpValue.Value, o.Value) +} + +func (rlpValue *RlpValue) Encode() []byte { + return Encode(rlpValue.Value) +} + +func NewRlpValueFromBytes(rlpData []byte) *RlpValue { + if len(rlpData) != 0 { + data, _ := Decode(rlpData, 0) + return NewRlpValue(data) + } + + return NewRlpValue(nil) +} + +// RlpValue value setters +// An empty rlp value is always a list +func EmptyRlpValue() *RlpValue { + return NewRlpValue([]interface{}{}) +} + +func (rlpValue *RlpValue) AppendList() *RlpValue { + list := EmptyRlpValue() + rlpValue.Value = append(rlpValue.AsSlice(), list) + + return list +} + +func (rlpValue *RlpValue) Append(v interface{}) *RlpValue { + rlpValue.Value = append(rlpValue.AsSlice(), v) + + return rlpValue +} + +/* +func FromBin(data []byte) uint64 { + if len(data) == 0 { + return 0 + } + + return FromBin(data[:len(data)-1])*256 + uint64(data[len(data)-1]) +} +*/ + +const ( + RlpEmptyList = 0x80 + RlpEmptyStr = 0x40 +) + +func Char(c []byte) int { + if len(c) > 0 { + return int(c[0]) + } + + return 0 +} + +func DecodeWithReader(reader *bytes.Buffer) interface{} { + var slice []interface{} + + // Read the next byte + char := Char(reader.Next(1)) + switch { + case char == 0: + return nil + case char <= 0x7c: + return char + + case char <= 0xb7: + return reader.Next(int(char - 0x80)) + + case char <= 0xbf: + buff := bytes.NewReader(reader.Next(int(char - 0xb8))) + length := ReadVarint(buff) + + return reader.Next(int(length)) + + case char <= 0xf7: + length := int(char - 0xc0) + for i := 0; i < length; i++ { + obj := DecodeWithReader(reader) + if obj != nil { + slice = append(slice, obj) + } else { + break + } + } + + return slice + + } + + return slice +} + +// TODO Use a bytes.Buffer instead of a raw byte slice. +// Cleaner code, and use draining instead of seeking the next bytes to read +func Decode(data []byte, pos uint64) (interface{}, uint64) { + /* + if pos > uint64(len(data)-1) { + log.Println(data) + log.Panicf("index out of range %d for data %q, l = %d", pos, data, len(data)) + } + */ + + var slice []interface{} + char := int(data[pos]) + switch { + case char <= 0x7f: + return data[pos], pos + 1 + + case char <= 0xb7: + b := uint64(data[pos]) - 0x80 + + return data[pos+1 : pos+1+b], pos + 1 + b + + case char <= 0xbf: + b := uint64(data[pos]) - 0xb7 + + b2 := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+b])) + + return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2 + + case char <= 0xf7: + b := uint64(data[pos]) - 0xc0 + prevPos := pos + pos++ + for i := uint64(0); i < b; { + var obj interface{} + + // Get the next item in the data list and append it + obj, prevPos = Decode(data, pos) + slice = append(slice, obj) + + // Increment i by the amount bytes read in the previous + // read + i += (prevPos - pos) + pos = prevPos + } + return slice, pos + + case char <= 0xff: + l := uint64(data[pos]) - 0xf7 + //b := BigD(data[pos+1 : pos+1+l]).Uint64() + b := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+l])) + + pos = pos + l + 1 + + prevPos := b + for i := uint64(0); i < uint64(b); { + var obj interface{} + + obj, prevPos = Decode(data, pos) + slice = append(slice, obj) + + i += (prevPos - pos) + pos = prevPos + } + return slice, pos + + default: + panic(fmt.Sprintf("byte not supported: %q", char)) + } + + return slice, 0 +} + +var ( + directRlp = big.NewInt(0x7f) + numberRlp = big.NewInt(0xb7) + zeroRlp = big.NewInt(0x0) +) + +func Encode(object interface{}) []byte { + var buff bytes.Buffer + + if object != nil { + switch t := object.(type) { + case *RlpValue: + buff.Write(Encode(t.AsRaw())) + // Code dup :-/ + case int: + buff.Write(Encode(big.NewInt(int64(t)))) + case uint: + buff.Write(Encode(big.NewInt(int64(t)))) + case int8: + buff.Write(Encode(big.NewInt(int64(t)))) + case int16: + buff.Write(Encode(big.NewInt(int64(t)))) + case int32: + buff.Write(Encode(big.NewInt(int64(t)))) + case int64: + buff.Write(Encode(big.NewInt(t))) + case uint16: + buff.Write(Encode(big.NewInt(int64(t)))) + case uint32: + buff.Write(Encode(big.NewInt(int64(t)))) + case uint64: + buff.Write(Encode(big.NewInt(int64(t)))) + case byte: + buff.Write(Encode(big.NewInt(int64(t)))) + case *big.Int: + buff.Write(Encode(t.Bytes())) + case []byte: + if len(t) == 1 && t[0] <= 0x7f { + buff.Write(t) + } else if len(t) < 56 { + buff.WriteByte(byte(len(t) + 0x80)) + buff.Write(t) + } else { + b := big.NewInt(int64(len(t))) + buff.WriteByte(byte(len(b.Bytes()) + 0xb7)) + buff.Write(b.Bytes()) + buff.Write(t) + } + case string: + buff.Write(Encode([]byte(t))) + case []interface{}: + // Inline function for writing the slice header + WriteSliceHeader := func(length int) { + if length < 56 { + buff.WriteByte(byte(length + 0xc0)) + } else { + b := big.NewInt(int64(length)) + buff.WriteByte(byte(len(b.Bytes()) + 0xf7)) + buff.Write(b.Bytes()) + } + } + + var b bytes.Buffer + for _, val := range t { + b.Write(Encode(val)) + } + WriteSliceHeader(len(b.Bytes())) + buff.Write(b.Bytes()) + } + } else { + // Empty list for nil + buff.WriteByte(0xc0) + } + + return buff.Bytes() +} -- cgit v1.2.3 From 73fd358d940418b15dec850f50407bd2e504d88c Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 15 Feb 2014 01:34:18 +0100 Subject: Removed RlpValue in favour of Value --- ethutil/rlp.go | 189 +-------------------------------------------------------- 1 file changed, 2 insertions(+), 187 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 0f88933b3..025d269a0 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -7,19 +7,8 @@ import ( _ "log" _ "math" "math/big" - "reflect" ) -/////////////////////////////////////// -type EthEncoder interface { - EncodeData(rlpData interface{}) []byte -} -type EthDecoder interface { - Get(idx int) *RlpValue -} - -////////////////////////////////////// - type RlpEncoder struct { rlpData []byte } @@ -33,180 +22,6 @@ func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte { return Encode(rlpData) } -// Data rlpValueutes are returned by the rlp decoder. The data rlpValueutes represents -// one item within the rlp data structure. It's responsible for all the casting -// It always returns something rlpValueid -type RlpValue struct { - Value interface{} - kind reflect.Value -} - -func (rlpValue *RlpValue) String() string { - return fmt.Sprintf("%q", rlpValue.Value) -} - -func Conv(rlpValue interface{}) *RlpValue { - return &RlpValue{Value: rlpValue, kind: reflect.ValueOf(rlpValue)} -} - -func NewRlpValue(rlpValue interface{}) *RlpValue { - return &RlpValue{Value: rlpValue} -} - -func (rlpValue *RlpValue) Type() reflect.Kind { - return reflect.TypeOf(rlpValue.Value).Kind() -} - -func (rlpValue *RlpValue) IsNil() bool { - return rlpValue.Value == nil -} - -func (rlpValue *RlpValue) Length() int { - //return rlpValue.kind.Len() - if data, ok := rlpValue.Value.([]interface{}); ok { - return len(data) - } - - return 0 -} - -func (rlpValue *RlpValue) AsRaw() interface{} { - return rlpValue.Value -} - -func (rlpValue *RlpValue) AsUint() uint64 { - if Value, ok := rlpValue.Value.(uint8); ok { - return uint64(Value) - } else if Value, ok := rlpValue.Value.(uint16); ok { - return uint64(Value) - } else if Value, ok := rlpValue.Value.(uint32); ok { - return uint64(Value) - } else if Value, ok := rlpValue.Value.(uint64); ok { - return Value - } - - return 0 -} - -func (rlpValue *RlpValue) AsByte() byte { - if Value, ok := rlpValue.Value.(byte); ok { - return Value - } - - return 0x0 -} - -func (rlpValue *RlpValue) AsBigInt() *big.Int { - if a, ok := rlpValue.Value.([]byte); ok { - b := new(big.Int) - b.SetBytes(a) - return b - } - - return big.NewInt(0) -} - -func (rlpValue *RlpValue) AsString() string { - if a, ok := rlpValue.Value.([]byte); ok { - return string(a) - } else if a, ok := rlpValue.Value.(string); ok { - return a - } else { - //panic(fmt.Sprintf("not string %T: %v", rlpValue.Value, rlpValue.Value)) - } - - return "" -} - -func (rlpValue *RlpValue) AsBytes() []byte { - if a, ok := rlpValue.Value.([]byte); ok { - return a - } - - return make([]byte, 0) -} - -func (rlpValue *RlpValue) AsSlice() []interface{} { - if d, ok := rlpValue.Value.([]interface{}); ok { - return d - } - - return []interface{}{} -} - -func (rlpValue *RlpValue) AsSliceFrom(from int) *RlpValue { - slice := rlpValue.AsSlice() - - return NewRlpValue(slice[from:]) -} - -func (rlpValue *RlpValue) AsSliceTo(to int) *RlpValue { - slice := rlpValue.AsSlice() - - return NewRlpValue(slice[:to]) -} - -func (rlpValue *RlpValue) AsSliceFromTo(from, to int) *RlpValue { - slice := rlpValue.AsSlice() - - return NewRlpValue(slice[from:to]) -} - -// Threat the rlpValueute as a slice -func (rlpValue *RlpValue) Get(idx int) *RlpValue { - if d, ok := rlpValue.Value.([]interface{}); ok { - // Guard for oob - if len(d) <= idx { - return NewRlpValue(nil) - } - - if idx < 0 { - panic("negative idx for Rlp Get") - } - - return NewRlpValue(d[idx]) - } - - // If this wasn't a slice you probably shouldn't be using this function - return NewRlpValue(nil) -} - -func (rlpValue *RlpValue) Cmp(o *RlpValue) bool { - return reflect.DeepEqual(rlpValue.Value, o.Value) -} - -func (rlpValue *RlpValue) Encode() []byte { - return Encode(rlpValue.Value) -} - -func NewRlpValueFromBytes(rlpData []byte) *RlpValue { - if len(rlpData) != 0 { - data, _ := Decode(rlpData, 0) - return NewRlpValue(data) - } - - return NewRlpValue(nil) -} - -// RlpValue value setters -// An empty rlp value is always a list -func EmptyRlpValue() *RlpValue { - return NewRlpValue([]interface{}{}) -} - -func (rlpValue *RlpValue) AppendList() *RlpValue { - list := EmptyRlpValue() - rlpValue.Value = append(rlpValue.AsSlice(), list) - - return list -} - -func (rlpValue *RlpValue) Append(v interface{}) *RlpValue { - rlpValue.Value = append(rlpValue.AsSlice(), v) - - return rlpValue -} - /* func FromBin(data []byte) uint64 { if len(data) == 0 { @@ -351,8 +166,8 @@ func Encode(object interface{}) []byte { if object != nil { switch t := object.(type) { - case *RlpValue: - buff.Write(Encode(t.AsRaw())) + case *Value: + buff.Write(Encode(t.Raw())) // Code dup :-/ case int: buff.Write(Encode(big.NewInt(int64(t)))) -- cgit v1.2.3 From d7eca7bcc12e940f0aa80d45e6e802ba68143b5c Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 18 Feb 2014 01:34:06 +0100 Subject: Rlp update --- ethutil/rlp.go | 8 -------- 1 file changed, 8 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 025d269a0..e633f5f1d 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -86,13 +86,6 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { // TODO Use a bytes.Buffer instead of a raw byte slice. // Cleaner code, and use draining instead of seeking the next bytes to read func Decode(data []byte, pos uint64) (interface{}, uint64) { - /* - if pos > uint64(len(data)-1) { - log.Println(data) - log.Panicf("index out of range %d for data %q, l = %d", pos, data, len(data)) - } - */ - var slice []interface{} char := int(data[pos]) switch { @@ -131,7 +124,6 @@ func Decode(data []byte, pos uint64) (interface{}, uint64) { case char <= 0xff: l := uint64(data[pos]) - 0xf7 - //b := BigD(data[pos+1 : pos+1+l]).Uint64() b := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+l])) pos = pos + l + 1 -- cgit v1.2.3 From c642094cac6ee6fb0215d7510cc57a719c2a2689 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 20 Mar 2014 17:27:26 +0100 Subject: Added encoder interface --- ethutil/rlp.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index e633f5f1d..33ec0d359 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -9,6 +9,10 @@ import ( "math/big" ) +type RlpEncodable interface { + RlpEncode() []byte +} + type RlpEncoder struct { rlpData []byte } -- cgit v1.2.3 From 308c59320c25845f9668e76559b581e2161fec15 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 27 Mar 2014 15:38:55 +0100 Subject: Fixed typo --- ethutil/rlp.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 33ec0d359..e6c75696e 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -57,7 +57,7 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { switch { case char == 0: return nil - case char <= 0x7c: + case char <= 0x7f: return char case char <= 0xb7: -- cgit v1.2.3 From 4f2e9c2640eaa962d085db329221bfd6f1a1799e Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 9 Apr 2014 12:27:25 -0400 Subject: Check for nil --- ethutil/rlp.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index e6c75696e..d95ace425 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -186,7 +186,12 @@ func Encode(object interface{}) []byte { case byte: buff.Write(Encode(big.NewInt(int64(t)))) case *big.Int: - buff.Write(Encode(t.Bytes())) + // Not sure how this is possible while we check for + if t == nil { + buff.WriteByte(0xc0) + } else { + buff.Write(Encode(t.Bytes())) + } case []byte: if len(t) == 1 && t[0] <= 0x7f { buff.Write(t) -- cgit v1.2.3 From 338b6980915c990c6e6287a7249ddd98e6be20eb Mon Sep 17 00:00:00 2001 From: obscuren Date: Sun, 27 Apr 2014 17:15:44 +0200 Subject: Refactoring and added documentation comments --- ethutil/rlp.go | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index d95ace425..69f80a0a6 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -26,16 +26,6 @@ func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte { return Encode(rlpData) } -/* -func FromBin(data []byte) uint64 { - if len(data) == 0 { - return 0 - } - - return FromBin(data[:len(data)-1])*256 + uint64(data[len(data)-1]) -} -*/ - const ( RlpEmptyList = 0x80 RlpEmptyStr = 0x40 -- cgit v1.2.3 From 58a0e8e3e2979b07e9e8f697f947a412ac81e386 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 16 Jun 2014 00:52:10 +0200 Subject: Changed RlpEncodable --- ethutil/rlp.go | 1 + 1 file changed, 1 insertion(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 69f80a0a6..195ef0efb 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -11,6 +11,7 @@ import ( type RlpEncodable interface { RlpEncode() []byte + RlpValue() []interface{} } type RlpEncoder struct { -- cgit v1.2.3 From 6e94c024e476a0e96b81d1cdd60dbb88b723593a Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 29 Jul 2014 23:31:33 +0200 Subject: Added big data test and updating to reader --- ethutil/rlp.go | 139 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 65 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 195ef0efb..333a84927 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -55,8 +55,7 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { return reader.Next(int(char - 0x80)) case char <= 0xbf: - buff := bytes.NewReader(reader.Next(int(char - 0xb8))) - length := ReadVarint(buff) + length := ReadVarInt(reader.Next(int(char - 0xb7))) return reader.Next(int(length)) @@ -72,74 +71,20 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { } return slice - - } - - return slice -} - -// TODO Use a bytes.Buffer instead of a raw byte slice. -// Cleaner code, and use draining instead of seeking the next bytes to read -func Decode(data []byte, pos uint64) (interface{}, uint64) { - var slice []interface{} - char := int(data[pos]) - switch { - case char <= 0x7f: - return data[pos], pos + 1 - - case char <= 0xb7: - b := uint64(data[pos]) - 0x80 - - return data[pos+1 : pos+1+b], pos + 1 + b - - case char <= 0xbf: - b := uint64(data[pos]) - 0xb7 - - b2 := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+b])) - - return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2 - - case char <= 0xf7: - b := uint64(data[pos]) - 0xc0 - prevPos := pos - pos++ - for i := uint64(0); i < b; { - var obj interface{} - - // Get the next item in the data list and append it - obj, prevPos = Decode(data, pos) - slice = append(slice, obj) - - // Increment i by the amount bytes read in the previous - // read - i += (prevPos - pos) - pos = prevPos - } - return slice, pos - case char <= 0xff: - l := uint64(data[pos]) - 0xf7 - b := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+l])) - - pos = pos + l + 1 - - prevPos := b - for i := uint64(0); i < uint64(b); { - var obj interface{} - - obj, prevPos = Decode(data, pos) - slice = append(slice, obj) - - i += (prevPos - pos) - pos = prevPos + length := ReadVarInt(reader.Next(int(char - 0xf7))) + for i := uint64(0); i < length; i++ { + obj := DecodeWithReader(reader) + if obj != nil { + slice = append(slice, obj) + } else { + break + } } - return slice, pos - default: - panic(fmt.Sprintf("byte not supported: %q", char)) } - return slice, 0 + return slice } var ( @@ -223,3 +168,67 @@ func Encode(object interface{}) []byte { return buff.Bytes() } + +// TODO Use a bytes.Buffer instead of a raw byte slice. +// Cleaner code, and use draining instead of seeking the next bytes to read +func Decode(data []byte, pos uint64) (interface{}, uint64) { + var slice []interface{} + char := int(data[pos]) + switch { + case char <= 0x7f: + return data[pos], pos + 1 + + case char <= 0xb7: + b := uint64(data[pos]) - 0x80 + + return data[pos+1 : pos+1+b], pos + 1 + b + + case char <= 0xbf: + b := uint64(data[pos]) - 0xb7 + + b2 := ReadVarInt(data[pos+1 : pos+1+b]) + + return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2 + + case char <= 0xf7: + b := uint64(data[pos]) - 0xc0 + prevPos := pos + pos++ + for i := uint64(0); i < b; { + var obj interface{} + + // Get the next item in the data list and append it + obj, prevPos = Decode(data, pos) + slice = append(slice, obj) + + // Increment i by the amount bytes read in the previous + // read + i += (prevPos - pos) + pos = prevPos + } + return slice, pos + + case char <= 0xff: + l := uint64(data[pos]) - 0xf7 + b := ReadVarInt(data[pos+1 : pos+1+l]) + + pos = pos + l + 1 + + prevPos := b + for i := uint64(0); i < uint64(b); { + var obj interface{} + + obj, prevPos = Decode(data, pos) + slice = append(slice, obj) + + i += (prevPos - pos) + pos = prevPos + } + return slice, pos + + default: + panic(fmt.Sprintf("byte not supported: %q", char)) + } + + return slice, 0 +} -- cgit v1.2.3 From 5ede1224e48fd82961bd4a0b2ec1a3eda0b6d99b Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 1 Aug 2014 10:21:43 +0200 Subject: minor rlp things --- ethutil/rlp.go | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 333a84927..cf7f97ffd 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -32,12 +32,14 @@ const ( RlpEmptyStr = 0x40 ) +const rlpEof = -1 + func Char(c []byte) int { if len(c) > 0 { return int(c[0]) } - return 0 + return rlpEof } func DecodeWithReader(reader *bytes.Buffer) interface{} { @@ -46,8 +48,6 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { // Read the next byte char := Char(reader.Next(1)) switch { - case char == 0: - return nil case char <= 0x7f: return char @@ -63,11 +63,7 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { length := int(char - 0xc0) for i := 0; i < length; i++ { obj := DecodeWithReader(reader) - if obj != nil { - slice = append(slice, obj) - } else { - break - } + slice = append(slice, obj) } return slice @@ -75,13 +71,12 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} { length := ReadVarInt(reader.Next(int(char - 0xf7))) for i := uint64(0); i < length; i++ { obj := DecodeWithReader(reader) - if obj != nil { - slice = append(slice, obj) - } else { - break - } + slice = append(slice, obj) } + + return slice default: + panic(fmt.Sprintf("byte not supported: %q", char)) } return slice -- cgit v1.2.3 From a760ce05b948e89bc564af20599dcf95698ac0eb Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 11 Aug 2014 16:23:38 +0200 Subject: Updated chain for filtering --- ethutil/rlp.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index cf7f97ffd..17ff627eb 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -2,15 +2,16 @@ package ethutil import ( "bytes" - _ "encoding/binary" "fmt" - _ "log" - _ "math" "math/big" ) -type RlpEncodable interface { +type RlpEncode interface { RlpEncode() []byte +} + +type RlpEncodeDecode interface { + RlpEncode RlpValue() []interface{} } -- cgit v1.2.3 From 33a0dec8a157b9687ca6038f4deb011f3f1f7bdc Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 15 Sep 2014 15:42:12 +0200 Subject: Improved catching up and refactored --- ethutil/rlp.go | 2 ++ 1 file changed, 2 insertions(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 17ff627eb..febfb78e1 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -124,6 +124,8 @@ func Encode(object interface{}) []byte { } else { buff.Write(Encode(t.Bytes())) } + case Bytes: + buff.Write(Encode([]byte(t))) case []byte: if len(t) == 1 && t[0] <= 0x7f { buff.Write(t) -- cgit v1.2.3 From 80261c803a82e51413608a3dc5273c982844d135 Mon Sep 17 00:00:00 2001 From: obscuren Date: Fri, 19 Sep 2014 13:19:19 +0200 Subject: Fixed deref ptr --- ethutil/rlp.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index febfb78e1..55406133b 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -15,6 +15,10 @@ type RlpEncodeDecode interface { RlpValue() []interface{} } +func Rlp(encoder RlpEncode) []byte { + return encoder.RlpEncode() +} + type RlpEncoder struct { rlpData []byte } -- cgit v1.2.3 From fb4113dab4df8480c77bdcb707fa6b5408755b79 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 29 Oct 2014 10:34:40 +0100 Subject: PoC 7 updates * Bloom * Block restructure * Receipts --- ethutil/rlp.go | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 55406133b..1fff2b28a 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -15,6 +15,10 @@ type RlpEncodeDecode interface { RlpValue() []interface{} } +type RlpEncodable interface { + RlpData() interface{} +} + func Rlp(encoder RlpEncode) []byte { return encoder.RlpEncode() } @@ -100,6 +104,8 @@ func Encode(object interface{}) []byte { switch t := object.(type) { case *Value: buff.Write(Encode(t.Raw())) + case RlpEncodable: + buff.Write(Encode(t.RlpData())) // Code dup :-/ case int: buff.Write(Encode(big.NewInt(int64(t)))) -- cgit v1.2.3 From b1c58b76a9588a90db5a773a997bb70265c378d3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 17 Dec 2014 12:57:35 +0100 Subject: moved err check --- ethutil/rlp.go | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 1fff2b28a..157dd4dd9 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -2,8 +2,10 @@ package ethutil import ( "bytes" + "encoding/binary" "fmt" "math/big" + "reflect" ) type RlpEncode interface { @@ -97,6 +99,14 @@ var ( zeroRlp = big.NewInt(0x0) ) +func intlen(i int64) (length int) { + for i > 0 { + i = i >> 8 + length++ + } + return +} + func Encode(object interface{}) []byte { var buff bytes.Buffer @@ -168,6 +178,26 @@ func Encode(object interface{}) []byte { } WriteSliceHeader(len(b.Bytes())) buff.Write(b.Bytes()) + default: + // This is how it should have been from the start + // needs refactoring (@fjl) + v := reflect.ValueOf(t) + switch v.Kind() { + case reflect.Slice: + var b bytes.Buffer + for i := 0; i < v.Len(); i++ { + b.Write(Encode(v.Index(i).Interface())) + } + + blen := b.Len() + if blen < 56 { + buff.WriteByte(byte(blen) + 0xc0) + } else { + buff.WriteByte(byte(intlen(int64(blen))) + 0xf7) + binary.Write(&buff, binary.BigEndian, int64(blen)) + } + buff.ReadFrom(&b) + } } } else { // Empty list for nil -- cgit v1.2.3 From df3366d910c2b1ddab986264bc186ca79ba65c4e Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 11:39:24 +0100 Subject: Rlp shouldn't write null bytes --- ethutil/rlp.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'ethutil/rlp.go') diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 157dd4dd9..1bc1a58a7 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -2,7 +2,6 @@ package ethutil import ( "bytes" - "encoding/binary" "fmt" "math/big" "reflect" @@ -193,8 +192,13 @@ func Encode(object interface{}) []byte { if blen < 56 { buff.WriteByte(byte(blen) + 0xc0) } else { - buff.WriteByte(byte(intlen(int64(blen))) + 0xf7) - binary.Write(&buff, binary.BigEndian, int64(blen)) + ilen := byte(intlen(int64(blen))) + buff.WriteByte(ilen + 0xf7) + t := make([]byte, ilen) + for i := byte(0); i < ilen; i++ { + t[ilen-i-1] = byte(blen >> (i * 8)) + } + buff.Write(t) } buff.ReadFrom(&b) } -- cgit v1.2.3