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 }