github.com/iotexproject/iotex-core@v1.14.1-rc1/action/envelope.go (about) 1 package action 2 3 import ( 4 "math/big" 5 6 "github.com/iotexproject/iotex-proto/golang/iotextypes" 7 "github.com/pkg/errors" 8 9 "github.com/iotexproject/iotex-core/pkg/log" 10 ) 11 12 type ( 13 // Envelope defines an envelope wrapped on action with some envelope metadata. 14 Envelope interface { 15 Version() uint32 16 Nonce() uint64 17 ChainID() uint32 18 GasLimit() uint64 19 GasPrice() *big.Int 20 Destination() (string, bool) 21 Cost() (*big.Int, error) 22 IntrinsicGas() (uint64, error) 23 Action() Action 24 Proto() *iotextypes.ActionCore 25 LoadProto(pbAct *iotextypes.ActionCore) error 26 SetNonce(n uint64) 27 SetChainID(chainID uint32) 28 } 29 30 envelope struct { 31 version uint32 32 chainID uint32 33 nonce uint64 34 gasLimit uint64 35 gasPrice *big.Int 36 payload actionPayload 37 } 38 ) 39 40 // Version returns the version 41 func (elp *envelope) Version() uint32 { return elp.version } 42 43 // ChainID return the chainID value 44 func (elp *envelope) ChainID() uint32 { return elp.chainID } 45 46 // Nonce returns the nonce 47 func (elp *envelope) Nonce() uint64 { return elp.nonce } 48 49 // Destination returns the destination address 50 func (elp *envelope) Destination() (string, bool) { 51 r, ok := elp.payload.(hasDestination) 52 if !ok { 53 return "", false 54 } 55 56 return r.Destination(), true 57 } 58 59 // GasLimit returns the gas limit 60 func (elp *envelope) GasLimit() uint64 { return elp.gasLimit } 61 62 // GasPrice returns the gas price 63 func (elp *envelope) GasPrice() *big.Int { 64 p := &big.Int{} 65 if elp.gasPrice == nil { 66 return p 67 } 68 return p.Set(elp.gasPrice) 69 } 70 71 // Cost returns cost of actions 72 func (elp *envelope) Cost() (*big.Int, error) { 73 return elp.payload.Cost() 74 } 75 76 // IntrinsicGas returns intrinsic gas of action. 77 func (elp *envelope) IntrinsicGas() (uint64, error) { 78 return elp.payload.IntrinsicGas() 79 } 80 81 // Action returns the action payload. 82 func (elp *envelope) Action() Action { return elp.payload } 83 84 // Proto convert Envelope to protobuf format. 85 func (elp *envelope) Proto() *iotextypes.ActionCore { 86 actCore := &iotextypes.ActionCore{ 87 Version: elp.version, 88 Nonce: elp.nonce, 89 GasLimit: elp.gasLimit, 90 ChainID: elp.chainID, 91 } 92 if elp.gasPrice != nil { 93 actCore.GasPrice = elp.gasPrice.String() 94 } 95 96 // TODO assert each action 97 switch act := elp.Action().(type) { 98 case *Transfer: 99 actCore.Action = &iotextypes.ActionCore_Transfer{Transfer: act.Proto()} 100 case *Execution: 101 actCore.Action = &iotextypes.ActionCore_Execution{Execution: act.Proto()} 102 case *GrantReward: 103 actCore.Action = &iotextypes.ActionCore_GrantReward{GrantReward: act.Proto()} 104 case *ClaimFromRewardingFund: 105 actCore.Action = &iotextypes.ActionCore_ClaimFromRewardingFund{ClaimFromRewardingFund: act.Proto()} 106 case *DepositToRewardingFund: 107 actCore.Action = &iotextypes.ActionCore_DepositToRewardingFund{DepositToRewardingFund: act.Proto()} 108 case *PutPollResult: 109 actCore.Action = &iotextypes.ActionCore_PutPollResult{PutPollResult: act.Proto()} 110 case *CreateStake: 111 actCore.Action = &iotextypes.ActionCore_StakeCreate{StakeCreate: act.Proto()} 112 case *Unstake: 113 actCore.Action = &iotextypes.ActionCore_StakeUnstake{StakeUnstake: act.Proto()} 114 case *WithdrawStake: 115 actCore.Action = &iotextypes.ActionCore_StakeWithdraw{StakeWithdraw: act.Proto()} 116 case *DepositToStake: 117 actCore.Action = &iotextypes.ActionCore_StakeAddDeposit{StakeAddDeposit: act.Proto()} 118 case *Restake: 119 actCore.Action = &iotextypes.ActionCore_StakeRestake{StakeRestake: act.Proto()} 120 case *ChangeCandidate: 121 actCore.Action = &iotextypes.ActionCore_StakeChangeCandidate{StakeChangeCandidate: act.Proto()} 122 case *TransferStake: 123 actCore.Action = &iotextypes.ActionCore_StakeTransferOwnership{StakeTransferOwnership: act.Proto()} 124 case *CandidateRegister: 125 actCore.Action = &iotextypes.ActionCore_CandidateRegister{CandidateRegister: act.Proto()} 126 case *CandidateUpdate: 127 actCore.Action = &iotextypes.ActionCore_CandidateUpdate{CandidateUpdate: act.Proto()} 128 case *CandidateActivate: 129 actCore.Action = &iotextypes.ActionCore_CandidateActivate{CandidateActivate: act.Proto()} 130 case *CandidateEndorsement: 131 actCore.Action = &iotextypes.ActionCore_CandidateEndorsement{CandidateEndorsement: act.Proto()} 132 default: 133 log.S().Panicf("Cannot convert type of action %T.\r\n", act) 134 } 135 return actCore 136 } 137 138 // LoadProto loads fields from protobuf format. 139 func (elp *envelope) LoadProto(pbAct *iotextypes.ActionCore) error { 140 if pbAct == nil { 141 return ErrNilProto 142 } 143 if elp == nil { 144 return ErrNilAction 145 } 146 *elp = envelope{} 147 elp.version = pbAct.GetVersion() 148 elp.nonce = pbAct.GetNonce() 149 elp.gasLimit = pbAct.GetGasLimit() 150 elp.chainID = pbAct.GetChainID() 151 if pbAct.GetGasPrice() == "" { 152 elp.gasPrice = big.NewInt(0) 153 } else { 154 gp, ok := new(big.Int).SetString(pbAct.GetGasPrice(), 10) 155 if !ok { 156 return errors.Errorf("invalid gas prcie %s", pbAct.GetGasPrice()) 157 } 158 elp.gasPrice = gp 159 } 160 161 switch { 162 case pbAct.GetTransfer() != nil: 163 act := &Transfer{} 164 if err := act.LoadProto(pbAct.GetTransfer()); err != nil { 165 return err 166 } 167 elp.payload = act 168 case pbAct.GetExecution() != nil: 169 act := &Execution{} 170 if err := act.LoadProto(pbAct.GetExecution()); err != nil { 171 return err 172 } 173 elp.payload = act 174 case pbAct.GetGrantReward() != nil: 175 act := &GrantReward{} 176 if err := act.LoadProto(pbAct.GetGrantReward()); err != nil { 177 return err 178 } 179 elp.payload = act 180 case pbAct.GetClaimFromRewardingFund() != nil: 181 act := &ClaimFromRewardingFund{} 182 if err := act.LoadProto(pbAct.GetClaimFromRewardingFund()); err != nil { 183 return err 184 } 185 elp.payload = act 186 case pbAct.GetDepositToRewardingFund() != nil: 187 act := &DepositToRewardingFund{} 188 if err := act.LoadProto(pbAct.GetDepositToRewardingFund()); err != nil { 189 return err 190 } 191 elp.payload = act 192 case pbAct.GetPutPollResult() != nil: 193 act := &PutPollResult{} 194 if err := act.LoadProto(pbAct.GetPutPollResult()); err != nil { 195 return err 196 } 197 elp.payload = act 198 199 case pbAct.GetStakeCreate() != nil: 200 act := &CreateStake{} 201 if err := act.LoadProto(pbAct.GetStakeCreate()); err != nil { 202 return err 203 } 204 elp.payload = act 205 case pbAct.GetStakeUnstake() != nil: 206 act := &Unstake{} 207 if err := act.LoadProto(pbAct.GetStakeUnstake()); err != nil { 208 return err 209 } 210 elp.payload = act 211 case pbAct.GetStakeWithdraw() != nil: 212 act := &WithdrawStake{} 213 if err := act.LoadProto(pbAct.GetStakeWithdraw()); err != nil { 214 return err 215 } 216 elp.payload = act 217 case pbAct.GetStakeAddDeposit() != nil: 218 act := &DepositToStake{} 219 if err := act.LoadProto(pbAct.GetStakeAddDeposit()); err != nil { 220 return err 221 } 222 elp.payload = act 223 case pbAct.GetStakeRestake() != nil: 224 act := &Restake{} 225 if err := act.LoadProto(pbAct.GetStakeRestake()); err != nil { 226 return err 227 } 228 elp.payload = act 229 case pbAct.GetStakeChangeCandidate() != nil: 230 act := &ChangeCandidate{} 231 if err := act.LoadProto(pbAct.GetStakeChangeCandidate()); err != nil { 232 return err 233 } 234 elp.payload = act 235 case pbAct.GetStakeTransferOwnership() != nil: 236 act := &TransferStake{} 237 if err := act.LoadProto(pbAct.GetStakeTransferOwnership()); err != nil { 238 return err 239 } 240 elp.payload = act 241 case pbAct.GetCandidateRegister() != nil: 242 act := &CandidateRegister{} 243 if err := act.LoadProto(pbAct.GetCandidateRegister()); err != nil { 244 return err 245 } 246 elp.payload = act 247 case pbAct.GetCandidateUpdate() != nil: 248 act := &CandidateUpdate{} 249 if err := act.LoadProto(pbAct.GetCandidateUpdate()); err != nil { 250 return err 251 } 252 elp.payload = act 253 case pbAct.GetCandidateActivate() != nil: 254 act := &CandidateActivate{} 255 if err := act.LoadProto(pbAct.GetCandidateActivate()); err != nil { 256 return err 257 } 258 elp.payload = act 259 case pbAct.GetCandidateEndorsement() != nil: 260 act := &CandidateEndorsement{} 261 if err := act.LoadProto(pbAct.GetCandidateEndorsement()); err != nil { 262 return err 263 } 264 elp.payload = act 265 default: 266 return errors.Errorf("no applicable action to handle proto type %T", pbAct.Action) 267 } 268 elp.payload.SetEnvelopeContext(elp) 269 return nil 270 } 271 272 // SetNonce sets the nonce value 273 func (elp *envelope) SetNonce(n uint64) { elp.nonce = n } 274 275 // SetChainID sets the chainID value 276 func (elp *envelope) SetChainID(chainID uint32) { elp.chainID = chainID }