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 ¬inuse.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 }