private.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package private
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "github.com/ethereum/go-ethereum/common"
  9. http2 "github.com/ethereum/go-ethereum/common/http"
  10. "github.com/ethereum/go-ethereum/core/types"
  11. "github.com/ethereum/go-ethereum/log"
  12. "github.com/ethereum/go-ethereum/private/engine"
  13. "github.com/ethereum/go-ethereum/private/engine/constellation"
  14. "github.com/ethereum/go-ethereum/private/engine/notinuse"
  15. "github.com/ethereum/go-ethereum/private/engine/qlightptm"
  16. "github.com/ethereum/go-ethereum/private/engine/tessera"
  17. "github.com/ethereum/go-ethereum/rpc"
  18. )
  19. var (
  20. // global variable to be accessed by other packages
  21. // singleton gateway to interact with private transaction manager
  22. P PrivateTransactionManager
  23. isPrivacyEnabled = false
  24. )
  25. type HasRPCClient interface {
  26. SetRPCClient(client *rpc.Client)
  27. }
  28. type Identifiable interface {
  29. Name() string
  30. HasFeature(f engine.PrivateTransactionManagerFeature) bool
  31. }
  32. // Interacting with Private Transaction Manager APIs
  33. type PrivateTransactionManager interface {
  34. Identifiable
  35. Send(data []byte, from string, to []string, extra *engine.ExtraMetadata) (string, []string, common.EncryptedPayloadHash, error)
  36. StoreRaw(data []byte, from string) (common.EncryptedPayloadHash, error)
  37. SendSignedTx(data common.EncryptedPayloadHash, to []string, extra *engine.ExtraMetadata) (string, []string, []byte, error)
  38. // Returns nil payload if not found
  39. Receive(data common.EncryptedPayloadHash) (string, []string, []byte, *engine.ExtraMetadata, error)
  40. // Returns nil payload if not found
  41. ReceiveRaw(data common.EncryptedPayloadHash) ([]byte, string, *engine.ExtraMetadata, error)
  42. IsSender(txHash common.EncryptedPayloadHash) (bool, error)
  43. GetParticipants(txHash common.EncryptedPayloadHash) ([]string, error)
  44. GetMandatory(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. Groups() ([]engine.PrivacyGroup, error)
  48. }
  49. // This loads any config specified via the legacy environment variable
  50. func GetLegacyEnvironmentConfig() (http2.Config, error) {
  51. return FromEnvironmentOrNil("PRIVATE_CONFIG")
  52. }
  53. func FromEnvironmentOrNil(name string) (http2.Config, error) {
  54. cfgPath := os.Getenv(name)
  55. cfg, err := http2.FetchConfigOrIgnore(cfgPath)
  56. if err != nil {
  57. return http2.Config{}, err
  58. }
  59. return cfg, nil
  60. }
  61. func InitialiseConnection(cfg http2.Config, isLightClient bool) error {
  62. var err error
  63. if isLightClient {
  64. P, err = NewQLightTxManager()
  65. return err
  66. }
  67. P, err = NewPrivateTxManager(cfg)
  68. return err
  69. }
  70. func IsQuorumPrivacyEnabled() bool {
  71. return isPrivacyEnabled
  72. }
  73. func NewQLightTxManager() (PrivateTransactionManager, error) {
  74. isPrivacyEnabled = true
  75. return qlightptm.New(), nil
  76. }
  77. func NewPrivateTxManager(cfg http2.Config) (PrivateTransactionManager, error) {
  78. if cfg.ConnectionType == http2.NoConnection {
  79. log.Info("Running with private transaction manager disabled - quorum private transactions will not be supported")
  80. return &notinuse.PrivateTransactionManager{}, nil
  81. }
  82. client, err := http2.CreateClient(cfg)
  83. if err != nil {
  84. return nil, fmt.Errorf("unable to create connection to private tx manager due to: %s", err)
  85. }
  86. ptm, err := selectPrivateTxManager(client)
  87. if err != nil {
  88. return nil, fmt.Errorf("unable to connect to private tx manager due to: %s", err)
  89. }
  90. isPrivacyEnabled = true
  91. return ptm, nil
  92. }
  93. // First call /upcheck to make sure the private tx manager is up
  94. // Then call /version to decide which private tx manager client implementation to be used
  95. func selectPrivateTxManager(client *engine.Client) (PrivateTransactionManager, error) {
  96. res, err := client.Get("/upcheck")
  97. if err != nil {
  98. return nil, err
  99. }
  100. if res.StatusCode != 200 {
  101. return nil, engine.ErrPrivateTxManagerNotReady
  102. }
  103. res, err = client.Get("/version")
  104. if err != nil {
  105. return nil, err
  106. }
  107. defer res.Body.Close()
  108. version, err := ioutil.ReadAll(res.Body)
  109. if err != nil {
  110. return nil, err
  111. }
  112. var privateTxManager PrivateTransactionManager
  113. defer func() {
  114. log.Info("Target Private Tx Manager", "name", privateTxManager.Name(), "distributionVersion", string(version))
  115. }()
  116. if res.StatusCode != 200 {
  117. // Constellation doesn't have /version endpoint
  118. privateTxManager = constellation.New(client)
  119. } else {
  120. privateTxManager = tessera.New(client, []byte(tessera.RetrieveTesseraAPIVersion(client)))
  121. }
  122. return privateTxManager, nil
  123. }
  124. // Retrieve the private transaction that is associated with a privacy marker transaction
  125. func FetchPrivateTransaction(data []byte) (*types.Transaction, []string, *engine.ExtraMetadata, error) {
  126. return FetchPrivateTransactionWithPTM(data, P)
  127. }
  128. func FetchPrivateTransactionWithPTM(data []byte, ptm PrivateTransactionManager) (*types.Transaction, []string, *engine.ExtraMetadata, error) {
  129. txHash := common.BytesToEncryptedPayloadHash(data)
  130. _, managedParties, txData, metadata, err := ptm.Receive(txHash)
  131. if err != nil {
  132. return nil, nil, nil, err
  133. }
  134. if txData == nil {
  135. return nil, nil, nil, nil
  136. }
  137. var tx types.Transaction
  138. err = json.NewDecoder(bytes.NewReader(txData)).Decode(&tx)
  139. if err != nil {
  140. log.Trace("failed to deserialize private transaction", "err", err)
  141. return nil, nil, nil, err
  142. }
  143. return &tx, managedParties, metadata, nil
  144. }