github.com/Night-mk/quorum@v21.1.0+incompatible/extension/privacyExtension/state_setter.go (about)

     1  package privacyExtension
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  
     7  	"github.com/ethereum/go-ethereum/common"
     8  	"github.com/ethereum/go-ethereum/core/state"
     9  	"github.com/ethereum/go-ethereum/core/types"
    10  	extension "github.com/ethereum/go-ethereum/extension/extensionContracts"
    11  	"github.com/ethereum/go-ethereum/log"
    12  	"github.com/ethereum/go-ethereum/private"
    13  )
    14  
    15  var DefaultExtensionHandler = NewExtensionHandler(private.P)
    16  
    17  type ExtensionHandler struct {
    18  	ptm           private.PrivateTransactionManager
    19  	isMultitenant bool
    20  }
    21  
    22  func NewExtensionHandler(transactionManager private.PrivateTransactionManager) *ExtensionHandler {
    23  	return &ExtensionHandler{ptm: transactionManager}
    24  }
    25  
    26  func (handler *ExtensionHandler) SupportMultitenancy(b bool) {
    27  	handler.isMultitenant = b
    28  }
    29  
    30  func (handler *ExtensionHandler) CheckExtensionAndSetPrivateState(txLogs []*types.Log, privateState *state.StateDB) {
    31  	extraMetaDataUpdated := false
    32  	for _, txLog := range txLogs {
    33  		if logContainsExtensionTopic(txLog) {
    34  			//this is a direct state share
    35  			address, hash, uuid, err := extension.UnpackStateSharedLog(txLog.Data)
    36  			if err != nil {
    37  				continue
    38  			}
    39  
    40  			// check if state exists for the extension address. If yes then skip
    41  			// processing
    42  			if privateState.GetCode(address) != nil {
    43  				if extraMetaDataUpdated {
    44  					continue
    45  				}
    46  				// check the privacy flag of the contract. if its other than
    47  				// 0 then need to update the privacy metadata for the contract
    48  				//TODO: validate the old and new parties to ensure that all old parties are there
    49  				setPrivacyMetadata(privateState, address, hash)
    50  				if handler.isMultitenant {
    51  					setManagedParties(handler.ptm, privateState, address, hash)
    52  				}
    53  				extraMetaDataUpdated = true
    54  			} else {
    55  				managedParties, accounts, privacyMetaData, found := handler.FetchStateData(txLog.Address, hash, uuid)
    56  				if !found {
    57  					continue
    58  				}
    59  				if !handler.isMultitenant {
    60  					managedParties = nil
    61  				}
    62  				if !validateAccountsExist([]common.Address{address}, accounts) {
    63  					log.Error("Account mismatch", "expected", address, "found", accounts)
    64  					continue
    65  				}
    66  				snapshotId := privateState.Snapshot()
    67  
    68  				if success := setState(privateState, accounts, privacyMetaData, managedParties); !success {
    69  					privateState.RevertToSnapshot(snapshotId)
    70  				}
    71  			}
    72  
    73  		}
    74  	}
    75  }
    76  
    77  func (handler *ExtensionHandler) FetchStateData(address common.Address, hash string, uuid string) ([]string, map[string]extension.AccountWithMetadata, *state.PrivacyMetadata, bool) {
    78  	if uuidIsSentByUs := handler.UuidIsOwn(address, uuid); !uuidIsSentByUs {
    79  		return nil, nil, nil, false
    80  	}
    81  
    82  	managedParties, stateData, privacyMetaData, ok := handler.FetchDataFromPTM(hash)
    83  	if !ok {
    84  		//there is nothing to do here, the state wasn't shared with us
    85  		log.Error("Extension: No state shared with us")
    86  		return nil, nil, nil, false
    87  	}
    88  
    89  	var accounts map[string]extension.AccountWithMetadata
    90  	if err := json.Unmarshal(stateData, &accounts); err != nil {
    91  		log.Error("Extension: Could not unmarshal data")
    92  		return nil, nil, nil, false
    93  	}
    94  
    95  	return managedParties, accounts, privacyMetaData, true
    96  }
    97  
    98  // Checks
    99  
   100  func (handler *ExtensionHandler) FetchDataFromPTM(hash string) ([]string, []byte, *state.PrivacyMetadata, bool) {
   101  	ptmHash, _ := common.Base64ToEncryptedPayloadHash(hash)
   102  	_, managedParties, stateData, extraMetaData, err := handler.ptm.Receive(ptmHash)
   103  
   104  	if stateData == nil {
   105  		log.Error("No state data found in PTM", "ptm hash", hash)
   106  		return nil, nil, nil, false
   107  	}
   108  	if err != nil {
   109  		log.Error("Error receiving state data from PTM", "ptm hash", hash, "err", err.Error())
   110  		return nil, nil, nil, false
   111  	}
   112  
   113  	privacyMetaData := state.NewStatePrivacyMetadata(ptmHash, extraMetaData.PrivacyFlag)
   114  	return managedParties, stateData, privacyMetaData, true
   115  }
   116  
   117  func (handler *ExtensionHandler) UuidIsOwn(address common.Address, uuid string) bool {
   118  	if uuid == "" {
   119  		//we never called accept
   120  		log.Warn("Extension: State shared by accept never called")
   121  		return false
   122  	}
   123  	encryptedTxHash := common.BytesToEncryptedPayloadHash(common.FromHex(uuid))
   124  	isSender, err := handler.ptm.IsSender(encryptedTxHash)
   125  	if isSender {
   126  		if err != nil {
   127  			log.Debug("Extension: could not determine if we are sender", "err", err.Error())
   128  			return false
   129  		}
   130  
   131  		_, _, encryptedPayload, _, err := handler.ptm.Receive(encryptedTxHash)
   132  		if err != nil {
   133  			log.Debug("Extension: payload not found", "err", err)
   134  			return false
   135  		}
   136  		var payload common.DecryptRequest
   137  		err = json.Unmarshal(encryptedPayload, &payload)
   138  		if err != nil {
   139  			log.Debug("Extension: payload unmarshal failed", "err", err)
   140  		}
   141  
   142  		contractDetails, _, err := handler.ptm.DecryptPayload(payload)
   143  		if err != nil {
   144  			log.Debug("Extension: payload decrypt failed", "err", err)
   145  		}
   146  
   147  		if !bytes.Equal(contractDetails, address.Bytes()) {
   148  			log.Error("Extension: wrong address in retrieved UUID")
   149  			return false
   150  		}
   151  	}
   152  	return isSender
   153  }