github.com/Night-mk/quorum@v21.1.0+incompatible/permission/core/cache.go (about) 1 package core 2 3 import ( 4 "errors" 5 "fmt" 6 "math/big" 7 "strings" 8 "sync" 9 10 "github.com/ethereum/go-ethereum/common" 11 "github.com/ethereum/go-ethereum/p2p/enode" 12 "github.com/hashicorp/golang-lru" 13 ) 14 15 type TransactionType uint8 16 17 const ( 18 ValueTransferTxn TransactionType = iota 19 ContractCallTxn 20 ContractDeployTxn 21 ) 22 23 type AccessType uint8 24 25 const ( 26 // common access type list for both V1 and V2 model. 27 // the first 4 are used by both models 28 // last 3 are used by V2 in alignment with EEA specs 29 ReadOnly AccessType = iota 30 Transact 31 ContractDeploy 32 FullAccess 33 // below access types are only used by V2 model 34 ContractCall 35 TransactAndContractCall 36 TransactAndContractDeploy 37 ContractCallAndDeploy 38 ) 39 40 type PermissionModelType uint8 41 42 const ( 43 V1 PermissionModelType = iota 44 V2 45 Default 46 ) 47 48 type OrgStatus uint8 49 50 const ( 51 OrgPendingApproval OrgStatus = iota + 1 52 OrgApproved 53 OrgPendingSuspension 54 OrgSuspended 55 ) 56 57 type OrgInfo struct { 58 OrgId string `json:"orgId"` 59 FullOrgId string `json:"fullOrgId"` 60 ParentOrgId string `json:"parentOrgId"` 61 UltimateParent string `json:"ultimateParent"` 62 Level *big.Int `json:"level"` 63 SubOrgList []string `json:"subOrgList"` 64 Status OrgStatus `json:"status"` 65 } 66 67 type NodeStatus uint8 68 69 const ( 70 NodePendingApproval NodeStatus = iota + 1 71 NodeApproved 72 NodeDeactivated 73 NodeBlackListed 74 NodeRecoveryInitiated 75 ) 76 77 type AcctStatus uint8 78 79 const ( 80 AcctPendingApproval AcctStatus = iota + 1 81 AcctActive 82 AcctInactive 83 AcctSuspended 84 AcctBlacklisted 85 AdminRevoked 86 AcctRecoveryInitiated 87 AcctRecoveryCompleted 88 ) 89 90 type NodeInfo struct { 91 OrgId string `json:"orgId"` 92 Url string `json:"url"` 93 Status NodeStatus `json:"status"` 94 } 95 96 type RoleInfo struct { 97 OrgId string `json:"orgId"` 98 RoleId string `json:"roleId"` 99 IsVoter bool `json:"isVoter"` 100 IsAdmin bool `json:"isAdmin"` 101 Access AccessType `json:"access"` 102 Active bool `json:"active"` 103 } 104 105 type AccountInfo struct { 106 OrgId string `json:"orgId"` 107 RoleId string `json:"roleId"` 108 AcctId common.Address `json:"acctId"` 109 IsOrgAdmin bool `json:"isOrgAdmin"` 110 Status AcctStatus `json:"status"` 111 } 112 113 type OrgDetailInfo struct { 114 NodeList []NodeInfo `json:"nodeList"` 115 RoleList []RoleInfo `json:"roleList"` 116 AcctList []AccountInfo `json:"acctList"` 117 SubOrgList []string `json:"subOrgList"` 118 } 119 120 var syncStarted = false 121 122 var defaultAccess = FullAccess 123 var qip714BlockReached = false 124 var networkBootUpCompleted = false 125 var networkAdminRole string 126 var orgAdminRole string 127 var PermissionModel = Default 128 var PermissionTransactionAllowedFunc func(_sender common.Address, _target common.Address, _value *big.Int, _gasPrice *big.Int, _gasLimit *big.Int, _payload []byte, _transactionType TransactionType) error 129 var ( 130 OrgInfoMap *OrgCache 131 NodeInfoMap *NodeCache 132 RoleInfoMap *RoleCache 133 AcctInfoMap *AcctCache 134 ) 135 136 type OrgKey struct { 137 OrgId string 138 } 139 140 type OrgCache struct { 141 c *lru.Cache 142 mux sync.Mutex 143 evicted bool 144 populateCacheFunc func(orgId string) (*OrgInfo, error) 145 } 146 147 func (o *OrgCache) PopulateCacheFunc(cf func(string) (*OrgInfo, error)) { 148 o.populateCacheFunc = cf 149 } 150 151 func NewOrgCache(cacheSize int) *OrgCache { 152 orgCache := OrgCache{evicted: false} 153 onEvictedFunc := func(k interface{}, v interface{}) { 154 orgCache.evicted = true 155 } 156 orgCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc) 157 return &orgCache 158 } 159 160 type RoleKey struct { 161 OrgId string 162 RoleId string 163 } 164 165 type RoleCache struct { 166 c *lru.Cache 167 evicted bool 168 populateCacheFunc func(*RoleKey) (*RoleInfo, error) 169 } 170 171 func (r *RoleCache) PopulateCacheFunc(cf func(*RoleKey) (*RoleInfo, error)) { 172 r.populateCacheFunc = cf 173 } 174 175 func NewRoleCache(cacheSize int) *RoleCache { 176 roleCache := RoleCache{evicted: false} 177 onEvictedFunc := func(k interface{}, v interface{}) { 178 roleCache.evicted = true 179 } 180 roleCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc) 181 return &roleCache 182 } 183 184 type NodeKey struct { 185 OrgId string 186 Url string 187 } 188 189 type NodeCache struct { 190 c *lru.Cache 191 evicted bool 192 populateCacheFunc func(string) (*NodeInfo, error) 193 populateAndValidateFunc func(string, string) bool 194 } 195 196 func (n *NodeCache) PopulateValidateFunc(cf func(string, string) bool) { 197 n.populateAndValidateFunc = cf 198 } 199 200 func (n *NodeCache) PopulateCacheFunc(cf func(string) (*NodeInfo, error)) { 201 n.populateCacheFunc = cf 202 } 203 204 func NewNodeCache(cacheSize int) *NodeCache { 205 nodeCache := NodeCache{evicted: false} 206 onEvictedFunc := func(k interface{}, v interface{}) { 207 nodeCache.evicted = true 208 209 } 210 nodeCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc) 211 return &nodeCache 212 } 213 214 type AccountKey struct { 215 AcctId common.Address 216 } 217 218 type AcctCache struct { 219 c *lru.Cache 220 evicted bool 221 populateCacheFunc func(account common.Address) (*AccountInfo, error) 222 } 223 224 func (a *AcctCache) PopulateCacheFunc(cf func(common.Address) (*AccountInfo, error)) { 225 a.populateCacheFunc = cf 226 } 227 228 func NewAcctCache(cacheSize int) *AcctCache { 229 acctCache := AcctCache{evicted: false} 230 onEvictedFunc := func(k interface{}, v interface{}) { 231 acctCache.evicted = true 232 } 233 234 acctCache.c, _ = lru.NewWithEvict(cacheSize, onEvictedFunc) 235 return &acctCache 236 } 237 238 func SetSyncStatus() { 239 syncStarted = true 240 } 241 242 func GetSyncStatus() bool { 243 return syncStarted 244 } 245 246 // sets default access to read only 247 func setDefaultAccess() { 248 if PermissionsEnabled() { 249 defaultAccess = ReadOnly 250 } 251 } 252 253 // sets the qip714block reached as true 254 func SetQIP714BlockReached() { 255 qip714BlockReached = true 256 setDefaultAccess() 257 } 258 259 // sets the network boot completed as true 260 func SetNetworkBootUpCompleted() { 261 networkBootUpCompleted = true 262 setDefaultAccess() 263 } 264 265 // return bool to indicate if permissions is enabled 266 func PermissionsEnabled() bool { 267 if PermissionModel == V2 { 268 return qip714BlockReached 269 } else { 270 return qip714BlockReached && networkBootUpCompleted 271 } 272 } 273 274 // sets default access to readonly and initializes the values for 275 // network admin role and org admin role 276 func SetDefaults(nwRoleId, oaRoleId string, permissionV2 bool) { 277 networkAdminRole = nwRoleId 278 orgAdminRole = oaRoleId 279 if permissionV2 { 280 PermissionModel = V2 281 } else { 282 PermissionModel = V1 283 } 284 } 285 286 func GetDefaults() (string, string, AccessType) { 287 return networkAdminRole, orgAdminRole, defaultAccess 288 } 289 290 func GetNodeUrl(enodeId string, ip string, port uint16, raftport uint16, isRaft bool) string { 291 if isRaft { 292 return fmt.Sprintf("enode://%s@%s:%d?discport=0&raftport=%d", enodeId, strings.Trim(ip, "\x00"), port, raftport) 293 } 294 return fmt.Sprintf("enode://%s@%s:%d?discport=0", enodeId, strings.Trim(ip, "\x00"), port) 295 } 296 297 func (o *OrgCache) UpsertOrg(orgId, parentOrg, ultimateParent string, level *big.Int, status OrgStatus) { 298 defer o.mux.Unlock() 299 o.mux.Lock() 300 var key OrgKey 301 if parentOrg == "" { 302 key = OrgKey{OrgId: orgId} 303 } else { 304 key = OrgKey{OrgId: parentOrg + "." + orgId} 305 pkey := OrgKey{OrgId: parentOrg} 306 if ent, ok := o.c.Get(pkey); ok { 307 porg := ent.(*OrgInfo) 308 if !containsKey(porg.SubOrgList, key.OrgId) { 309 porg.SubOrgList = append(porg.SubOrgList, key.OrgId) 310 o.c.Add(pkey, porg) 311 } 312 } 313 } 314 315 norg := &OrgInfo{orgId, key.OrgId, parentOrg, ultimateParent, level, nil, status} 316 o.c.Add(key, norg) 317 } 318 319 func (o *OrgCache) UpsertOrgWithSubOrgList(orgRec *OrgInfo) { 320 var key OrgKey 321 if orgRec.ParentOrgId == "" { 322 key = OrgKey{OrgId: orgRec.OrgId} 323 } else { 324 key = OrgKey{OrgId: orgRec.ParentOrgId + "." + orgRec.OrgId} 325 } 326 orgRec.FullOrgId = key.OrgId 327 o.c.Add(key, orgRec) 328 } 329 330 func containsKey(s []string, e string) bool { 331 for _, a := range s { 332 if a == e { 333 return true 334 } 335 } 336 return false 337 } 338 339 func (o *OrgCache) GetOrg(orgId string) (*OrgInfo, error) { 340 key := OrgKey{OrgId: orgId} 341 if ent, ok := o.c.Get(key); ok { 342 return ent.(*OrgInfo), nil 343 } 344 // check if the org cache is evicted. if yes we need 345 // fetch the record from the contract 346 if o.evicted { 347 // call cache population function to populate from contract 348 orgRec, err := o.populateCacheFunc(orgId) 349 if err != nil { 350 return nil, err 351 } 352 // insert the received record into cache 353 o.UpsertOrgWithSubOrgList(orgRec) 354 //return the record 355 return orgRec, nil 356 } 357 return nil, errors.New("Org does not exist") 358 } 359 360 func (o *OrgCache) GetOrgList() []OrgInfo { 361 olist := make([]OrgInfo, len(o.c.Keys())) 362 for i, k := range o.c.Keys() { 363 v, _ := o.c.Get(k) 364 vp := v.(*OrgInfo) 365 olist[i] = *vp 366 } 367 return olist 368 } 369 370 func (n *NodeCache) UpsertNode(orgId string, url string, status NodeStatus) { 371 key := NodeKey{OrgId: orgId, Url: url} 372 n.c.Add(key, &NodeInfo{orgId, url, status}) 373 } 374 375 func (n *NodeCache) GetNodeByUrl(url string) (*NodeInfo, error) { 376 for _, k := range n.c.Keys() { 377 ent := k.(NodeKey) 378 if ent.Url == url { 379 v, _ := n.c.Get(ent) 380 return v.(*NodeInfo), nil 381 } 382 } 383 // check if the node cache is evicted. if yes we need 384 // fetch the record from the contract 385 if n.evicted { 386 387 // call cache population function to populate from contract 388 nodeRec, err := n.populateCacheFunc(url) 389 if err != nil { 390 return nil, err 391 } 392 393 // insert the received record into cache 394 n.UpsertNode(nodeRec.OrgId, nodeRec.Url, nodeRec.Status) 395 //return the record 396 return nodeRec, err 397 } 398 return nil, errors.New("Node does not exist") 399 } 400 401 func (n *NodeCache) GetNodeList() []NodeInfo { 402 olist := make([]NodeInfo, len(n.c.Keys())) 403 for i, k := range n.c.Keys() { 404 v, _ := n.c.Get(k) 405 vp := v.(*NodeInfo) 406 olist[i] = *vp 407 } 408 return olist 409 } 410 411 func (a *AcctCache) UpsertAccount(orgId string, role string, acct common.Address, orgAdmin bool, status AcctStatus) { 412 key := AccountKey{acct} 413 a.c.Add(key, &AccountInfo{orgId, role, acct, orgAdmin, status}) 414 } 415 416 func (a *AcctCache) GetAccount(acct common.Address) (*AccountInfo, error) { 417 if v, ok := a.c.Get(AccountKey{acct}); ok { 418 return v.(*AccountInfo), nil 419 } 420 421 // check if the account cache is evicted. if yes we need 422 // fetch the record from the contract 423 if a.evicted { 424 // call function to populate cache with the record 425 acctRec, err := a.populateCacheFunc(acct) 426 // insert the received record into cache 427 if err != nil { 428 return nil, err 429 } 430 a.UpsertAccount(acctRec.OrgId, acctRec.RoleId, acctRec.AcctId, acctRec.IsOrgAdmin, acctRec.Status) 431 //return the record 432 return acctRec, nil 433 } 434 return nil, nil 435 } 436 437 func (a *AcctCache) GetAcctList() []AccountInfo { 438 alist := make([]AccountInfo, len(a.c.Keys())) 439 for i, k := range a.c.Keys() { 440 v, _ := a.c.Get(k) 441 vp := v.(*AccountInfo) 442 alist[i] = *vp 443 } 444 return alist 445 } 446 447 func (a *AcctCache) GetAcctListOrg(orgId string) []AccountInfo { 448 var alist []AccountInfo 449 for _, k := range a.c.Keys() { 450 v, _ := a.c.Get(k) 451 vp := v.(*AccountInfo) 452 if vp.OrgId == orgId { 453 alist = append(alist, *vp) 454 } 455 } 456 return alist 457 } 458 459 func (a *AcctCache) GetAcctListRole(orgId, roleId string) []AccountInfo { 460 var alist []AccountInfo 461 for _, k := range a.c.Keys() { 462 v, _ := a.c.Get(k) 463 vp := v.(*AccountInfo) 464 465 orgRec, err := OrgInfoMap.GetOrg(vp.OrgId) 466 if err != nil { 467 return nil 468 } 469 470 if vp.RoleId == roleId && (vp.OrgId == orgId || (orgRec != nil && orgRec.UltimateParent == orgId)) { 471 alist = append(alist, *vp) 472 } 473 } 474 return alist 475 } 476 477 func (r *RoleCache) UpsertRole(orgId string, role string, voter bool, admin bool, access AccessType, active bool) { 478 key := RoleKey{orgId, role} 479 r.c.Add(key, &RoleInfo{orgId, role, voter, admin, access, active}) 480 481 } 482 483 func (r *RoleCache) GetRole(orgId string, roleId string) (*RoleInfo, error) { 484 key := RoleKey{OrgId: orgId, RoleId: roleId} 485 if ent, ok := r.c.Get(key); ok { 486 return ent.(*RoleInfo), nil 487 } 488 // check if the role cache is evicted. if yes we need 489 // fetch the record from the contract 490 if r.evicted { 491 // call cache population function to populate from contract 492 roleRec, err := r.populateCacheFunc(&RoleKey{RoleId: roleId, OrgId: orgId}) 493 if err != nil { 494 return nil, err 495 } 496 // insert the received record into cache 497 r.UpsertRole(roleRec.OrgId, roleRec.RoleId, roleRec.IsVoter, roleRec.IsAdmin, roleRec.Access, roleRec.Active) 498 499 //return the record 500 return roleRec, nil 501 } 502 return nil, errors.New("Invalid role") 503 } 504 505 func (r *RoleCache) GetRoleList() []RoleInfo { 506 rlist := make([]RoleInfo, len(r.c.Keys())) 507 for i, k := range r.c.Keys() { 508 v, _ := r.c.Get(k) 509 vp := v.(*RoleInfo) 510 rlist[i] = *vp 511 } 512 return rlist 513 } 514 515 // Returns the access type for an account. If not found returns 516 // default access 517 func GetAcctAccess(acctId common.Address) AccessType { 518 519 // check if the org status is fine to do the transaction 520 a, _ := AcctInfoMap.GetAccount(acctId) 521 if a != nil && a.Status == AcctActive { 522 // get the org details and ultimate org details. check org status 523 // if the org is not approved or pending suspension 524 if checkIfOrgActive(a.OrgId) { 525 if a.RoleId == networkAdminRole || a.RoleId == orgAdminRole { 526 return FullAccess 527 } 528 if r, _ := RoleInfoMap.GetRole(a.OrgId, a.RoleId); r != nil && r.Active { 529 return r.Access 530 } 531 if o, _ := OrgInfoMap.GetOrg(a.OrgId); o != nil { 532 if r, _ := RoleInfoMap.GetRole(o.UltimateParent, a.RoleId); r != nil && r.Active { 533 return r.Access 534 } 535 } 536 } 537 } 538 return defaultAccess 539 } 540 541 //checks if the given org is active in the network 542 func checkIfOrgActive(orgId string) bool { 543 o, _ := OrgInfoMap.GetOrg(orgId) 544 if o != nil && o.Status != OrgSuspended { 545 u, _ := OrgInfoMap.GetOrg(o.UltimateParent) 546 if u == nil { 547 return true 548 } 549 if u != nil && u.Status != OrgSuspended { 550 return true 551 } 552 } 553 return false 554 } 555 556 // checks if the passed account is linked to a org admin or 557 // network admin role 558 func CheckIfAdminAccount(acctId common.Address) bool { 559 if !PermissionsEnabled() { 560 return true 561 } 562 a, _ := AcctInfoMap.GetAccount(acctId) 563 if a != nil && a.Status == AcctActive { 564 if checkIfOrgActive(a.OrgId) { 565 if a.RoleId == networkAdminRole || a.RoleId == orgAdminRole { 566 return true 567 } 568 if r, _ := RoleInfoMap.GetRole(a.OrgId, a.RoleId); r != nil && r.Active && r.IsAdmin { 569 return true 570 } 571 if o, _ := OrgInfoMap.GetOrg(a.OrgId); o != nil { 572 if r, _ := RoleInfoMap.GetRole(o.UltimateParent, a.RoleId); r != nil && r.Active && r.IsAdmin { 573 return true 574 } 575 } 576 } 577 } 578 return false 579 } 580 581 // validates if the account can transact from the current node 582 func ValidateNodeForTxn(hexnodeId string, from common.Address) bool { 583 if !PermissionsEnabled() || hexnodeId == "" { 584 return true 585 } 586 587 passedEnodeId, err := enode.ParseV4(hexnodeId) 588 if err != nil { 589 return false 590 } 591 592 ac, _ := AcctInfoMap.GetAccount(from) 593 if ac == nil { 594 return true 595 } 596 597 acOrgRec, err := OrgInfoMap.GetOrg(ac.OrgId) 598 if err != nil { 599 return false 600 } 601 602 // scan through the node list and validate 603 for _, n := range NodeInfoMap.GetNodeList() { 604 orgRec, err := OrgInfoMap.GetOrg(n.OrgId) 605 if err != nil { 606 return false 607 } 608 if orgRec.UltimateParent == acOrgRec.UltimateParent { 609 recEnodeId, _ := enode.ParseV4(n.Url) 610 if recEnodeId.ID() == passedEnodeId.ID() && n.Status == NodeApproved { 611 return true 612 } 613 } 614 } 615 if NodeInfoMap.evicted { 616 return NodeInfoMap.populateAndValidateFunc(hexnodeId, acOrgRec.UltimateParent) 617 } 618 619 return false 620 } 621 622 func IsV2Permission() bool { 623 return PermissionModel == V2 624 } 625 626 // checks if the account permission allows the transaction to be executed 627 func IsTransactionAllowed(from common.Address, to common.Address, value *big.Int, gasPrice *big.Int, gasLimit *big.Int, payload []byte, transactionType TransactionType) error { 628 //if we have not reached QIP714 block return full access 629 if !PermissionsEnabled() { 630 return nil 631 } 632 633 return PermissionTransactionAllowedFunc(from, to, value, gasPrice, gasLimit, payload, transactionType) 634 }