github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/consensus/abci/execute_tx.go (about)

     1  package abci
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/hyperledger/burrow/consensus/tendermint/codes"
     8  	"github.com/hyperledger/burrow/execution"
     9  	"github.com/hyperledger/burrow/execution/errors"
    10  	"github.com/hyperledger/burrow/logging"
    11  	"github.com/hyperledger/burrow/logging/structure"
    12  	"github.com/hyperledger/burrow/txs"
    13  	"github.com/tendermint/tendermint/abci/types"
    14  )
    15  
    16  // Attempt to execute a transaction using ABCI conventions and codes
    17  func ExecuteTx(logHeader string, executor execution.Executor, txDecoder txs.Decoder, txBytes []byte) types.ResponseCheckTx {
    18  	logf := func(format string, args ...interface{}) string {
    19  		return fmt.Sprintf("%s: "+format, append([]interface{}{logHeader}, args...)...)
    20  	}
    21  
    22  	txEnv, err := txDecoder.DecodeTx(txBytes)
    23  	if err != nil {
    24  		return types.ResponseCheckTx{
    25  			Code: codes.EncodingErrorCode,
    26  			Log:  logf("Decoding error: %s", err),
    27  		}
    28  	}
    29  	txe, err := executor.Execute(txEnv)
    30  	if err != nil {
    31  		ex := errors.AsException(err)
    32  		return types.ResponseCheckTx{
    33  			Code: codes.TxExecutionErrorCode,
    34  			Log:  logf("Could not execute transaction: %s, error: %v", txEnv, ex.Exception),
    35  		}
    36  	}
    37  
    38  	tags := []types.EventAttribute{{Key: []byte(structure.TxHashKey), Value: []byte(txEnv.Tx.Hash().String())}}
    39  	if txe.Receipt.CreatesContract {
    40  		tags = append(tags, types.EventAttribute{
    41  			Key:   []byte("created_contract_address"),
    42  			Value: []byte(txe.Receipt.ContractAddress.String()),
    43  		})
    44  	}
    45  
    46  	events := []types.Event{{Type: "ExecuteTx", Attributes: tags}}
    47  	bs, err := txe.Receipt.Encode()
    48  	if err != nil {
    49  		return types.ResponseCheckTx{
    50  			Code:   codes.EncodingErrorCode,
    51  			Events: events,
    52  			Log:    logf("Could not serialise receipt: %s", err),
    53  		}
    54  	}
    55  	return types.ResponseCheckTx{
    56  		Code:   codes.TxExecutionSuccessCode,
    57  		Events: events,
    58  		Log:    logf("Execution success - TxExecution in data"),
    59  		Data:   bs,
    60  	}
    61  }
    62  
    63  // Some ABCI type helpers
    64  
    65  func WithEvents(logger *logging.Logger, events []types.Event) *logging.Logger {
    66  	for _, e := range events {
    67  		values := make([]string, 0, len(e.Attributes))
    68  		for _, kvp := range e.Attributes {
    69  			values = append(values, fmt.Sprintf("%s:%s", string(kvp.Key), string(kvp.Value)))
    70  		}
    71  		logger = logger.With(e.Type, strings.Join(values, ","))
    72  	}
    73  	return logger
    74  }
    75  
    76  func DeliverTxFromCheckTx(ctr types.ResponseCheckTx) types.ResponseDeliverTx {
    77  	return types.ResponseDeliverTx{
    78  		Code:      ctr.Code,
    79  		Log:       ctr.Log,
    80  		Data:      ctr.Data,
    81  		Events:    ctr.Events,
    82  		GasUsed:   ctr.GasUsed,
    83  		GasWanted: ctr.GasWanted,
    84  		Info:      ctr.Info,
    85  	}
    86  }