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 }