github.com/koko1123/flow-go-1@v0.29.6/engine/access/rest/request/transaction.go (about)

     1  package request
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  
     7  	"github.com/koko1123/flow-go-1/engine/access/rest/models"
     8  	"github.com/koko1123/flow-go-1/engine/access/rest/util"
     9  	"github.com/koko1123/flow-go-1/engine/common/rpc/convert"
    10  	"github.com/koko1123/flow-go-1/model/flow"
    11  )
    12  
    13  const maxAuthorizers = 100
    14  const maxAllowedScriptArguments = 100
    15  
    16  type Transaction flow.TransactionBody
    17  
    18  func (t *Transaction) Parse(raw io.Reader, chain flow.Chain) error {
    19  	var tx models.TransactionsBody
    20  	err := parseBody(raw, &tx)
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	if tx.ProposalKey == nil {
    26  		return fmt.Errorf("proposal key not provided")
    27  	}
    28  	if tx.Script == "" {
    29  		return fmt.Errorf("script not provided")
    30  	}
    31  	if tx.Payer == "" {
    32  		return fmt.Errorf("payer not provided")
    33  	}
    34  	if len(tx.Authorizers) > maxAuthorizers {
    35  		return fmt.Errorf("too many authorizers. Maximum authorizers allowed: %d", maxAuthorizers)
    36  	}
    37  	if len(tx.Arguments) > maxAllowedScriptArguments {
    38  		return fmt.Errorf("too many arguments. Maximum arguments allowed: %d", maxAllowedScriptArguments)
    39  	}
    40  	if tx.ReferenceBlockId == "" {
    41  		return fmt.Errorf("reference block not provided")
    42  	}
    43  	if len(tx.EnvelopeSignatures) == 0 {
    44  		return fmt.Errorf("envelope signatures not provided")
    45  	}
    46  
    47  	var args Arguments
    48  	err = args.Parse(tx.Arguments)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	var payer Address
    54  	err = payer.Parse(tx.Payer)
    55  	if err != nil {
    56  		return fmt.Errorf("invalid payer: %w", err)
    57  	}
    58  
    59  	auths := make([]flow.Address, len(tx.Authorizers))
    60  	for i, auth := range tx.Authorizers {
    61  		var a Address
    62  		err := a.Parse(auth)
    63  		if err != nil {
    64  			return err
    65  		}
    66  
    67  		auths[i] = a.Flow()
    68  	}
    69  
    70  	var proposal ProposalKey
    71  	err = proposal.Parse(*tx.ProposalKey)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	var payloadSigs TransactionSignatures
    77  	err = payloadSigs.Parse(tx.PayloadSignatures)
    78  	if err != nil {
    79  		return err
    80  	}
    81  
    82  	var envelopeSigs TransactionSignatures
    83  	err = envelopeSigs.Parse(tx.EnvelopeSignatures)
    84  	if err != nil {
    85  		return err
    86  	}
    87  
    88  	// script comes in as a base64 encoded string, decode base64 back to a string here
    89  	script, err := util.FromBase64(tx.Script)
    90  	if err != nil {
    91  		return fmt.Errorf("invalid transaction script encoding")
    92  	}
    93  
    94  	var blockID ID
    95  	err = blockID.Parse(tx.ReferenceBlockId)
    96  	if err != nil {
    97  		return fmt.Errorf("invalid reference block ID: %w", err)
    98  	}
    99  
   100  	gasLimit, err := util.ToUint64(tx.GasLimit)
   101  	if err != nil {
   102  		return fmt.Errorf("invalid gas limit: %w", err)
   103  	}
   104  
   105  	flowTransaction := flow.TransactionBody{
   106  		ReferenceBlockID:   blockID.Flow(),
   107  		Script:             script,
   108  		Arguments:          args.Flow(),
   109  		GasLimit:           gasLimit,
   110  		ProposalKey:        proposal.Flow(),
   111  		Payer:              payer.Flow(),
   112  		Authorizers:        auths,
   113  		PayloadSignatures:  payloadSigs.Flow(),
   114  		EnvelopeSignatures: envelopeSigs.Flow(),
   115  	}
   116  
   117  	// we use the gRPC method of converting the incoming transaction to a Flow transaction since
   118  	// it sets the signer_index appropriately.
   119  	entityTransaction := convert.TransactionToMessage(flowTransaction)
   120  	flowTx, err := convert.MessageToTransaction(entityTransaction, chain)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	*t = Transaction(flowTx)
   126  
   127  	return nil
   128  }
   129  
   130  func (t Transaction) Flow() flow.TransactionBody {
   131  	return flow.TransactionBody(t)
   132  }