github.com/klaytn/klaytn@v1.10.2/blockchain/types/account/account_serializer.go (about) 1 // Copyright 2019 The klaytn Authors 2 // This file is part of the klaytn library. 3 // 4 // The klaytn library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The klaytn library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>. 16 17 package account 18 19 import ( 20 "encoding/json" 21 "io" 22 23 "github.com/klaytn/klaytn/rlp" 24 ) 25 26 // AccountSerializer serializes an Account object using RLP/JSON. 27 type AccountSerializer struct { 28 accType AccountType 29 account Account 30 } 31 32 // accountJSON is an internal data structure for JSON serialization. 33 type accountJSON struct { 34 AccType AccountType `json:"accType"` 35 Account json.RawMessage `json:"account"` 36 } 37 38 // NewAccountSerializer creates a new AccountSerializer object with default values. 39 // This returned object will be used for decoding. 40 func NewAccountSerializer() *AccountSerializer { 41 return &AccountSerializer{} 42 } 43 44 // NewAccountSerializerWithAccount creates a new AccountSerializer object with the given account. 45 func NewAccountSerializerWithAccount(a Account) *AccountSerializer { 46 return &AccountSerializer{a.Type(), a} 47 } 48 49 func (ser *AccountSerializer) EncodeRLP(w io.Writer) error { 50 // If it is a LegacyAccount object, do not encode the account type. 51 if ser.accType == LegacyAccountType { 52 return rlp.Encode(w, ser.account.(*LegacyAccount)) 53 } 54 55 if err := rlp.Encode(w, ser.accType); err != nil { 56 return err 57 } 58 59 return rlp.Encode(w, ser.account) 60 } 61 62 func (ser *AccountSerializer) GetAccount() Account { 63 return ser.account 64 } 65 66 func (ser *AccountSerializer) DecodeRLP(s *rlp.Stream) error { 67 if err := s.Decode(&ser.accType); err != nil { 68 // fallback to decoding a LegacyAccount object. 69 acc := newLegacyAccount() 70 if err := s.Decode(acc); err != nil { 71 return err 72 } 73 ser.accType = LegacyAccountType 74 ser.account = acc 75 return nil 76 } 77 78 var err error 79 ser.account, err = NewAccountWithType(ser.accType) 80 if err != nil { 81 return err 82 } 83 84 return s.Decode(ser.account) 85 } 86 87 func (ser *AccountSerializer) MarshalJSON() ([]byte, error) { 88 // if it is a legacyAccount object, do not marshal the account type. 89 if ser.accType == LegacyAccountType { 90 return json.Marshal(ser.account) 91 } 92 b, err := json.Marshal(ser.account) 93 if err != nil { 94 return nil, err 95 } 96 97 return json.Marshal(&accountJSON{ser.accType, b}) 98 } 99 100 func (ser *AccountSerializer) UnmarshalJSON(b []byte) error { 101 dec := &accountJSON{} 102 103 if err := json.Unmarshal(b, dec); err != nil { 104 return err 105 } 106 107 if len(dec.Account) == 0 { 108 // fallback to unmarshal a LegacyAccount object. 109 acc := newLegacyAccount() 110 if err := json.Unmarshal(b, acc); err != nil { 111 return err 112 } 113 ser.accType = LegacyAccountType 114 ser.account = acc 115 116 return nil 117 118 } 119 120 ser.accType = dec.AccType 121 122 var err error 123 ser.account, err = NewAccountWithType(ser.accType) 124 if err != nil { 125 return err 126 } 127 128 return json.Unmarshal(dec.Account, ser.account) 129 }