From 52be0fb2c239c2b85ab0a49f7c54a3fb1e8efdaa Mon Sep 17 00:00:00 2001 From: "Daniel A. Nagy" Date: Wed, 11 Feb 2015 19:56:19 +0100 Subject: [PATCH] Felix' changes from PR https://github.com/ethereum/go-ethereum/pull/303 --- bzz/protocol.go | 1 + rlp/encode.go | 52 ++++++++++++++++++++++++++++++++++++++++++++-- rlp/encode_test.go | 22 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 2 deletions(-) diff --git a/bzz/protocol.go b/bzz/protocol.go index f999de68e8..34ff87c9ca 100644 --- a/bzz/protocol.go +++ b/bzz/protocol.go @@ -174,6 +174,7 @@ func runBzzProtocol(netStore *NetStore, p *p2p.Peer, rw p2p.MsgReadWriter) (err func (self *bzzProtocol) handle() error { msg, err := self.rw.ReadMsg() + dpaLogger.Debugf("Incoming MSG: %v", msg) if err != nil { return err } diff --git a/rlp/encode.go b/rlp/encode.go index 689d25dd81..6ae4a123ae 100644 --- a/rlp/encode.go +++ b/rlp/encode.go @@ -32,6 +32,48 @@ type Encoder interface { EncodeRLP(io.Writer) error } +// Flat wraps a value (which must encode as a list) so +// it encodes as the list's elements. +// +// Example: suppose you have defined a type +// +// type foo struct { A, B uint } +// +// Under normal encoding rules, +// +// rlp.Encode(foo{1, 2}) --> 0xC20102 +// +// This function can help you achieve the following encoding: +// +// rlp.Encode(rlp.Flat(foo{1, 2})) --> 0x0102 +func Flat(val interface{}) Encoder { + return flatenc{val} +} + +type flatenc struct{ val interface{} } + +func (e flatenc) EncodeRLP(out io.Writer) error { + // record current output position + var ( + eb = out.(*encbuf) + prevstrsize = len(eb.str) + prevnheads = len(eb.lheads) + ) + if err := eb.encode(e.val); err != nil { + return err + } + // check that a new list header has appeared + if len(eb.lheads) == prevnheads || eb.lheads[prevnheads].offset == prevstrsize-1 { + return fmt.Errorf("rlp.Flat: %T did not encode as list", e.val) + } + // remove the new list header + newhead := eb.lheads[prevnheads] + copy(eb.lheads[prevnheads:], eb.lheads[prevnheads+1:]) + eb.lheads = eb.lheads[:len(eb.lheads)-1] + eb.lhsize -= newhead.tagsize() + return nil +} + // Encode writes the RLP encoding of val to w. Note that Encode may // perform many small writes in some cases. Consider making w // buffered. @@ -123,6 +165,13 @@ func (head *listhead) encode(buf []byte) []byte { } } +func (head *listhead) tagsize() int { + if head.size < 56 { + return 1 + } + return 1 + intsize(uint64(head.size)) +} + func newencbuf() *encbuf { return &encbuf{sizebuf: make([]byte, 9)} } @@ -280,7 +329,6 @@ func (r *encReader) next() []byte { var ( encoderInterface = reflect.TypeOf(new(Encoder)).Elem() - emptyInterface = reflect.TypeOf(new(interface{})).Elem() big0 = big.NewInt(0) ) @@ -292,7 +340,7 @@ func makeWriter(typ reflect.Type) (writer, error) { return writeEncoder, nil case kind != reflect.Ptr && reflect.PtrTo(typ).Implements(encoderInterface): return writeEncoderNoPtr, nil - case typ == emptyInterface: + case kind == reflect.Interface: return writeInterface, nil case typ.AssignableTo(reflect.PtrTo(bigInt)): return writeBigIntPtr, nil diff --git a/rlp/encode_test.go b/rlp/encode_test.go index 8dba3671bb..9b30856589 100644 --- a/rlp/encode_test.go +++ b/rlp/encode_test.go @@ -32,9 +32,19 @@ func (e byteEncoder) EncodeRLP(w io.Writer) error { return nil } +type encodableReader struct { + A, B uint +} + +func (e *encodableReader) Read(b []byte) (int, error) { + panic("called") +} + var ( _ = Encoder(&testEncoder{}) _ = Encoder(byteEncoder(0)) + + reader io.Reader = &encodableReader{1, 2} ) type encTest struct { @@ -167,6 +177,15 @@ var encTests = []encTest{ {val: &recstruct{5, nil}, output: "C205C0"}, {val: &recstruct{5, &recstruct{4, &recstruct{3, nil}}}, output: "C605C404C203C0"}, + // flat + {val: Flat(uint(1)), error: "rlp.Flat: uint did not encode as list"}, + {val: Flat(simplestruct{A: 3, B: "foo"}), output: "0383666F6F"}, + { + // value generates more list headers after the Flat + val: []interface{}{"foo", []uint{1, 2}, Flat([]uint{3, 4}), []uint{5, 6}, "bar"}, + output: "D083666F6FC201020304C2050683626172", + }, + // nil {val: (*uint)(nil), output: "80"}, {val: (*string)(nil), output: "80"}, @@ -176,6 +195,9 @@ var encTests = []encTest{ {val: (*[]struct{ uint })(nil), output: "C0"}, {val: (*interface{})(nil), output: "C0"}, + // interfaces + {val: []io.Reader{reader}, output: "C3C20102"}, // the contained value is a struct + // Encoder {val: (*testEncoder)(nil), output: "00000000"}, {val: &testEncoder{}, output: "00010001000100010001"},