github.com/iotexproject/iotex-core@v1.14.1-rc1/action/action.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package action 7 8 import ( 9 "math" 10 "math/big" 11 12 "github.com/ethereum/go-ethereum/core/types" 13 "github.com/iotexproject/go-pkgs/crypto" 14 "github.com/pkg/errors" 15 ) 16 17 type ( 18 // Action is the action can be Executed in protocols. The method is added to avoid mistakenly used empty interface as action. 19 Action interface { 20 SanityCheck() error 21 } 22 23 // EthCompatibleAction is the action which is compatible to be converted to eth tx 24 EthCompatibleAction interface { 25 ToEthTx(uint32) (*types.Transaction, error) 26 } 27 28 actionPayload interface { 29 Cost() (*big.Int, error) 30 IntrinsicGas() (uint64, error) 31 SetEnvelopeContext(Envelope) 32 SanityCheck() error 33 } 34 35 hasDestination interface { 36 Destination() string 37 } 38 ) 39 40 // Sign signs the action using sender's private key 41 func Sign(act Envelope, sk crypto.PrivateKey) (*SealedEnvelope, error) { 42 sealed := &SealedEnvelope{ 43 Envelope: act, 44 srcPubkey: sk.PublicKey(), 45 } 46 47 h, err := sealed.envelopeHash() 48 if err != nil { 49 return sealed, errors.Wrap(err, "failed to generate envelope hash") 50 } 51 sig, err := sk.Sign(h[:]) 52 if err != nil { 53 return sealed, ErrInvalidSender 54 } 55 sealed.signature = sig 56 return sealed, nil 57 } 58 59 // FakeSeal creates a SealedActionEnvelope without signature. 60 // This method should be only used in tests. 61 func FakeSeal(act Envelope, pubk crypto.PublicKey) *SealedEnvelope { 62 sealed := &SealedEnvelope{ 63 Envelope: act, 64 srcPubkey: pubk, 65 } 66 return sealed 67 } 68 69 // AssembleSealedEnvelope assembles a SealedEnvelope use Envelope, Sender Address and Signature. 70 // This method should be only used in tests. 71 func AssembleSealedEnvelope(act Envelope, pk crypto.PublicKey, sig []byte) *SealedEnvelope { 72 sealed := &SealedEnvelope{ 73 Envelope: act, 74 srcPubkey: pk, 75 signature: sig, 76 } 77 return sealed 78 } 79 80 // CalculateIntrinsicGas returns the intrinsic gas of an action 81 func CalculateIntrinsicGas(baseIntrinsicGas uint64, payloadGas uint64, payloadSize uint64) (uint64, error) { 82 if payloadGas == 0 && payloadSize == 0 { 83 return baseIntrinsicGas, nil 84 } 85 if (math.MaxUint64-baseIntrinsicGas)/payloadGas < payloadSize { 86 return 0, ErrInsufficientFunds 87 } 88 return payloadSize*payloadGas + baseIntrinsicGas, nil 89 } 90 91 // IsSystemAction determine whether input action belongs to system action 92 func IsSystemAction(act *SealedEnvelope) bool { 93 switch act.Action().(type) { 94 case *GrantReward, *PutPollResult: 95 return true 96 default: 97 return false 98 } 99 }