github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/private/private.go (about) 1 package private 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 10 "github.com/kisexp/xdchain/common" 11 http2 "github.com/kisexp/xdchain/common/http" 12 "github.com/kisexp/xdchain/core/types" 13 "github.com/kisexp/xdchain/log" 14 "github.com/kisexp/xdchain/private/engine" 15 "github.com/kisexp/xdchain/private/engine/constellation" 16 "github.com/kisexp/xdchain/private/engine/notinuse" 17 "github.com/kisexp/xdchain/private/engine/tessera" 18 ) 19 20 var ( 21 // global variable to be accessed by other packages 22 // singleton gateway to interact with private transaction manager 23 P PrivateTransactionManager 24 isPrivacyEnabled = false 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 GetMandatory(txHash common.EncryptedPayloadHash) ([]string, error) 46 EncryptPayload(data []byte, from string, to []string, extra *engine.ExtraMetadata) ([]byte, error) 47 DecryptPayload(payload common.DecryptRequest) ([]byte, *engine.ExtraMetadata, error) 48 49 Groups() ([]engine.PrivacyGroup, error) 50 } 51 52 // This loads any config specified via the legacy environment variable 53 func GetLegacyEnvironmentConfig() (http2.Config, error) { 54 return FromEnvironmentOrNil("PRIVATE_CONFIG") 55 } 56 57 func FromEnvironmentOrNil(name string) (http2.Config, error) { 58 cfgPath := os.Getenv(name) 59 cfg, err := http2.FetchConfigOrIgnore(cfgPath) 60 if err != nil { 61 return http2.Config{}, err 62 } 63 64 return cfg, nil 65 } 66 67 func InitialiseConnection(cfg http2.Config) error { 68 var err error 69 P, err = NewPrivateTxManager(cfg) 70 return err 71 } 72 73 func IsQuorumPrivacyEnabled() bool { 74 return isPrivacyEnabled 75 } 76 77 func NewPrivateTxManager(cfg http2.Config) (PrivateTransactionManager, error) { 78 79 if cfg.ConnectionType == http2.NoConnection { 80 log.Info("Running with private transaction manager disabled - quorum private transactions will not be supported") 81 return ¬inuse.PrivateTransactionManager{}, nil 82 } 83 84 client, err := http2.CreateClient(cfg) 85 if err != nil { 86 return nil, fmt.Errorf("unable to create connection to private tx manager due to: %s", err) 87 } 88 89 ptm, err := selectPrivateTxManager(client) 90 if err != nil { 91 return nil, fmt.Errorf("unable to connect to private tx manager due to: %s", err) 92 } 93 94 isPrivacyEnabled = true 95 return ptm, nil 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", string(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 } 129 130 // Retrieve the private transaction that is associated with a privacy marker transaction 131 func FetchPrivateTransaction(data []byte) (*types.Transaction, []string, *engine.ExtraMetadata, error) { 132 txHash := common.BytesToEncryptedPayloadHash(data) 133 134 _, managedParties, txData, metadata, err := P.Receive(txHash) 135 if err != nil { 136 return nil, nil, nil, err 137 } 138 if txData == nil { 139 return nil, nil, nil, nil 140 } 141 142 var tx types.Transaction 143 err = json.NewDecoder(bytes.NewReader(txData)).Decode(&tx) 144 if err != nil { 145 log.Trace("failed to deserialize private transaction", "err", err) 146 return nil, nil, nil, err 147 } 148 149 return &tx, managedParties, metadata, nil 150 }