github.com/RobustRoundRobin/quorum@v20.10.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) (common.EncryptedPayloadHash, error) 37 StoreRaw(data []byte, from string) (common.EncryptedPayloadHash, error) 38 SendSignedTx(data common.EncryptedPayloadHash, to []string, extra *engine.ExtraMetadata) ([]byte, error) 39 // Returns nil payload if not found 40 Receive(data common.EncryptedPayloadHash) ([]byte, *engine.ExtraMetadata, error) 41 // Returns nil payload if not found 42 ReceiveRaw(data common.EncryptedPayloadHash) ([]byte, *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 info, err := os.Lstat(cfgPath) 62 if err != nil { 63 panic(fmt.Sprintf("unable to read %s due to %s", cfgPath, err)) 64 } 65 // We accept either the socket or a configuration file that points to 66 // a socket. 67 socketPath := cfgPath 68 isSocket := info.Mode()&os.ModeSocket != 0 69 if !isSocket { 70 cfg, err := engine.LoadConfig(cfgPath) 71 if err != nil { 72 panic(fmt.Sprintf("unable to load configuration file for private transaction manager from %s due to %s", cfgPath, err)) 73 } 74 socketPath = filepath.Join(cfg.WorkDir, cfg.Socket) 75 } 76 77 client := &engine.Client{ 78 HttpClient: &http.Client{ 79 Transport: unixTransport(socketPath), 80 }, 81 BaseURL: "http+unix://c", 82 } 83 ptm, err := selectPrivateTxManager(client) 84 if err != nil { 85 panic(fmt.Sprintf("unable to connect to private tx manager using %s due to %s", socketPath, err)) 86 } 87 return ptm 88 } 89 90 func unixTransport(socketPath string) *httpunix.Transport { 91 t := &httpunix.Transport{ 92 DialTimeout: 1 * time.Second, 93 RequestTimeout: 5 * time.Second, 94 ResponseHeaderTimeout: 5 * time.Second, 95 } 96 t.RegisterLocation("c", socketPath) 97 return t 98 } 99 100 // First call /upcheck to make sure the private tx manager is up 101 // Then call /version to decide which private tx manager client implementation to be used 102 func selectPrivateTxManager(client *engine.Client) (PrivateTransactionManager, error) { 103 res, err := client.Get("/upcheck") 104 if err != nil { 105 return nil, err 106 } 107 if res.StatusCode != 200 { 108 return nil, engine.ErrPrivateTxManagerNotReady 109 } 110 res, err = client.Get("/version") 111 if err != nil { 112 return nil, err 113 } 114 defer res.Body.Close() 115 version, err := ioutil.ReadAll(res.Body) 116 if err != nil { 117 return nil, err 118 } 119 var privateTxManager PrivateTransactionManager 120 defer func() { 121 log.Info("Target Private Tx Manager", "name", privateTxManager.Name(), "distributionVersion", version) 122 }() 123 if res.StatusCode != 200 { 124 // Constellation doesn't have /version endpoint 125 privateTxManager = constellation.New(client) 126 } else { 127 privateTxManager = tessera.New(client, []byte(tessera.RetrieveTesseraAPIVersion(client))) 128 } 129 return privateTxManager, nil 130 }