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 }