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