From 85a7f74f836742964b0bcd0aa89e08e062be1f81 Mon Sep 17 00:00:00 2001 From: Brannon King Date: Wed, 28 Jul 2021 19:38:24 -0400 Subject: [PATCH] switch node encoding to mum (via enkodo) --- claimtrie/change/change.go | 53 +++++++++++++++++-- claimtrie/node/noderepo/pebble.go | 85 +++++-------------------------- go.mod | 1 + go.sum | 2 + 4 files changed, 65 insertions(+), 76 deletions(-) diff --git a/claimtrie/change/change.go b/claimtrie/change/change.go index e207d8e1..87217969 100644 --- a/claimtrie/change/change.go +++ b/claimtrie/change/change.go @@ -1,8 +1,11 @@ package change -import "github.com/btcsuite/btcd/wire" +import ( + "github.com/btcsuite/btcd/wire" + "github.com/mojura/enkodo" +) -type ChangeType int +type ChangeType int32 const ( AddClaim ChangeType = iota @@ -16,7 +19,7 @@ type Change struct { Type ChangeType Height int32 - Name []byte + Name []byte `msg:"-"` ClaimID ClaimID OutPoint wire.OutPoint Amount int64 @@ -50,3 +53,47 @@ func (c Change) SetAmount(amt int64) Change { c.Amount = amt return c } + +func (c *Change) MarshalEnkodo(enc *enkodo.Encoder) error { + enc.Bytes(c.ClaimID[:]) + enc.Bytes(c.OutPoint.Hash[:]) + enc.Uint32(c.OutPoint.Index) + enc.Int32(int32(c.Type)) + enc.Int32(c.Height) + enc.Int32(c.ActiveHeight) + enc.Int32(c.VisibleHeight) + enc.Int64(c.Amount) + if c.SpentChildren != nil { + enc.Int32(int32(len(c.SpentChildren))) + for key := range c.SpentChildren { + enc.String(key) + } + } else { + enc.Int32(0) + } + return nil +} + +func (c *Change) UnmarshalEnkodo(dec *enkodo.Decoder) error { + id := c.ClaimID[:] + err := dec.Bytes(&id) + op := c.OutPoint.Hash[:] + err = dec.Bytes(&op) + c.OutPoint.Index, err = dec.Uint32() + t, err := dec.Int32() + c.Type = ChangeType(t) + c.Height, err = dec.Int32() + c.ActiveHeight, err = dec.Int32() + c.VisibleHeight, err = dec.Int32() + c.Amount, err = dec.Int64() + keys, err := dec.Int32() + if keys > 0 { + c.SpentChildren = map[string]bool{} + } + for keys > 0 { + keys-- + key, _ := dec.String() + c.SpentChildren[key] = true + } + return err +} diff --git a/claimtrie/node/noderepo/pebble.go b/claimtrie/node/noderepo/pebble.go index 530a2271..7578a84d 100644 --- a/claimtrie/node/noderepo/pebble.go +++ b/claimtrie/node/noderepo/pebble.go @@ -2,81 +2,18 @@ package noderepo import ( "bytes" - "reflect" + "github.com/mojura/enkodo" "sort" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/claimtrie/change" - "github.com/btcsuite/btcd/claimtrie/node" - "github.com/btcsuite/btcd/wire" - "github.com/cockroachdb/pebble" "github.com/pkg/errors" - "github.com/vmihailenco/msgpack/v5" ) type Pebble struct { db *pebble.DB } -func init() { - claimEncoder := func(e *msgpack.Encoder, v reflect.Value) error { - claim := v.Interface().(change.ClaimID) - return e.EncodeBytes(claim[:]) - } - claimDecoder := func(e *msgpack.Decoder, v reflect.Value) error { - data, err := e.DecodeBytes() - if err != nil { - return err - } - if len(data) > change.ClaimIDSize { - id, err := change.NewIDFromString(string(data)) - if err != nil { - return err - } - v.Set(reflect.ValueOf(id)) - } else { - id := change.ClaimID{} - copy(id[:], data) - v.Set(reflect.ValueOf(id)) - } - return nil - } - msgpack.Register(change.ClaimID{}, claimEncoder, claimDecoder) - - opEncoder := func(e *msgpack.Encoder, v reflect.Value) error { - op := v.Interface().(wire.OutPoint) - if err := e.EncodeBytes(op.Hash[:]); err != nil { - return err - } - return e.EncodeUint32(op.Index) - } - opDecoder := func(e *msgpack.Decoder, v reflect.Value) error { - data, err := e.DecodeBytes() - if err != nil { - return err - } - if len(data) > chainhash.HashSize { - // try the older data: - op := node.NewOutPointFromString(string(data)) - v.Set(reflect.ValueOf(*op)) - } else { - index, err := e.DecodeUint32() - if err != nil { - return err - } - hash, err := chainhash.NewHash(data) - if err != nil { - return err - } - op := wire.OutPoint{Hash: *hash, Index: index} - v.Set(reflect.ValueOf(op)) - } - return nil - } - msgpack.Register(wire.OutPoint{}, opEncoder, opDecoder) -} - func NewPebble(path string) (*Pebble, error) { db, err := pebble.Open(path, &pebble.Options{Cache: pebble.NewCache(32 << 20), BytesPerSync: 4 << 20}) @@ -91,16 +28,18 @@ func (repo *Pebble) AppendChanges(changes []change.Change) error { batch := repo.db.NewBatch() defer batch.Close() - // TODO: switch to buffer pool and reuse encoder + buffer := bytes.NewBuffer(nil) + encoder := enkodo.NewWriter(buffer) + defer encoder.Close() + for _, chg := range changes { - name := chg.Name - chg.Name = nil // don't waste the storage space on this (annotation a better approach?) - value, err := msgpack.Marshal(chg) + buffer.Reset() + err := encoder.Encode(&chg) if err != nil { return errors.Wrap(err, "in marshaller") } - err = batch.Merge(name, value, pebble.NoSync) + err = batch.Merge(chg.Name, buffer.Bytes(), pebble.NoSync) if err != nil { return errors.Wrap(err, "in merge") } @@ -123,14 +62,14 @@ func (repo *Pebble) LoadChanges(name []byte) ([]change.Change, error) { func unmarshalChanges(name, data []byte) ([]change.Change, error) { var changes []change.Change - dec := msgpack.GetDecoder() - defer msgpack.PutDecoder(dec) reader := bytes.NewReader(data) - dec.Reset(reader) + decoder := enkodo.NewReader(reader) + defer decoder.Close() + for reader.Len() > 0 { var chg change.Change - err := dec.Decode(&chg) + err := decoder.Decode(&chg) if err != nil { return nil, errors.Wrap(err, "in decode") } diff --git a/go.mod b/go.mod index b91fe5d1..2475d8ef 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/felixge/fgprof v0.9.1 github.com/jessevdk/go-flags v1.4.0 github.com/jrick/logrotate v1.0.0 + github.com/mojura/enkodo v0.5.5 // indirect github.com/pkg/errors v0.9.1 github.com/shirou/gopsutil/v3 v3.21.6 github.com/spf13/cobra v1.1.3 diff --git a/go.sum b/go.sum index 4ee3f148..7b8bc2fc 100644 --- a/go.sum +++ b/go.sum @@ -268,6 +268,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mojura/enkodo v0.5.5 h1:bkjksvk8XeO0SLjtkUzvqS9oJlAIO5WFibSCSn9o/58= +github.com/mojura/enkodo v0.5.5/go.mod h1:9/1bBkNTRhwLPSFAo0uG1a+numnsZMxNIzLdWxlFl+g= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM=