github.com/decred/dcrlnd@v0.7.6/channeldb/migration21/legacy/legacy_codec.go (about)

     1  package legacy
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/decred/dcrd/chaincfg/chainhash"
     9  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
    10  	"github.com/decred/dcrd/dcrutil/v4"
    11  	"github.com/decred/dcrd/wire"
    12  	lnwire "github.com/decred/dcrlnd/channeldb/migration/lnwire21"
    13  	"github.com/decred/dcrlnd/channeldb/migration21/common"
    14  	"github.com/decred/dcrlnd/keychain"
    15  	"github.com/decred/dcrlnd/shachain"
    16  )
    17  
    18  var (
    19  	// Big endian is the preferred byte order, due to cursor scans over
    20  	// integer keys iterating in order.
    21  	byteOrder = binary.BigEndian
    22  )
    23  
    24  // writeOutpoint writes an outpoint to the passed writer using the minimal
    25  // amount of bytes possible.
    26  func writeOutpoint(w io.Writer, o *wire.OutPoint) error {
    27  	if _, err := w.Write(o.Hash[:]); err != nil {
    28  		return err
    29  	}
    30  	if err := binary.Write(w, byteOrder, o.Index); err != nil {
    31  		return err
    32  	}
    33  
    34  	// Note: this is decred-only.
    35  	if err := binary.Write(w, byteOrder, o.Tree); err != nil {
    36  		return err
    37  	}
    38  
    39  	return nil
    40  }
    41  
    42  // readOutpoint reads an outpoint from the passed reader that was previously
    43  // written using the writeOutpoint struct.
    44  func readOutpoint(r io.Reader, o *wire.OutPoint) error {
    45  	if _, err := io.ReadFull(r, o.Hash[:]); err != nil {
    46  		return err
    47  	}
    48  	if err := binary.Read(r, byteOrder, &o.Index); err != nil {
    49  		return err
    50  	}
    51  
    52  	// Note: this is decred-only.
    53  	if err := binary.Read(r, byteOrder, &o.Tree); err != nil {
    54  		return err
    55  	}
    56  
    57  	return nil
    58  }
    59  
    60  // UnknownElementType is an error returned when the codec is unable to encode or
    61  // decode a particular type.
    62  type UnknownElementType struct {
    63  	method  string
    64  	element interface{}
    65  }
    66  
    67  // NewUnknownElementType creates a new UnknownElementType error from the passed
    68  // method name and element.
    69  func NewUnknownElementType(method string, el interface{}) UnknownElementType {
    70  	return UnknownElementType{method: method, element: el}
    71  }
    72  
    73  // Error returns the name of the method that encountered the error, as well as
    74  // the type that was unsupported.
    75  func (e UnknownElementType) Error() string {
    76  	return fmt.Sprintf("Unknown type in %s: %T", e.method, e.element)
    77  }
    78  
    79  // WriteElement is a one-stop shop to write the big endian representation of
    80  // any element which is to be serialized for storage on disk. The passed
    81  // io.Writer should be backed by an appropriately sized byte slice, or be able
    82  // to dynamically expand to accommodate additional data.
    83  func WriteElement(w io.Writer, element interface{}) error {
    84  	switch e := element.(type) {
    85  	case keychain.KeyDescriptor:
    86  		if err := binary.Write(w, byteOrder, e.Family); err != nil {
    87  			return err
    88  		}
    89  		if err := binary.Write(w, byteOrder, e.Index); err != nil {
    90  			return err
    91  		}
    92  
    93  		if e.PubKey != nil {
    94  			if err := binary.Write(w, byteOrder, true); err != nil {
    95  				return fmt.Errorf("error writing serialized element: %s", err)
    96  			}
    97  
    98  			return WriteElement(w, e.PubKey)
    99  		}
   100  
   101  		return binary.Write(w, byteOrder, false)
   102  
   103  	case chainhash.Hash:
   104  		if _, err := w.Write(e[:]); err != nil {
   105  			return err
   106  		}
   107  
   108  	case common.ClosureType:
   109  		if err := binary.Write(w, byteOrder, e); err != nil {
   110  			return err
   111  		}
   112  
   113  	case wire.OutPoint:
   114  		return writeOutpoint(w, &e)
   115  
   116  	case lnwire.ShortChannelID:
   117  		if err := binary.Write(w, byteOrder, e.ToUint64()); err != nil {
   118  			return err
   119  		}
   120  
   121  	case lnwire.ChannelID:
   122  		if _, err := w.Write(e[:]); err != nil {
   123  			return err
   124  		}
   125  
   126  	case int64, uint64:
   127  		if err := binary.Write(w, byteOrder, e); err != nil {
   128  			return err
   129  		}
   130  
   131  	case uint32:
   132  		if err := binary.Write(w, byteOrder, e); err != nil {
   133  			return err
   134  		}
   135  
   136  	case int32:
   137  		if err := binary.Write(w, byteOrder, e); err != nil {
   138  			return err
   139  		}
   140  
   141  	case uint16:
   142  		if err := binary.Write(w, byteOrder, e); err != nil {
   143  			return err
   144  		}
   145  
   146  	case uint8:
   147  		if err := binary.Write(w, byteOrder, e); err != nil {
   148  			return err
   149  		}
   150  
   151  	case bool:
   152  		if err := binary.Write(w, byteOrder, e); err != nil {
   153  			return err
   154  		}
   155  
   156  	case dcrutil.Amount:
   157  		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
   158  			return err
   159  		}
   160  
   161  	case lnwire.MilliAtom:
   162  		if err := binary.Write(w, byteOrder, uint64(e)); err != nil {
   163  			return err
   164  		}
   165  
   166  	case *secp256k1.PrivateKey:
   167  		b := e.Serialize()
   168  		if _, err := w.Write(b); err != nil {
   169  			return err
   170  		}
   171  
   172  	case *secp256k1.PublicKey:
   173  		b := e.SerializeCompressed()
   174  		if _, err := w.Write(b); err != nil {
   175  			return err
   176  		}
   177  
   178  	case shachain.Producer:
   179  		return e.Encode(w)
   180  
   181  	case shachain.Store:
   182  		return e.Encode(w)
   183  
   184  	case *wire.MsgTx:
   185  		return e.Serialize(w)
   186  
   187  	case [32]byte:
   188  		if _, err := w.Write(e[:]); err != nil {
   189  			return err
   190  		}
   191  
   192  	case []byte:
   193  		if err := wire.WriteVarBytes(w, 0, e); err != nil {
   194  			return err
   195  		}
   196  
   197  	case lnwire.Message:
   198  		if _, err := lnwire.WriteMessage(w, e, 0); err != nil {
   199  			return err
   200  		}
   201  
   202  	case lnwire.FundingFlag:
   203  		if err := binary.Write(w, byteOrder, e); err != nil {
   204  			return err
   205  		}
   206  
   207  	default:
   208  		return UnknownElementType{"WriteElement", e}
   209  	}
   210  
   211  	return nil
   212  }
   213  
   214  // WriteElements is writes each element in the elements slice to the passed
   215  // io.Writer using WriteElement.
   216  func WriteElements(w io.Writer, elements ...interface{}) error {
   217  	for _, element := range elements {
   218  		err := WriteElement(w, element)
   219  		if err != nil {
   220  			return err
   221  		}
   222  	}
   223  	return nil
   224  }
   225  
   226  // ReadElement is a one-stop utility function to deserialize any datastructure
   227  // encoded using the serialization format of the database.
   228  func ReadElement(r io.Reader, element interface{}) error {
   229  	switch e := element.(type) {
   230  	case *chainhash.Hash:
   231  		if _, err := io.ReadFull(r, e[:]); err != nil {
   232  			return err
   233  		}
   234  
   235  	case *wire.OutPoint:
   236  		return readOutpoint(r, e)
   237  
   238  	case *lnwire.ShortChannelID:
   239  		var a uint64
   240  		if err := binary.Read(r, byteOrder, &a); err != nil {
   241  			return err
   242  		}
   243  		*e = lnwire.NewShortChanIDFromInt(a)
   244  
   245  	case *lnwire.ChannelID:
   246  		if _, err := io.ReadFull(r, e[:]); err != nil {
   247  			return err
   248  		}
   249  
   250  	case *int64, *uint64:
   251  		if err := binary.Read(r, byteOrder, e); err != nil {
   252  			return err
   253  		}
   254  
   255  	case *uint32:
   256  		if err := binary.Read(r, byteOrder, e); err != nil {
   257  			return err
   258  		}
   259  
   260  	case *int32:
   261  		if err := binary.Read(r, byteOrder, e); err != nil {
   262  			return err
   263  		}
   264  
   265  	case *uint16:
   266  		if err := binary.Read(r, byteOrder, e); err != nil {
   267  			return err
   268  		}
   269  
   270  	case *uint8:
   271  		if err := binary.Read(r, byteOrder, e); err != nil {
   272  			return err
   273  		}
   274  
   275  	case *bool:
   276  		if err := binary.Read(r, byteOrder, e); err != nil {
   277  			return err
   278  		}
   279  
   280  	case *dcrutil.Amount:
   281  		var a uint64
   282  		if err := binary.Read(r, byteOrder, &a); err != nil {
   283  			return err
   284  		}
   285  
   286  		*e = dcrutil.Amount(a)
   287  
   288  	case *lnwire.MilliAtom:
   289  		var a uint64
   290  		if err := binary.Read(r, byteOrder, &a); err != nil {
   291  			return err
   292  		}
   293  
   294  		*e = lnwire.MilliAtom(a)
   295  
   296  	case **secp256k1.PrivateKey:
   297  		var b [secp256k1.PrivKeyBytesLen]byte
   298  		if _, err := io.ReadFull(r, b[:]); err != nil {
   299  			return err
   300  		}
   301  
   302  		priv := secp256k1.PrivKeyFromBytes(b[:])
   303  		*e = priv
   304  
   305  	case **secp256k1.PublicKey:
   306  		var b [secp256k1.PubKeyBytesLenCompressed]byte
   307  		if _, err := io.ReadFull(r, b[:]); err != nil {
   308  			return err
   309  		}
   310  
   311  		pubKey, err := secp256k1.ParsePubKey(b[:])
   312  		if err != nil {
   313  			return err
   314  		}
   315  		*e = pubKey
   316  
   317  	case *shachain.Producer:
   318  		var root [32]byte
   319  		if _, err := io.ReadFull(r, root[:]); err != nil {
   320  			return err
   321  		}
   322  
   323  		// TODO(roasbeef): remove
   324  		producer, err := shachain.NewRevocationProducerFromBytes(root[:])
   325  		if err != nil {
   326  			return err
   327  		}
   328  
   329  		*e = producer
   330  
   331  	case *shachain.Store:
   332  		store, err := shachain.NewRevocationStoreFromBytes(r)
   333  		if err != nil {
   334  			return err
   335  		}
   336  
   337  		*e = store
   338  
   339  	case **wire.MsgTx:
   340  		tx := wire.NewMsgTx()
   341  		if err := tx.Deserialize(r); err != nil {
   342  			return err
   343  		}
   344  
   345  		*e = tx
   346  
   347  	case *[32]byte:
   348  		if _, err := io.ReadFull(r, e[:]); err != nil {
   349  			return err
   350  		}
   351  
   352  	case *[]byte:
   353  		bytes, err := wire.ReadVarBytes(r, 0, 66000, "[]byte")
   354  		if err != nil {
   355  			return err
   356  		}
   357  
   358  		*e = bytes
   359  
   360  	case *lnwire.Message:
   361  		msg, err := lnwire.ReadMessage(r, 0)
   362  		if err != nil {
   363  			return err
   364  		}
   365  
   366  		*e = msg
   367  
   368  	case *lnwire.FundingFlag:
   369  		if err := binary.Read(r, byteOrder, e); err != nil {
   370  			return err
   371  		}
   372  
   373  	case *common.ClosureType:
   374  		if err := binary.Read(r, byteOrder, e); err != nil {
   375  			return err
   376  		}
   377  
   378  	case *keychain.KeyDescriptor:
   379  		if err := binary.Read(r, byteOrder, &e.Family); err != nil {
   380  			return err
   381  		}
   382  		if err := binary.Read(r, byteOrder, &e.Index); err != nil {
   383  			return err
   384  		}
   385  
   386  		var hasPubKey bool
   387  		if err := binary.Read(r, byteOrder, &hasPubKey); err != nil {
   388  			return err
   389  		}
   390  
   391  		if hasPubKey {
   392  			return ReadElement(r, &e.PubKey)
   393  		}
   394  
   395  	default:
   396  		return UnknownElementType{"ReadElement", e}
   397  	}
   398  
   399  	return nil
   400  }
   401  
   402  // ReadElements deserializes a variable number of elements into the passed
   403  // io.Reader, with each element being deserialized according to the ReadElement
   404  // function.
   405  func ReadElements(r io.Reader, elements ...interface{}) error {
   406  	for _, element := range elements {
   407  		err := ReadElement(r, element)
   408  		if err != nil {
   409  			return err
   410  		}
   411  	}
   412  	return nil
   413  }