github.com/jpmorganchase/quorum@v21.1.0+incompatible/permission/backend.go (about) 1 package permission 2 3 import ( 4 "crypto/ecdsa" 5 "errors" 6 "math/big" 7 "sync" 8 "time" 9 10 "github.com/ethereum/go-ethereum/accounts" 11 "github.com/ethereum/go-ethereum/accounts/abi/bind" 12 "github.com/ethereum/go-ethereum/common" 13 "github.com/ethereum/go-ethereum/eth" 14 "github.com/ethereum/go-ethereum/internal/ethapi" 15 "github.com/ethereum/go-ethereum/log" 16 "github.com/ethereum/go-ethereum/node" 17 "github.com/ethereum/go-ethereum/p2p" 18 "github.com/ethereum/go-ethereum/permission/core" 19 ptype "github.com/ethereum/go-ethereum/permission/core/types" 20 "github.com/ethereum/go-ethereum/permission/v1" 21 "github.com/ethereum/go-ethereum/permission/v2" 22 "github.com/ethereum/go-ethereum/rpc" 23 ) 24 25 type PermissionCtrl struct { 26 node *node.Node 27 ethClnt bind.ContractBackend 28 eth *eth.Ethereum 29 key *ecdsa.PrivateKey 30 dataDir string 31 permConfig *ptype.PermissionConfig 32 contract ptype.InitService 33 backend ptype.Backend 34 useDns bool 35 isRaft bool 36 startWaitGroup *sync.WaitGroup // waitgroup to make sure all dependencies are ready before we start the service 37 errorChan chan error // channel to capture error when starting aysnc 38 networkInitialized bool 39 controlService ptype.ControlService 40 } 41 42 var permissionService *PermissionCtrl 43 44 func setPermissionService(ps *PermissionCtrl) { 45 if permissionService == nil { 46 permissionService = ps 47 } 48 } 49 50 // Create a service instance for permissioning 51 // 52 // Permission Service depends on the following: 53 // 1. EthService to be ready 54 // 2. Downloader to sync up blocks 55 // 3. InProc RPC server to be ready 56 func NewQuorumPermissionCtrl(stack *node.Node, pconfig *ptype.PermissionConfig, useDns bool) (*PermissionCtrl, error) { 57 wg := &sync.WaitGroup{} 58 wg.Add(1) 59 60 p := &PermissionCtrl{ 61 node: stack, 62 key: stack.GetNodeKey(), 63 dataDir: stack.DataDir(), 64 permConfig: pconfig, 65 startWaitGroup: wg, 66 errorChan: make(chan error), 67 useDns: useDns, 68 isRaft: false, 69 } 70 71 err := p.populateBackEnd() 72 if err != nil { 73 return nil, err 74 } 75 stopChan, stopSubscription := ptype.SubscribeStopEvent() 76 inProcRPCServerSub := stack.EventMux().Subscribe(rpc.InProcServerReadyEvent{}) 77 log.Debug("permission service: waiting for InProcRPC Server") 78 79 go func(_wg *sync.WaitGroup) { 80 defer func(start time.Time) { 81 log.Debug("permission service: InProcRPC server is ready", "took", time.Since(start)) 82 stopSubscription.Unsubscribe() 83 inProcRPCServerSub.Unsubscribe() 84 _wg.Done() 85 }(time.Now()) 86 select { 87 case <-inProcRPCServerSub.Chan(): 88 case <-stopChan: 89 } 90 }(wg) // wait for inproc RPC to be ready 91 return p, nil 92 } 93 94 func (p *PermissionCtrl) Start(srvr *p2p.Server) error { 95 log.Info("permission service: starting") 96 go func() { 97 log.Info("permission service: starting async") 98 p.asyncStart() 99 }() 100 return nil 101 } 102 103 func (p *PermissionCtrl) Protocols() []p2p.Protocol { 104 return []p2p.Protocol{} 105 } 106 107 func (p *PermissionCtrl) APIs() []rpc.API { 108 return []rpc.API{ 109 { 110 Namespace: "quorumPermission", 111 Version: "1.0", 112 Service: NewQuorumControlsAPI(p), 113 Public: true, 114 }, 115 } 116 } 117 118 func (p *PermissionCtrl) Stop() error { 119 log.Info("permission service: stopping") 120 ptype.StopFeed.Send(ptype.StopEvent{}) 121 log.Info("permission service: stopped") 122 return nil 123 } 124 125 func (p *PermissionCtrl) IsV2Permission() bool { 126 return p.permConfig.PermissionsModel == ptype.PERMISSION_V2 127 } 128 129 func NewPermissionContractService(ethClnt bind.ContractBackend, permissionV2 bool, key *ecdsa.PrivateKey, 130 permConfig *ptype.PermissionConfig, isRaft, useDns bool) ptype.InitService { 131 132 contractBackEnd := ptype.ContractBackend{ 133 EthClnt: ethClnt, 134 Key: key, 135 PermConfig: permConfig, 136 IsRaft: isRaft, 137 UseDns: useDns, 138 } 139 140 if permissionV2 { 141 return &v2.Init{ 142 Backend: contractBackEnd, 143 } 144 } 145 return &v1.Init{ 146 Backend: contractBackEnd, 147 } 148 } 149 150 func (p *PermissionCtrl) NewPermissionRoleService(txa ethapi.SendTxArgs) (ptype.RoleService, error) { 151 transactOpts, err := p.getTxParams(txa) 152 if err != nil { 153 return nil, err 154 } 155 return p.backend.GetRoleService(transactOpts, p.getContractBackend()) 156 } 157 158 func (p *PermissionCtrl) NewPermissionOrgService(txa ethapi.SendTxArgs) (ptype.OrgService, error) { 159 transactOpts, err := p.getTxParams(txa) 160 if err != nil { 161 return nil, err 162 } 163 return p.backend.GetOrgService(transactOpts, p.getContractBackend()) 164 } 165 166 func (p *PermissionCtrl) NewPermissionNodeService(txa ethapi.SendTxArgs) (ptype.NodeService, error) { 167 transactOpts, err := p.getTxParams(txa) 168 if err != nil { 169 return nil, err 170 } 171 return p.backend.GetNodeService(transactOpts, p.getContractBackend()) 172 } 173 174 func (p *PermissionCtrl) NewPermissionAccountService(txa ethapi.SendTxArgs) (ptype.AccountService, error) { 175 transactOpts, err := p.getTxParams(txa) 176 if err != nil { 177 return nil, err 178 } 179 return p.backend.GetAccountService(transactOpts, p.getContractBackend()) 180 } 181 182 func (p *PermissionCtrl) NewPermissionAuditService() (ptype.AuditService, error) { 183 return p.backend.GetAuditService(p.getContractBackend()) 184 } 185 186 func (p *PermissionCtrl) NewPermissionControlService() (ptype.ControlService, error) { 187 return p.backend.GetControlService(p.getContractBackend()) 188 } 189 190 func (p *PermissionCtrl) getContractBackend() ptype.ContractBackend { 191 return ptype.ContractBackend{EthClnt: p.ethClnt, Key: p.key, PermConfig: p.permConfig, IsRaft: p.isRaft, UseDns: p.isRaft} 192 } 193 194 func (p *PermissionCtrl) ConnectionAllowed(_enodeId, _ip string, _port, _raftPort uint16) (bool, error) { 195 cs, err := p.backend.GetControlService(p.getContractBackend()) 196 if err != nil { 197 return false, err 198 } 199 return cs.ConnectionAllowed(_enodeId, _ip, _port, _raftPort) 200 } 201 202 func (p *PermissionCtrl) IsTransactionAllowed(_sender common.Address, _target common.Address, _value *big.Int, _gasPrice *big.Int, _gasLimit *big.Int, _payload []byte, transactionType core.TransactionType) error { 203 // If permissions model is not in use return nil 204 if core.PermissionModel == core.Default { 205 return nil 206 } 207 208 cs, err := p.backend.GetControlService(p.getContractBackend()) 209 if err != nil { 210 return err 211 } 212 213 return cs.TransactionAllowed(_sender, _target, _value, _gasPrice, _gasLimit, _payload, transactionType) 214 } 215 216 func (p *PermissionCtrl) populateBackEnd() error { 217 backend := ptype.NewInterfaceBackend(p.node, false, p.dataDir) 218 219 switch p.permConfig.PermissionsModel { 220 case ptype.PERMISSION_V2: 221 p.backend = &v2.Backend{ 222 Ib: *backend, 223 } 224 log.Info("permission service: using v2 permissions model") 225 return nil 226 227 case ptype.PERMISSION_V1: 228 p.backend = &v1.Backend{ 229 Ib: *backend, 230 } 231 log.Info("permission service: using v1 permissions model") 232 return nil 233 234 default: 235 return errors.New("permission: invalid permissions model passed") 236 } 237 238 } 239 240 func (p *PermissionCtrl) updateBackEnd() { 241 p.contract = NewPermissionContractService(p.ethClnt, p.IsV2Permission(), p.key, p.permConfig, p.isRaft, p.useDns) 242 switch p.IsV2Permission() { 243 case true: 244 p.backend.(*v2.Backend).Contr = p.contract.(*v2.Init) 245 p.backend.(*v2.Backend).Ib.SetIsRaft(p.isRaft) 246 247 default: 248 p.backend.(*v1.Backend).Contr = p.contract.(*v1.Init) 249 p.backend.(*v1.Backend).Ib.SetIsRaft(p.isRaft) 250 } 251 } 252 253 // validateAccount validates the account and returns the wallet associated with that for signing the transaction 254 func (p *PermissionCtrl) validateAccount(from common.Address) (accounts.Wallet, error) { 255 acct := accounts.Account{Address: from} 256 w, err := p.eth.AccountManager().Find(acct) 257 if err != nil { 258 return nil, err 259 } 260 return w, nil 261 } 262 263 // getTxParams extracts the transaction related parameters 264 func (p *PermissionCtrl) getTxParams(txa ethapi.SendTxArgs) (*bind.TransactOpts, error) { 265 w, err := p.validateAccount(txa.From) 266 if err != nil { 267 return nil, ptype.ErrInvalidAccount 268 } 269 fromAcct := accounts.Account{Address: txa.From} 270 transactOpts := bind.NewWalletTransactor(w, fromAcct) 271 272 transactOpts.GasPrice = defaultGasPrice 273 if txa.GasPrice != nil { 274 transactOpts.GasPrice = txa.GasPrice.ToInt() 275 } 276 277 transactOpts.GasLimit = defaultGasLimit 278 if txa.Gas != nil { 279 transactOpts.GasLimit = uint64(*txa.Gas) 280 } 281 transactOpts.From = fromAcct.Address 282 283 return transactOpts, nil 284 }