123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- package qlight
- import (
- "context"
- "fmt"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/mps"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/multitenancy"
- "github.com/ethereum/go-ethereum/plugin/security"
- "github.com/ethereum/go-ethereum/private"
- "github.com/ethereum/go-ethereum/rpc"
- )
- type privateBlockDataResolverImpl struct {
- privateStateManager mps.PrivateStateManager
- ptm private.PrivateTransactionManager
- }
- func NewPrivateBlockDataResolver(privateStateManager mps.PrivateStateManager, ptm private.PrivateTransactionManager) PrivateBlockDataResolver {
- return &privateBlockDataResolverImpl{privateStateManager: privateStateManager, ptm: ptm}
- }
- func (p *privateBlockDataResolverImpl) PrepareBlockPrivateData(block *types.Block, psi string) (*BlockPrivateData, error) {
- PSI := types.PrivateStateIdentifier(psi)
- var pvtTxs []PrivateTransactionData
- psm, err := p.privateStateManager.ResolveForUserContext(rpc.WithPrivateStateIdentifier(context.Background(), PSI))
- if err != nil {
- return nil, err
- }
- for _, tx := range block.Transactions() {
- if tx.IsPrivacyMarker() {
- ptd, err := p.fetchPrivateData(tx.Data(), psm)
- if err != nil {
- return nil, err
- }
- if ptd != nil {
- pvtTxs = append(pvtTxs, *ptd)
- }
- innerTx, _, _, _ := private.FetchPrivateTransactionWithPTM(tx.Data(), p.ptm)
- if innerTx != nil {
- tx = innerTx
- }
- }
- if tx.IsPrivate() {
- ptd, err := p.fetchPrivateData(tx.Data(), psm)
- if err != nil {
- return nil, err
- }
- if ptd != nil {
- pvtTxs = append(pvtTxs, *ptd)
- }
- }
- }
- if len(pvtTxs) == 0 {
- return nil, nil
- }
- var privateStateRoot = common.Hash{}
- stateRepo, err := p.privateStateManager.StateRepository(block.Root())
- if err != nil {
- log.Debug("Unable to retrieve private state repo while preparing the private block data", "block.No", block.Number(), "psi", psi, "err", err)
- } else {
- privateStateRoot, err = stateRepo.PrivateStateRoot(PSI)
- if err != nil {
- log.Debug("Unable to retrieve private state root while preparing the private block data", "block.No", block.Number(), "psi", psi, "err", err)
- }
- }
- return &BlockPrivateData{
- BlockHash: block.Hash(),
- PSI: PSI,
- PrivateStateRoot: privateStateRoot,
- PrivateTransactions: pvtTxs,
- }, nil
- }
- func (p *privateBlockDataResolverImpl) fetchPrivateData(encryptedPayloadHash []byte, psm *mps.PrivateStateMetadata) (*PrivateTransactionData, error) {
- txHash := common.BytesToEncryptedPayloadHash(encryptedPayloadHash)
- _, _, privateTx, extra, err := p.ptm.Receive(txHash)
- if err != nil {
- return nil, err
- }
- // we're not party to this transaction
- if privateTx == nil {
- return nil, nil
- }
- if p.privateStateManager.NotIncludeAny(psm, extra.ManagedParties...) {
- return nil, nil
- }
- extra.ManagedParties = psm.FilterAddresses(extra.ManagedParties...)
- ptd := PrivateTransactionData{
- Hash: &txHash,
- Payload: privateTx,
- Extra: extra,
- IsSender: false,
- }
- if len(psm.Addresses) == 0 {
- // this is not an MPS node so we have to ask tessera
- ptd.IsSender, err = p.ptm.IsSender(txHash)
- if err != nil {
- return nil, err
- }
- } else {
- // this is an MPS node so we can speed up the IsSender logic by checking the addresses in the private state metadata
- ptd.IsSender = !psm.NotIncludeAny(extra.Sender)
- }
- return &ptd, nil
- }
- type authProviderImpl struct {
- privateStateManager mps.PrivateStateManager
- authManagerProvider AuthManagerProvider
- authManager security.AuthenticationManager
- enabled bool
- }
- func NewAuthProvider(privateStateManager mps.PrivateStateManager, authManagerProvider AuthManagerProvider) AuthProvider {
- return &authProviderImpl{
- privateStateManager: privateStateManager,
- authManagerProvider: authManagerProvider,
- enabled: false,
- }
- }
- func (a *authProviderImpl) Initialize() error {
- if a.authManagerProvider != nil {
- a.authManager = a.authManagerProvider()
- if a.authManager == nil {
- return nil
- }
- authEnabled, err := a.authManager.IsEnabled(context.Background())
- if err != nil {
- return err
- }
- a.enabled = authEnabled
- }
- return nil
- }
- func (a *authProviderImpl) Authorize(token string, psi string) error {
- if !a.enabled {
- return nil
- }
- authToken, err := a.authManager.Authenticate(context.Background(), token)
- if err != nil {
- return err
- }
- PSI := types.PrivateStateIdentifier(psi)
- // check that we have access to the relevant PSI
- psiAuth, err := multitenancy.IsPSIAuthorized(authToken, PSI)
- if err != nil {
- return err
- }
- if !psiAuth {
- return fmt.Errorf("PSI not authorized")
- }
- // check that we have access to qlight://p2p , rpc://eth_*
- qlightP2P := false
- rpcETH := false
- for _, ga := range authToken.GetAuthorities() {
- if ga.GetRaw() == "p2p://qlight" {
- qlightP2P = true
- }
- if ga.GetRaw() == "rpc://eth_*" {
- rpcETH = true
- }
- }
- if !qlightP2P || !rpcETH {
- return fmt.Errorf("The P2P token does not have the necessary authorization p2p=%v rpcETH=%v", qlightP2P, rpcETH)
- }
- // try to resolve the PSI
- _, err = a.privateStateManager.ResolveForUserContext(rpc.WithPrivateStateIdentifier(context.Background(), PSI))
- if err != nil {
- return fmt.Errorf("QLight auth error: %w", err)
- }
- return nil
- }
|