Skip to content

Commit

Permalink
Stripped all support for encoding maps, since it's not blockchain com…
Browse files Browse the repository at this point in the history
…patible.

nodeos never encodes and specifically prescribes not to encode maps. Their
encoding is not deterministic, and that's a no go on a blockchain.
  • Loading branch information
abourget committed Nov 13, 2018
1 parent f6ac2eb commit 1debc39
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 101 deletions.
20 changes: 0 additions & 20 deletions decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -370,26 +370,6 @@ func (d *Decoder) Decode(v interface{}) (err error) {
return
}

case reflect.Map:
var l uint64
if l, err = d.ReadUvarint64(); err != nil {
return
}
kt := t.Key()
vt := t.Elem()
rv.Set(reflect.MakeMap(t))
for i := 0; i < int(l); i++ {
kv := reflect.Indirect(reflect.New(kt))
if err = d.Decode(kv.Addr().Interface()); err != nil {
return
}
vv := reflect.Indirect(reflect.New(vt))
if err = d.Decode(vv.Addr().Interface()); err != nil {
return
}
rv.SetMapIndex(kv, vv)
}

default:
return errors.New("decode, unsupported type " + t.String())
}
Expand Down
83 changes: 21 additions & 62 deletions decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,14 +331,14 @@ func TestDecoder_Time(t *testing.T) {
}

type EncodeTestStruct struct {
F1 string
F2 int16
F3 uint16
F4 uint32
F5 Checksum256
F6 []string
F7 [2]string
F8 map[string]string
F1 string
F2 int16
F3 uint16
F4 uint32
F5 Checksum256
F6 []string
F7 [2]string
// F8 map[string]string
F9 ecc.PublicKey
F10 ecc.Signature
F11 byte
Expand All @@ -359,16 +359,17 @@ func TestDecoder_Encode(t *testing.T) {
tstamp := Tstamp{Time: time.Unix(0, now.UnixNano())}
blockts := BlockTimestamp{time.Unix(now.Unix(), 0)}
s := &EncodeTestStruct{
F1: "abc",
F2: -75,
F3: 99,
F4: 999,
F5: bytes.Repeat([]byte{0}, 32),
F6: []string{"def", "789"},
F7: [2]string{"foo", "bar"},
F8: map[string]string{"foo": "bar", "hello": "you"},
F9: ecc.PublicKey{Curve: ecc.CurveK1, Content: bytes.Repeat([]byte{0}, 33)},
F10: ecc.Signature{Curve: ecc.CurveK1, Content: bytes.Repeat([]byte{0}, 65)},
F1: "abc",
F2: -75,
F3: 99,
F4: 999,
F5: bytes.Repeat([]byte{0}, 32),
F6: []string{"def", "789"},
F7: [2]string{"foo", "bar"},
// maps don't serialize deterministically.. we no want that.
// F8: map[string]string{"foo": "bar", "hello": "you"},
F9: ecc.PublicKey{Curve: ecc.CurveK1, Content: make([]byte, 33)},
F10: ecc.Signature{Curve: ecc.CurveK1, Content: make([]byte, 65)},
F11: byte(1),
F12: uint64(87),
F13: []byte{1, 2, 3, 4, 5},
Expand All @@ -383,7 +384,7 @@ func TestDecoder_Encode(t *testing.T) {
enc := NewEncoder(buf)
assert.NoError(t, enc.Encode(s))

assert.Equal(t, "03616263b5ff6300e7030000000000000000000000000000000000000000000000000000000000000000000002036465660337383903666f6f036261720203666f6f036261720568656c6c6f03796f750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001570000000000000005010203040504ae0f517acd57150b973d23e70701a08601000000000004454f5300000000", hex.EncodeToString(buf.Bytes()))
assert.Equal(t, "03616263b5ff6300e7030000000000000000000000000000000000000000000000000000000000000000000002036465660337383903666f6f036261720000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001570000000000000005010203040504ae0f517acd57150b973d23e70701a08601000000000004454f5300000000", hex.EncodeToString(buf.Bytes()))

decoder := NewDecoder(buf.Bytes())
assert.NoError(t, decoder.Decode(s))
Expand All @@ -395,7 +396,7 @@ func TestDecoder_Encode(t *testing.T) {
assert.Equal(t, Checksum256(bytes.Repeat([]byte{0}, 32)), s.F5)
assert.Equal(t, []string{"def", "789"}, s.F6)
assert.Equal(t, [2]string{"foo", "bar"}, s.F7)
assert.Equal(t, map[string]string{"foo": "bar", "hello": "you"}, s.F8)
// assert.Equal(t, map[string]string{"foo": "bar", "hello": "you"}, s.F8)
assert.Equal(t, ecc.PublicKey{Curve: ecc.CurveK1, Content: bytes.Repeat([]byte{0}, 33)}, s.F9)
assert.Equal(t, ecc.Signature{Curve: ecc.CurveK1, Content: bytes.Repeat([]byte{0}, 65)}, s.F10)
assert.Equal(t, byte(1), s.F11)
Expand Down Expand Up @@ -473,37 +474,6 @@ func TestDecoder_Decode_Struct_Err(t *testing.T) {

}

func TestDecoder_Decode_Map_Err(t *testing.T) {

buf := new(bytes.Buffer)
enc := NewEncoder(buf)

decoder := NewDecoder(buf.Bytes())
var m map[string]string
err := decoder.Decode(&m)
assert.Equal(t, err, ErrVarIntBufferSize)

enc.writeUVarInt(1)
decoder = NewDecoder(buf.Bytes())
err = decoder.Decode(&m)
assert.Equal(t, err, ErrVarIntBufferSize)
}

func TestDecoder_Decode_Bad_Map(t *testing.T) {

buf := new(bytes.Buffer)
var m map[string]time.Duration
enc := NewEncoder(buf)
enc.writeUVarInt(1)
enc.writeString("foo")
enc.writeString("bar")

decoder := NewDecoder(buf.Bytes())
err := decoder.Decode(&m)
assert.EqualError(t, err, "decode, unsupported type time.Duration")

}

func TestEncoder_Encode_array_error(t *testing.T) {

decoder := NewDecoder([]byte{1})
Expand Down Expand Up @@ -532,17 +502,6 @@ func TestEncoder_Encode_slide_error(t *testing.T) {
assert.EqualError(t, err, "Encode: unsupported type time.Duration")

}
func TestEncoder_Encode_map_error(t *testing.T) {

buf := new(bytes.Buffer)
enc := NewEncoder(buf)
err := enc.Encode(map[string]time.Duration{"key": time.Duration(0)})
assert.EqualError(t, err, "Encode: unsupported type time.Duration")
err = enc.Encode(map[time.Duration]string{time.Duration(0): "key"})
assert.EqualError(t, err, "Encode: unsupported type time.Duration")

}

func TestEncoder_Encode_struct_error(t *testing.T) {

s := struct {
Expand Down
19 changes: 0 additions & 19 deletions encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,25 +216,6 @@ func (e *Encoder) Encode(v interface{}) (err error) {
}
}

case reflect.Map:
// FIXME: it doesn't make sense to encode a map.. it's an
// invalid format for the blockchain and cannot be
// reconstructed when serialized in binary.
l := rv.Len()
if err = e.writeUVarInt(l); err != nil {
return
}
encoderLog.Debug("map", zap.Int("length", l), typeField("type", v))

for _, key := range rv.MapKeys() {
value := rv.MapIndex(key)
if err = e.Encode(key.Interface()); err != nil {
return err
}
if err = e.Encode(value.Interface()); err != nil {
return err
}
}
default:
return errors.New("Encode: unsupported type " + t.String())
}
Expand Down

0 comments on commit 1debc39

Please sign in to comment.