server.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. package qlight
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/ethereum/go-ethereum/common"
  6. "github.com/ethereum/go-ethereum/core/mps"
  7. "github.com/ethereum/go-ethereum/core/types"
  8. "github.com/ethereum/go-ethereum/log"
  9. "github.com/ethereum/go-ethereum/multitenancy"
  10. "github.com/ethereum/go-ethereum/plugin/security"
  11. "github.com/ethereum/go-ethereum/private"
  12. "github.com/ethereum/go-ethereum/rpc"
  13. )
  14. type privateBlockDataResolverImpl struct {
  15. privateStateManager mps.PrivateStateManager
  16. ptm private.PrivateTransactionManager
  17. }
  18. func NewPrivateBlockDataResolver(privateStateManager mps.PrivateStateManager, ptm private.PrivateTransactionManager) PrivateBlockDataResolver {
  19. return &privateBlockDataResolverImpl{privateStateManager: privateStateManager, ptm: ptm}
  20. }
  21. func (p *privateBlockDataResolverImpl) PrepareBlockPrivateData(block *types.Block, psi string) (*BlockPrivateData, error) {
  22. PSI := types.PrivateStateIdentifier(psi)
  23. var pvtTxs []PrivateTransactionData
  24. psm, err := p.privateStateManager.ResolveForUserContext(rpc.WithPrivateStateIdentifier(context.Background(), PSI))
  25. if err != nil {
  26. return nil, err
  27. }
  28. for _, tx := range block.Transactions() {
  29. if tx.IsPrivacyMarker() {
  30. ptd, err := p.fetchPrivateData(tx.Data(), psm)
  31. if err != nil {
  32. return nil, err
  33. }
  34. if ptd != nil {
  35. pvtTxs = append(pvtTxs, *ptd)
  36. }
  37. innerTx, _, _, _ := private.FetchPrivateTransactionWithPTM(tx.Data(), p.ptm)
  38. if innerTx != nil {
  39. tx = innerTx
  40. }
  41. }
  42. if tx.IsPrivate() {
  43. ptd, err := p.fetchPrivateData(tx.Data(), psm)
  44. if err != nil {
  45. return nil, err
  46. }
  47. if ptd != nil {
  48. pvtTxs = append(pvtTxs, *ptd)
  49. }
  50. }
  51. }
  52. if len(pvtTxs) == 0 {
  53. return nil, nil
  54. }
  55. var privateStateRoot = common.Hash{}
  56. stateRepo, err := p.privateStateManager.StateRepository(block.Root())
  57. if err != nil {
  58. log.Debug("Unable to retrieve private state repo while preparing the private block data", "block.No", block.Number(), "psi", psi, "err", err)
  59. } else {
  60. privateStateRoot, err = stateRepo.PrivateStateRoot(PSI)
  61. if err != nil {
  62. log.Debug("Unable to retrieve private state root while preparing the private block data", "block.No", block.Number(), "psi", psi, "err", err)
  63. }
  64. }
  65. return &BlockPrivateData{
  66. BlockHash: block.Hash(),
  67. PSI: PSI,
  68. PrivateStateRoot: privateStateRoot,
  69. PrivateTransactions: pvtTxs,
  70. }, nil
  71. }
  72. func (p *privateBlockDataResolverImpl) fetchPrivateData(encryptedPayloadHash []byte, psm *mps.PrivateStateMetadata) (*PrivateTransactionData, error) {
  73. txHash := common.BytesToEncryptedPayloadHash(encryptedPayloadHash)
  74. _, _, privateTx, extra, err := p.ptm.Receive(txHash)
  75. if err != nil {
  76. return nil, err
  77. }
  78. // we're not party to this transaction
  79. if privateTx == nil {
  80. return nil, nil
  81. }
  82. if p.privateStateManager.NotIncludeAny(psm, extra.ManagedParties...) {
  83. return nil, nil
  84. }
  85. extra.ManagedParties = psm.FilterAddresses(extra.ManagedParties...)
  86. ptd := PrivateTransactionData{
  87. Hash: &txHash,
  88. Payload: privateTx,
  89. Extra: extra,
  90. IsSender: false,
  91. }
  92. if len(psm.Addresses) == 0 {
  93. // this is not an MPS node so we have to ask tessera
  94. ptd.IsSender, err = p.ptm.IsSender(txHash)
  95. if err != nil {
  96. return nil, err
  97. }
  98. } else {
  99. // this is an MPS node so we can speed up the IsSender logic by checking the addresses in the private state metadata
  100. ptd.IsSender = !psm.NotIncludeAny(extra.Sender)
  101. }
  102. return &ptd, nil
  103. }
  104. type authProviderImpl struct {
  105. privateStateManager mps.PrivateStateManager
  106. authManagerProvider AuthManagerProvider
  107. authManager security.AuthenticationManager
  108. enabled bool
  109. }
  110. func NewAuthProvider(privateStateManager mps.PrivateStateManager, authManagerProvider AuthManagerProvider) AuthProvider {
  111. return &authProviderImpl{
  112. privateStateManager: privateStateManager,
  113. authManagerProvider: authManagerProvider,
  114. enabled: false,
  115. }
  116. }
  117. func (a *authProviderImpl) Initialize() error {
  118. if a.authManagerProvider != nil {
  119. a.authManager = a.authManagerProvider()
  120. if a.authManager == nil {
  121. return nil
  122. }
  123. authEnabled, err := a.authManager.IsEnabled(context.Background())
  124. if err != nil {
  125. return err
  126. }
  127. a.enabled = authEnabled
  128. }
  129. return nil
  130. }
  131. func (a *authProviderImpl) Authorize(token string, psi string) error {
  132. if !a.enabled {
  133. return nil
  134. }
  135. authToken, err := a.authManager.Authenticate(context.Background(), token)
  136. if err != nil {
  137. return err
  138. }
  139. PSI := types.PrivateStateIdentifier(psi)
  140. // check that we have access to the relevant PSI
  141. psiAuth, err := multitenancy.IsPSIAuthorized(authToken, PSI)
  142. if err != nil {
  143. return err
  144. }
  145. if !psiAuth {
  146. return fmt.Errorf("PSI not authorized")
  147. }
  148. // check that we have access to qlight://p2p , rpc://eth_*
  149. qlightP2P := false
  150. rpcETH := false
  151. for _, ga := range authToken.GetAuthorities() {
  152. if ga.GetRaw() == "p2p://qlight" {
  153. qlightP2P = true
  154. }
  155. if ga.GetRaw() == "rpc://eth_*" {
  156. rpcETH = true
  157. }
  158. }
  159. if !qlightP2P || !rpcETH {
  160. return fmt.Errorf("The P2P token does not have the necessary authorization p2p=%v rpcETH=%v", qlightP2P, rpcETH)
  161. }
  162. // try to resolve the PSI
  163. _, err = a.privateStateManager.ResolveForUserContext(rpc.WithPrivateStateIdentifier(context.Background(), PSI))
  164. if err != nil {
  165. return fmt.Errorf("QLight auth error: %w", err)
  166. }
  167. return nil
  168. }