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  }