123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178 |
- package privacyExtension
- import (
- "bytes"
- "encoding/json"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/mps"
- "github.com/ethereum/go-ethereum/core/state"
- "github.com/ethereum/go-ethereum/core/types"
- extension "github.com/ethereum/go-ethereum/extension/extensionContracts"
- "github.com/ethereum/go-ethereum/log"
- "github.com/ethereum/go-ethereum/private"
- )
- var DefaultExtensionHandler *ExtensionHandler
- type ExtensionHandler struct {
- ptm private.PrivateTransactionManager
- psmr mps.PrivateStateMetadataResolver
- isMultitenant bool
- }
- func Init() {
- DefaultExtensionHandler = NewExtensionHandler(private.P)
- }
- func NewExtensionHandler(transactionManager private.PrivateTransactionManager) *ExtensionHandler {
- return &ExtensionHandler{ptm: transactionManager}
- }
- func (handler *ExtensionHandler) SupportMultitenancy(b bool) {
- handler.isMultitenant = b
- }
- func (handler *ExtensionHandler) SetPSMR(psmr mps.PrivateStateMetadataResolver) {
- handler.psmr = psmr
- }
- func (handler *ExtensionHandler) CheckExtensionAndSetPrivateState(txLogs []*types.Log, privateState *state.StateDB, psi types.PrivateStateIdentifier) {
- extraMetaDataUpdated := false
- for _, txLog := range txLogs {
- if !logContainsExtensionTopic(txLog) {
- continue
- }
- //this is a direct state share
- address, hash, uuid, err := extension.UnpackStateSharedLog(txLog.Data)
- if err != nil {
- continue
- }
- // check if state exists for the extension address. If yes then skip
- // processing
- if privateState.GetCode(address) != nil {
- if extraMetaDataUpdated {
- continue
- }
- // check the privacy flag of the contract. if its other than
- // 0 then need to update the privacy metadata for the contract
- //TODO: validate the old and new parties to ensure that all old parties are there
- setPrivacyMetadata(privateState, address, hash)
- if handler.isMultitenant {
- setManagedParties(handler.ptm, privateState, address, hash)
- }
- extraMetaDataUpdated = true
- } else {
- managedParties, accounts, privacyMetaData, found := handler.FetchStateData(txLog.Address, hash, uuid, psi)
- if !found {
- continue
- }
- if !handler.isMultitenant {
- managedParties = nil
- }
- if !validateAccountsExist([]common.Address{address}, accounts) {
- log.Error("Account mismatch", "expected", address, "found", accounts)
- continue
- }
- snapshotId := privateState.Snapshot()
- if success := setState(privateState, accounts, privacyMetaData, managedParties); !success {
- privateState.RevertToSnapshot(snapshotId)
- }
- }
- }
- }
- func (handler *ExtensionHandler) FetchStateData(address common.Address, hash string, uuid string, psi types.PrivateStateIdentifier) ([]string, map[string]extension.AccountWithMetadata, *state.PrivacyMetadata, bool) {
- if uuidIsSentByUs := handler.UuidIsOwn(address, uuid, psi); !uuidIsSentByUs {
- return nil, nil, nil, false
- }
- managedParties, stateData, privacyMetaData, ok := handler.FetchDataFromPTM(hash)
- if !ok {
- //there is nothing to do here, the state wasn't shared with us
- log.Error("Extension: No state shared with us")
- return nil, nil, nil, false
- }
- var accounts map[string]extension.AccountWithMetadata
- if err := json.Unmarshal(stateData, &accounts); err != nil {
- log.Error("Extension: Could not unmarshal data")
- return nil, nil, nil, false
- }
- return managedParties, accounts, privacyMetaData, true
- }
- // Checks
- func (handler *ExtensionHandler) FetchDataFromPTM(hash string) ([]string, []byte, *state.PrivacyMetadata, bool) {
- ptmHash, _ := common.Base64ToEncryptedPayloadHash(hash)
- _, managedParties, stateData, extraMetaData, err := handler.ptm.Receive(ptmHash)
- if stateData == nil {
- log.Error("No state data found in PTM", "ptm hash", hash)
- return nil, nil, nil, false
- }
- if err != nil {
- log.Error("Error receiving state data from PTM", "ptm hash", hash, "err", err.Error())
- return nil, nil, nil, false
- }
- privacyMetaData := state.NewStatePrivacyMetadata(ptmHash, extraMetaData.PrivacyFlag)
- return managedParties, stateData, privacyMetaData, true
- }
- func (handler *ExtensionHandler) UuidIsOwn(address common.Address, uuid string, psi types.PrivateStateIdentifier) bool {
- if uuid == "" {
- //we never called accept
- log.Warn("Extension: State shared by accept never called")
- return false
- }
- encryptedTxHash := common.BytesToEncryptedPayloadHash(common.FromHex(uuid))
- isSender, err := handler.ptm.IsSender(encryptedTxHash)
- if err != nil {
- log.Debug("Extension: could not determine if we are sender", "err", err.Error())
- return false
- }
- if !isSender {
- return false
- }
- senderPublicKey, _, encryptedPayload, _, err := handler.ptm.Receive(encryptedTxHash)
- if err != nil {
- log.Debug("Extension: payload not found", "err", err)
- return false
- }
- //check the given PSI is same as PSI of sender key
- senderPsm, err := handler.psmr.ResolveForManagedParty(senderPublicKey)
- if err != nil {
- log.Debug("Extension: unable to determine sender public key PSI", "err", err)
- return false
- }
- if senderPsm.ID != psi {
- // sender was another tenant on this node
- //not an error case, so no need to log an error
- return false
- }
- var payload common.DecryptRequest
- if err := json.Unmarshal(encryptedPayload, &payload); err != nil {
- log.Debug("Extension: payload unmarshal failed", "err", err)
- }
- contractDetails, _, err := handler.ptm.DecryptPayload(payload)
- if err != nil {
- log.Debug("Extension: payload decrypt failed", "err", err)
- }
- if !bytes.Equal(contractDetails, address.Bytes()) {
- log.Error("Extension: wrong address in retrieved UUID")
- return false
- }
- return true
- }
|