github.com/Night-mk/quorum@v21.1.0+incompatible/private/private.go (about)

     1  package private
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/ethereum/go-ethereum/common"
    13  	"github.com/ethereum/go-ethereum/log"
    14  	"github.com/ethereum/go-ethereum/private/engine"
    15  	"github.com/ethereum/go-ethereum/private/engine/constellation"
    16  	"github.com/ethereum/go-ethereum/private/engine/notinuse"
    17  	"github.com/ethereum/go-ethereum/private/engine/tessera"
    18  	"github.com/tv42/httpunix"
    19  )
    20  
    21  var (
    22  	// global variable to be accessed by other packages
    23  	// singleton gateway to interact with private transaction manager
    24  	P = FromEnvironmentOrNil("PRIVATE_CONFIG")
    25  )
    26  
    27  type Identifiable interface {
    28  	Name() string
    29  	HasFeature(f engine.PrivateTransactionManagerFeature) bool
    30  }
    31  
    32  // Interacting with Private Transaction Manager APIs
    33  type PrivateTransactionManager interface {
    34  	Identifiable
    35  
    36  	Send(data []byte, from string, to []string, extra *engine.ExtraMetadata) (string, []string, common.EncryptedPayloadHash, error)
    37  	StoreRaw(data []byte, from string) (common.EncryptedPayloadHash, error)
    38  	SendSignedTx(data common.EncryptedPayloadHash, to []string, extra *engine.ExtraMetadata) (string, []string, []byte, error)
    39  	// Returns nil payload if not found
    40  	Receive(data common.EncryptedPayloadHash) (string, []string, []byte, *engine.ExtraMetadata, error)
    41  	// Returns nil payload if not found
    42  	ReceiveRaw(data common.EncryptedPayloadHash) ([]byte, string, *engine.ExtraMetadata, error)
    43  	IsSender(txHash common.EncryptedPayloadHash) (bool, error)
    44  	GetParticipants(txHash common.EncryptedPayloadHash) ([]string, error)
    45  	EncryptPayload(data []byte, from string, to []string, extra *engine.ExtraMetadata) ([]byte, error)
    46  	DecryptPayload(payload common.DecryptRequest) ([]byte, *engine.ExtraMetadata, error)
    47  }
    48  
    49  func FromEnvironmentOrNil(name string) PrivateTransactionManager {
    50  	cfgPath := os.Getenv(name)
    51  	if cfgPath == "" {
    52  		return nil
    53  	}
    54  	if strings.EqualFold(cfgPath, "ignore") {
    55  		return &notinuse.PrivateTransactionManager{}
    56  	}
    57  	return MustNewPrivateTxManager(cfgPath)
    58  }
    59  
    60  func MustNewPrivateTxManager(cfgPath string) PrivateTransactionManager {
    61  	ptm, err := NewPrivateTxManager(cfgPath)
    62  	if err != nil {
    63  		panic(err)
    64  	}
    65  	return ptm
    66  }
    67  
    68  func NewPrivateTxManager(cfgPath string) (PrivateTransactionManager, error) {
    69  	cfg, err := engine.LoadConfig(cfgPath)
    70  	if err != nil {
    71  		return nil, fmt.Errorf("unable to read %s due to %s", cfgPath, err)
    72  	}
    73  
    74  	client := &engine.Client{
    75  		HttpClient: &http.Client{
    76  			Transport: unixTransport(cfg),
    77  		},
    78  		BaseURL: "http+unix://c",
    79  	}
    80  
    81  	ptm, err := selectPrivateTxManager(client)
    82  	if err != nil {
    83  		return nil, fmt.Errorf("unable to connect to private tx manager using %s due to %s", cfgPath, err)
    84  	}
    85  	return ptm, nil
    86  }
    87  
    88  func unixTransport(cfg engine.Config) *httpunix.Transport {
    89  	t := &httpunix.Transport{
    90  		DialTimeout:           time.Duration(cfg.DialTimeout) * time.Second,
    91  		RequestTimeout:        time.Duration(cfg.RequestTimeout) * time.Second,
    92  		ResponseHeaderTimeout: time.Duration(cfg.ResponseHeaderTimeout) * time.Second,
    93  	}
    94  	t.RegisterLocation("c", filepath.Join(cfg.WorkDir, cfg.Socket))
    95  	return t
    96  }
    97  
    98  // First call /upcheck to make sure the private tx manager is up
    99  // Then call /version to decide which private tx manager client implementation to be used
   100  func selectPrivateTxManager(client *engine.Client) (PrivateTransactionManager, error) {
   101  	res, err := client.Get("/upcheck")
   102  	if err != nil {
   103  		return nil, err
   104  	}
   105  	if res.StatusCode != 200 {
   106  		return nil, engine.ErrPrivateTxManagerNotReady
   107  	}
   108  	res, err = client.Get("/version")
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	defer res.Body.Close()
   113  	version, err := ioutil.ReadAll(res.Body)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  	var privateTxManager PrivateTransactionManager
   118  	defer func() {
   119  		log.Info("Target Private Tx Manager", "name", privateTxManager.Name(), "distributionVersion", version)
   120  	}()
   121  	if res.StatusCode != 200 {
   122  		// Constellation doesn't have /version endpoint
   123  		privateTxManager = constellation.New(client)
   124  	} else {
   125  		privateTxManager = tessera.New(client, []byte(tessera.RetrieveTesseraAPIVersion(client)))
   126  	}
   127  	return privateTxManager, nil
   128  }