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 }