github.com/coltonfike/e2c@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  }