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