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 }