github.com/hyperledger/burrow@v0.34.5-0.20220512172541-77f09336001d/rpc/rpctransact/transact_server.go (about)

     1  package rpctransact
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/hyperledger/burrow/acm/acmstate"
     8  
     9  	"github.com/hyperledger/burrow/logging"
    10  
    11  	"github.com/hyperledger/burrow/bcm"
    12  
    13  	"github.com/hyperledger/burrow/execution"
    14  	"github.com/hyperledger/burrow/execution/exec"
    15  	"github.com/hyperledger/burrow/txs"
    16  	"github.com/hyperledger/burrow/txs/payload"
    17  	"golang.org/x/net/context"
    18  )
    19  
    20  // This is probably silly
    21  const maxBroadcastSyncTimeout = time.Hour
    22  
    23  type transactServer struct {
    24  	UnimplementedTransactServer
    25  	stateSnapshot func() (acmstate.Reader, error)
    26  	blockchain    bcm.BlockchainInfo
    27  	transactor    *execution.Transactor
    28  	txCodec       txs.Codec
    29  	logger        *logging.Logger
    30  }
    31  
    32  func NewTransactServer(stateSnapshotter func() (acmstate.Reader, error), blockchain bcm.BlockchainInfo,
    33  	transactor *execution.Transactor, txCodec txs.Codec, logger *logging.Logger) TransactServer {
    34  	return &transactServer{
    35  		stateSnapshot: stateSnapshotter,
    36  		blockchain:    blockchain,
    37  		transactor:    transactor,
    38  		txCodec:       txCodec,
    39  		logger:        logger.WithScope("NewTransactServer()"),
    40  	}
    41  }
    42  
    43  func (ts *transactServer) BroadcastTxSync(ctx context.Context, param *TxEnvelopeParam) (*exec.TxExecution, error) {
    44  	const errHeader = "BroadcastTxSync():"
    45  	if param.Timeout == 0 {
    46  		param.Timeout = maxBroadcastSyncTimeout
    47  	}
    48  	ctx, cancel := context.WithTimeout(ctx, param.Timeout)
    49  	defer cancel()
    50  	txEnv := param.GetEnvelope(ts.transactor.BlockchainInfo.ChainID())
    51  	if txEnv == nil {
    52  		return nil, fmt.Errorf("%s no transaction envelope or payload provided", errHeader)
    53  	}
    54  	return ts.transactor.BroadcastTxSync(ctx, txEnv)
    55  }
    56  
    57  func (ts *transactServer) BroadcastTxAsync(ctx context.Context, param *TxEnvelopeParam) (*txs.Receipt, error) {
    58  	const errHeader = "BroadcastTxAsync():"
    59  	if param.Timeout == 0 {
    60  		param.Timeout = maxBroadcastSyncTimeout
    61  	}
    62  	txEnv := param.GetEnvelope(ts.transactor.BlockchainInfo.ChainID())
    63  	if txEnv == nil {
    64  		return nil, fmt.Errorf("%s no transaction envelope or payload provided", errHeader)
    65  	}
    66  	return ts.transactor.BroadcastTxAsync(ctx, txEnv)
    67  }
    68  
    69  func (ts *transactServer) SignTx(ctx context.Context, param *TxEnvelopeParam) (*TxEnvelope, error) {
    70  	txEnv := param.GetEnvelope(ts.transactor.BlockchainInfo.ChainID())
    71  	if txEnv == nil {
    72  		return nil, fmt.Errorf("no transaction envelope or payload provided")
    73  	}
    74  	txEnv, err := ts.transactor.SignTx(txEnv)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	return &TxEnvelope{
    79  		Envelope: txEnv,
    80  	}, nil
    81  }
    82  
    83  func (ts *transactServer) FormulateTx(ctx context.Context, param *payload.Any) (*TxEnvelope, error) {
    84  	txEnv := txs.EnvelopeFromAny(ts.transactor.BlockchainInfo.ChainID(), param)
    85  	if txEnv == nil {
    86  		return nil, fmt.Errorf("no payload provided to FormulateTx")
    87  	}
    88  	return &TxEnvelope{
    89  		Envelope: txEnv,
    90  	}, nil
    91  }
    92  
    93  func (ts *transactServer) CallTxSync(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) {
    94  	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
    95  }
    96  
    97  func (ts *transactServer) CallTxAsync(ctx context.Context, param *payload.CallTx) (*txs.Receipt, error) {
    98  	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
    99  }
   100  
   101  func (ts *transactServer) CallTxSim(ctx context.Context, param *payload.CallTx) (*exec.TxExecution, error) {
   102  	if param.Address == nil {
   103  		return nil, fmt.Errorf("CallSim requires a non-nil address from which to retrieve code")
   104  	}
   105  	// Get a consistent state view for duration of simulated call
   106  	st, err := ts.stateSnapshot()
   107  	if err != nil {
   108  		return nil, err
   109  	}
   110  	return execution.CallSim(st, ts.blockchain, param.Input.Address, *param.Address, param.Data, ts.logger)
   111  }
   112  
   113  func (ts *transactServer) CallCodeSim(ctx context.Context, param *CallCodeParam) (*exec.TxExecution, error) {
   114  	// Get a consistent state view for duration of simulated call
   115  	st, err := ts.stateSnapshot()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	return execution.CallCodeSim(st, ts.blockchain, param.FromAddress, param.FromAddress, param.Code, param.Data,
   120  		ts.logger)
   121  }
   122  
   123  func (ts *transactServer) SendTxSync(ctx context.Context, param *payload.SendTx) (*exec.TxExecution, error) {
   124  	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
   125  }
   126  
   127  func (ts *transactServer) SendTxAsync(ctx context.Context, param *payload.SendTx) (*txs.Receipt, error) {
   128  	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
   129  }
   130  
   131  func (ts *transactServer) NameTxSync(ctx context.Context, param *payload.NameTx) (*exec.TxExecution, error) {
   132  	return ts.BroadcastTxSync(ctx, &TxEnvelopeParam{Payload: param.Any()})
   133  }
   134  
   135  func (ts *transactServer) NameTxAsync(ctx context.Context, param *payload.NameTx) (*txs.Receipt, error) {
   136  	return ts.BroadcastTxAsync(ctx, &TxEnvelopeParam{Payload: param.Any()})
   137  }
   138  
   139  func (te *TxEnvelopeParam) GetEnvelope(chainID string) *txs.Envelope {
   140  	if te == nil {
   141  		return nil
   142  	}
   143  	if te.Envelope != nil {
   144  		return te.Envelope
   145  	}
   146  	if te.Payload != nil {
   147  		return txs.EnvelopeFromAny(chainID, te.Payload)
   148  	}
   149  	return nil
   150  }