github.com/jpmorganchase/quorum@v21.1.0+incompatible/multitenancy/authorization_provider_test.go (about)

     1  package multitenancy
     2  
     3  import (
     4  	"context"
     5  	"net/url"
     6  	"os"
     7  	"testing"
     8  
     9  	"github.com/ethereum/go-ethereum/common"
    10  	"github.com/ethereum/go-ethereum/log"
    11  	"github.com/jpmorganchase/quorum-security-plugin-sdk-go/proto"
    12  	"github.com/stretchr/testify/assert"
    13  )
    14  
    15  func init() {
    16  	log.Root().SetHandler(log.StreamHandler(os.Stdout, log.TerminalFormat(false)))
    17  }
    18  
    19  type testCase struct {
    20  	msg          string
    21  	granted      []string
    22  	ask          []*ContractSecurityAttribute
    23  	isAuthorized bool
    24  }
    25  
    26  func TestMatch_whenTypical(t *testing.T) {
    27  	granted, _ := url.Parse("private://0xa1b1c1/create/contracts?from.tm=A/")
    28  	ask, _ := url.Parse("private://0xa1b1c1/create/contracts?from.tm=A%2F")
    29  
    30  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
    31  }
    32  
    33  func TestMatch_whenAskNothing(t *testing.T) {
    34  	granted, _ := url.Parse("private://0x0/_/contracts?from.tm=A&owned.eoa=0x0")
    35  	ask, _ := url.Parse("private://0xa1b1c1/write/contracts?owned.eoa=0xe1e1e1")
    36  
    37  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
    38  
    39  	ask, _ = url.Parse("private://0xa1b1c1/write/contracts")
    40  
    41  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
    42  }
    43  
    44  func TestMatch_whenGrantNothing(t *testing.T) {
    45  	granted, _ := url.Parse("private://0xa1b1c1/write/contracts")
    46  	ask, _ := url.Parse("private://0xa1b1c1/write/contracts?from.tm=A")
    47  
    48  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
    49  }
    50  
    51  func TestMatch_whenAnyAction(t *testing.T) {
    52  	granted, _ := url.Parse("private://0xa1b1c1/_/contracts?owned.eoa=0x0&from.tm=A1")
    53  	ask, _ := url.Parse("private://0xa1b1c1/read/contracts?from.tm=A1")
    54  
    55  	assert.True(t, match(&ContractSecurityAttribute{
    56  		Visibility: VisibilityPrivate,
    57  		Action:     ActionRead,
    58  	}, ask, granted))
    59  
    60  	ask, _ = url.Parse("private://0xa1b1c1/read/contracts?owned.eoa=0x0&from.tm=A1&from.tm=B1")
    61  
    62  	assert.True(t, match(&ContractSecurityAttribute{
    63  		Visibility: VisibilityPrivate,
    64  		Action:     ActionRead,
    65  	}, ask, granted))
    66  
    67  	ask, _ = url.Parse("private://0xa1b1c1/write/contracts?owned.eoa=0x0&from.tm=A1")
    68  
    69  	assert.True(t, match(&ContractSecurityAttribute{
    70  		Visibility: VisibilityPrivate,
    71  		Action:     ActionWrite,
    72  	}, ask, granted))
    73  }
    74  
    75  func TestMatch_whenPathNotMatched(t *testing.T) {
    76  	granted, _ := url.Parse("private://0xa1b1c1/write/contracts?owned.eoa=0x0&from.tm=A1")
    77  	ask, _ := url.Parse("private://0xa1b1c1/read/contracts?from.tm=A1")
    78  
    79  	assert.False(t, match(&ContractSecurityAttribute{
    80  		Visibility: VisibilityPrivate,
    81  		Action:     ActionRead,
    82  	}, ask, granted))
    83  }
    84  
    85  func TestMatch_whenSchemeIsNotEqual(t *testing.T) {
    86  	granted, _ := url.Parse("unknown://0xa1b1c1/create/contracts?from.tm=A")
    87  	ask, _ := url.Parse("private://0xa1b1c1/create/contracts?from.tm=A")
    88  
    89  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
    90  }
    91  
    92  func TestMatch_whenContractWritePermission_GrantedIsTheSuperSet(t *testing.T) {
    93  	granted, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A&from.tm=B")
    94  	ask, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A")
    95  
    96  	assert.True(t, match(&ContractSecurityAttribute{
    97  		Visibility: VisibilityPrivate,
    98  		Action:     ActionWrite,
    99  	}, ask, granted), "with write permission")
   100  
   101  	granted, _ = url.Parse("private://0x0/read/contracts?owned.eoa=0x0&from.tm=A&from.tm=B")
   102  	ask, _ = url.Parse("private://0x0/read/contracts?owned.eoa=0x0&from.tm=A")
   103  
   104  	assert.True(t, match(&ContractSecurityAttribute{
   105  		Visibility: VisibilityPrivate,
   106  		Action:     ActionRead,
   107  	}, ask, granted), "with read permission")
   108  }
   109  
   110  func TestMatch_whenContractReadPermission_AnyAction(t *testing.T) {
   111  	granted, _ := url.Parse("private://0x1234/_/contracts?owned.eoa=0x0&from.tm=A")
   112  	ask, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x1234&from.tm=A")
   113  
   114  	assert.True(t, match(&ContractSecurityAttribute{
   115  		Visibility: VisibilityPrivate,
   116  		Action:     ActionRead,
   117  	}, ask, granted))
   118  }
   119  
   120  func TestMatch_whenContractReadPermission_AnyEoa(t *testing.T) {
   121  	granted, _ := url.Parse("private://0x1234/_/contracts?owned.eoa=0x0&from.tm=A")
   122  	ask, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x0&from.tm=A")
   123  
   124  	assert.True(t, match(&ContractSecurityAttribute{
   125  		Visibility: VisibilityPrivate,
   126  		Action:     ActionRead,
   127  	}, ask, granted))
   128  }
   129  
   130  func TestMatch_whenContractReadPermission_EoaDifferent(t *testing.T) {
   131  	granted, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x095e7baea6a6c7c4c2dfeb977efac326af552d87&from.tm=A")
   132  	ask, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x945304eb96065b2a98b57a48a06ae28d285a71b5&from.tm=A")
   133  
   134  	assert.False(t, match(&ContractSecurityAttribute{
   135  		Visibility: VisibilityPrivate,
   136  		Action:     ActionRead,
   137  	}, ask, granted))
   138  }
   139  
   140  func TestMatch_whenContractReadPermission_EoaSame(t *testing.T) {
   141  	granted, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x095e7baea6a6c7c4c2dfeb977efac326af552d87&from.tm=A")
   142  	ask, _ := url.Parse("private://0x0/read/contracts?owned.eoa=0x095e7baea6a6c7c4c2dfeb977efac326af552d87&from.tm=A")
   143  
   144  	assert.True(t, match(&ContractSecurityAttribute{
   145  		Visibility: VisibilityPrivate,
   146  		Action:     ActionRead,
   147  	}, ask, granted))
   148  }
   149  
   150  func TestMatch_whenContractReadPermission_TmKeysIntersect(t *testing.T) {
   151  	granted, _ := url.Parse("private://0x0/read/contracts?from.tm=A&from.tm=B")
   152  	ask, _ := url.Parse("private://0x0/read/contracts?from.tm=B&from.tm=C")
   153  
   154  	assert.True(t, match(&ContractSecurityAttribute{
   155  		Visibility: VisibilityPrivate,
   156  		Action:     ActionRead,
   157  	}, ask, granted))
   158  }
   159  
   160  func TestMatch_whenContractReadPermission_TmKeysDontIntersect(t *testing.T) {
   161  	granted, _ := url.Parse("private://0x0/read/contracts?from.tm=A&from.tm=B")
   162  	ask, _ := url.Parse("private://0x0/read/contracts?from.tm=C&from.tm=D")
   163  
   164  	assert.False(t, match(&ContractSecurityAttribute{
   165  		Visibility: VisibilityPrivate,
   166  		Action:     ActionRead,
   167  	}, ask, granted))
   168  }
   169  
   170  func TestMatch_whenContractWritePermission_Same(t *testing.T) {
   171  	granted, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A")
   172  	ask, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A")
   173  
   174  	assert.True(t, match(&ContractSecurityAttribute{
   175  		Visibility: VisibilityPrivate,
   176  		Action:     ActionWrite,
   177  	}, ask, granted))
   178  }
   179  
   180  func TestMatch_whenContractWritePermission_Different(t *testing.T) {
   181  	granted, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A")
   182  	ask, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=B")
   183  
   184  	assert.False(t, match(&ContractSecurityAttribute{
   185  		Visibility: VisibilityPrivate,
   186  		Action:     ActionWrite,
   187  	}, ask, granted))
   188  }
   189  
   190  func TestMatch_whenContractWritePermission_AskIsSuperSet(t *testing.T) {
   191  	granted, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=A")
   192  	ask, _ := url.Parse("private://0x0/write/contracts?owned.eoa=0x0&from.tm=B&from.tm=C&from.tm=A")
   193  
   194  	assert.True(t, match(&ContractSecurityAttribute{
   195  		Visibility: VisibilityPrivate,
   196  		Action:     ActionWrite,
   197  	}, ask, granted))
   198  }
   199  
   200  func TestMatch_whenContractCreatePermission_Same(t *testing.T) {
   201  	granted, _ := url.Parse("private://0x0/create/contracts?owned.eoa=0x0&from.tm=A")
   202  	ask, _ := url.Parse("private://0x0/create/contracts?owned.eoa=0x0&from.tm=A")
   203  
   204  	assert.True(t, match(&ContractSecurityAttribute{
   205  		Visibility: VisibilityPrivate,
   206  		Action:     ActionCreate,
   207  	}, ask, granted))
   208  }
   209  
   210  func TestMatch_whenContractCreatePermission_Different(t *testing.T) {
   211  	granted, _ := url.Parse("private://0x0/create/contracts?owned.eoa=0x0&from.tm=A")
   212  	ask, _ := url.Parse("private://0x0/create/contracts?owned.eoa=0x0&from.tm=B")
   213  
   214  	assert.False(t, match(&ContractSecurityAttribute{
   215  		Visibility: VisibilityPrivate,
   216  		Action:     ActionCreate,
   217  	}, ask, granted))
   218  }
   219  
   220  func TestMatch_whenUsingWildcardAccount(t *testing.T) {
   221  	granted, _ := url.Parse("private://0x0/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   222  	ask, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   223  
   224  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
   225  
   226  	granted, _ = url.Parse("private://0x0/read/contract?owned.eoa=0x0&from.tm=A")
   227  	ask, _ = url.Parse("private://0xa1b1c1/read/contract?owned.eoa=0x1234&from.tm=A")
   228  
   229  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionRead}, ask, granted))
   230  }
   231  
   232  func TestMatch_whenNotUsingWildcardAccount(t *testing.T) {
   233  	granted, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   234  	ask, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   235  
   236  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
   237  
   238  	granted, _ = url.Parse("private://0x0/read/contract?owned.eoa=0x0&from.tm=A")
   239  	ask, _ = url.Parse("private://0xa1b1c1/read/contract?owned.eoa=0x1234&from.tm=A")
   240  
   241  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionRead}, ask, granted))
   242  }
   243  
   244  func TestMatch_failsWhenAccountsDiffer(t *testing.T) {
   245  	granted, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   246  	ask, _ := url.Parse("private://0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b/create/contracts?from.tm=dLHrFQpbSda0EhJnLonsBwDjks%2Bf724NipfI5zK5RSs%3D")
   247  
   248  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
   249  }
   250  
   251  func TestMatch_whenPublic(t *testing.T) {
   252  	granted, _ := url.Parse("private://0xa1b1c1/create/contract?from.tm=A/")
   253  	ask, _ := url.Parse("public://0x0/create/contract")
   254  
   255  	assert.True(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
   256  }
   257  
   258  func TestMatch_whenNotEscaped(t *testing.T) {
   259  	// query not escaped probably in the granted authority resource identitifer
   260  	granted, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=")
   261  	ask, _ := url.Parse("private://0xed9d02e382b34818e88b88a309c7fe71e65f419d/create/contracts?from.tm=BULeR8JyUWhiuuCMU%2FHLA0Q5pzkYT%2BcHII3ZKBey3Bo%3D")
   262  
   263  	assert.False(t, match(&ContractSecurityAttribute{Action: ActionCreate}, ask, granted))
   264  }
   265  
   266  func runTestCases(t *testing.T, testCases []*testCase) {
   267  	testObject := &DefaultContractAuthorizationProvider{}
   268  	for _, tc := range testCases {
   269  		log.Debug("--> Running test case: " + tc.msg)
   270  		authorities := make([]*proto.GrantedAuthority, 0)
   271  		for _, a := range tc.granted {
   272  			authorities = append(authorities, &proto.GrantedAuthority{Raw: a})
   273  		}
   274  		b, err := testObject.IsAuthorized(
   275  			context.Background(),
   276  			&proto.PreAuthenticatedAuthenticationToken{Authorities: authorities},
   277  			tc.ask...)
   278  		if !assert.NoError(t, err, tc.msg) {
   279  			return
   280  		}
   281  		if !assert.Equal(t, tc.isAuthorized, b, tc.msg) {
   282  			return
   283  		}
   284  	}
   285  }
   286  
   287  func TestDefaultAccountAccessDecisionManager_IsAuthorized_forPublicContracts(t *testing.T) {
   288  	runTestCases(t, []*testCase{
   289  		canCreatePublicContracts,
   290  		// canNotCreatePublicContracts,
   291  		canReadOwnedPublicContracts,
   292  		canReadOtherPublicContracts,
   293  		// canNotReadOtherPublicContracts,
   294  		canWriteOwnedPublicContracts,
   295  		canWriteOtherPublicContracts1,
   296  		canWriteOtherPublicContracts2,
   297  		// canNotWriteOtherPublicContracts,
   298  		canCreatePublicContractsAndWriteToOthers,
   299  	})
   300  }
   301  
   302  func TestDefaultAccountAccessDecisionManager_IsAuthorized_forPrivateContracts(t *testing.T) {
   303  	runTestCases(t, []*testCase{
   304  		canCreatePrivateContracts,
   305  		canNotCreatePrivateContracts,
   306  		canReadOwnedPrivateContracts,
   307  		canReadOtherPrivateContracts,
   308  		canNotReadOtherPrivateContracts,
   309  		canNotReadOtherPrivateContractsNoPrivy,
   310  		canWriteOwnedPrivateContracts,
   311  		canWriteOtherPrivateContracts,
   312  		canWriteOtherPrivateContractsWithOverlappedScope,
   313  		canNotWriteOtherPrivateContracts,
   314  		canNotWriteOtherPrivateContractsNoPrivy,
   315  	})
   316  }
   317  
   318  func TestDefaultAccountAccessDecisionManager_IsAuthorized_forPrivateContracts_wildcards_whenCreate(t *testing.T) {
   319  	fullAccessToX := []string{
   320  		"private://0x0/_/contracts?owned.eoa=0x0&from.tm=X",
   321  	}
   322  	runTestCases(t, []*testCase{
   323  		{
   324  			msg:          "X has full access to a private contract when create",
   325  			isAuthorized: true,
   326  			granted:      fullAccessToX,
   327  			ask: []*ContractSecurityAttribute{
   328  				// create
   329  				{
   330  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   331  						From: common.HexToAddress("0xa1a1a1"),
   332  					},
   333  					Visibility:  VisibilityPrivate,
   334  					Action:      ActionCreate,
   335  					PrivateFrom: "X",
   336  					Parties:     []string{},
   337  				},
   338  			},
   339  		},
   340  		{
   341  			msg:          "X can't creat private contract with other TM key",
   342  			isAuthorized: false,
   343  			granted:      fullAccessToX,
   344  			ask: []*ContractSecurityAttribute{
   345  				// create
   346  				{
   347  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   348  						From: common.HexToAddress("0xa1a1a1"),
   349  					},
   350  					Visibility:  VisibilityPrivate,
   351  					Action:      ActionCreate,
   352  					PrivateFrom: "A",
   353  					Parties:     []string{},
   354  				},
   355  			},
   356  		},
   357  	})
   358  }
   359  
   360  func TestDefaultAccountAccessDecisionManager_IsAuthorized_forPrivateContracts_wildcards_whenRead(t *testing.T) {
   361  	fullAccessToX := []string{
   362  		"private://0x0/_/contracts?owned.eoa=0x0&from.tm=X",
   363  	}
   364  	runTestCases(t, []*testCase{
   365  		{
   366  			msg:          "X has full access to a private contract when read as one of the participants",
   367  			isAuthorized: true,
   368  			granted:      fullAccessToX,
   369  			ask: []*ContractSecurityAttribute{
   370  				{
   371  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   372  					Visibility:                    VisibilityPrivate,
   373  					Action:                        ActionRead,
   374  					PrivateFrom:                   "X",
   375  					Parties:                       []string{"X", "Y"},
   376  				},
   377  			},
   378  		},
   379  		{
   380  			msg:          "X has full access to a private contract when read as a single participant",
   381  			isAuthorized: true,
   382  			granted:      fullAccessToX,
   383  			ask: []*ContractSecurityAttribute{
   384  				{
   385  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   386  					Visibility:                    VisibilityPrivate,
   387  					Action:                        ActionRead,
   388  					PrivateFrom:                   "X",
   389  					Parties:                       []string{"X"},
   390  				},
   391  			},
   392  		},
   393  		{
   394  			msg:          "X can't read other private contracts",
   395  			isAuthorized: false,
   396  			granted:      fullAccessToX,
   397  			ask: []*ContractSecurityAttribute{
   398  				{
   399  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   400  					Visibility:                    VisibilityPrivate,
   401  					Action:                        ActionRead,
   402  					PrivateFrom:                   "X",
   403  					Parties:                       []string{"A", "B"},
   404  				},
   405  			},
   406  		},
   407  		{
   408  			msg:          "X can't read other private contracts by faking the read",
   409  			isAuthorized: false,
   410  			granted:      fullAccessToX,
   411  			ask: []*ContractSecurityAttribute{
   412  				{
   413  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   414  					Visibility:                    VisibilityPrivate,
   415  					Action:                        ActionRead,
   416  					PrivateFrom:                   "A",
   417  					Parties:                       []string{"A", "B"},
   418  				},
   419  			},
   420  		},
   421  		{
   422  			msg:          "X can't read other private contracts when proxy-read",
   423  			isAuthorized: false,
   424  			granted:      fullAccessToX,
   425  			ask: []*ContractSecurityAttribute{
   426  				// read its own contract
   427  				{
   428  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   429  					Visibility:                    VisibilityPrivate,
   430  					Action:                        ActionRead,
   431  					PrivateFrom:                   "X",
   432  					Parties:                       []string{"X"},
   433  				},
   434  				// but using it as proxy to read other contract
   435  				{
   436  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{},
   437  					Visibility:                    VisibilityPrivate,
   438  					Action:                        ActionRead,
   439  					PrivateFrom:                   "X",
   440  					Parties:                       []string{"A", "B"},
   441  				},
   442  			},
   443  		},
   444  	})
   445  }
   446  
   447  func TestDefaultAccountAccessDecisionManager_IsAuthorized_forPrivateContracts_wildcards_whenWrite(t *testing.T) {
   448  	fullAccessToX := []string{
   449  		"private://0x0/_/contracts?owned.eoa=0x0&from.tm=X",
   450  	}
   451  	runTestCases(t, []*testCase{
   452  		{
   453  			msg:          "X has full access to a private contract when write as a single participant",
   454  			isAuthorized: true,
   455  			granted:      fullAccessToX,
   456  			ask: []*ContractSecurityAttribute{
   457  				{
   458  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   459  						From: common.HexToAddress("0xa1a1a1"),
   460  					},
   461  					Visibility:  VisibilityPrivate,
   462  					Action:      ActionWrite,
   463  					PrivateFrom: "X",
   464  					Parties:     []string{"X"},
   465  				},
   466  			},
   467  		},
   468  		{
   469  			msg:          "X has full access to a private contract when write as one of the participants",
   470  			isAuthorized: true,
   471  			granted:      fullAccessToX,
   472  			ask: []*ContractSecurityAttribute{
   473  				{
   474  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   475  						From: common.HexToAddress("0xa1a1a1"),
   476  					},
   477  					Visibility:  VisibilityPrivate,
   478  					Action:      ActionWrite,
   479  					PrivateFrom: "X",
   480  					Parties:     []string{"X", "Y"},
   481  				},
   482  			},
   483  		},
   484  		{
   485  			msg:          "X must not access other private contracts when faking write",
   486  			isAuthorized: false,
   487  			granted:      fullAccessToX,
   488  			ask: []*ContractSecurityAttribute{
   489  				{
   490  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   491  						From: common.HexToAddress("0xa1a1a1"),
   492  						To:   common.HexToAddress("0xb1b1b1"), // creator EOA address
   493  					},
   494  					Visibility:  VisibilityPrivate,
   495  					Action:      ActionWrite,
   496  					PrivateFrom: "A",
   497  					Parties:     []string{"A", "B"},
   498  				},
   499  			},
   500  		},
   501  		{
   502  			msg:          "X can not write to a private contract not privy to X",
   503  			isAuthorized: false,
   504  			granted:      fullAccessToX,
   505  			ask: []*ContractSecurityAttribute{
   506  				{
   507  					AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   508  						From: common.HexToAddress("0xa1a1a1"),
   509  						To:   common.HexToAddress("0xb1b1b1"), // creator EOA address
   510  					},
   511  					Visibility:  VisibilityPrivate,
   512  					Action:      ActionWrite,
   513  					PrivateFrom: "X",
   514  					Parties:     []string{"A", "B"},
   515  				},
   516  			},
   517  		},
   518  	})
   519  }
   520  
   521  var (
   522  	canCreatePublicContracts = &testCase{
   523  		msg: "0x0a1a1a1 can create public contracts",
   524  		granted: []string{
   525  			"public://0x0000000000000000000000000000000000a1a1a1/create/contracts",
   526  		},
   527  		ask: []*ContractSecurityAttribute{
   528  			{
   529  				AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   530  					From: common.HexToAddress("0xa1a1a1"),
   531  				},
   532  				Visibility: VisibilityPublic,
   533  				Action:     ActionCreate,
   534  			},
   535  		},
   536  		isAuthorized: true,
   537  	}
   538  	canCreatePublicContractsAndWriteToOthers = &testCase{
   539  		msg: "0x0a1a1a1 can create public contracts and write to contracts created by 0xb1b1b1",
   540  		granted: []string{
   541  			"public://0x0000000000000000000000000000000000a1a1a1/create/contracts",
   542  			"public://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&owned.eoa=0x0000000000000000000000000000000000c1c1c1",
   543  		},
   544  		ask: []*ContractSecurityAttribute{
   545  			{
   546  				AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   547  					From: common.HexToAddress("0xa1a1a1"),
   548  				},
   549  				Visibility: VisibilityPublic,
   550  				Action:     ActionCreate,
   551  			}, {
   552  				AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   553  					From: common.HexToAddress("0xa1a1a1"),
   554  					To:   common.HexToAddress("0xb1b1b1"),
   555  				},
   556  				Visibility: VisibilityPublic,
   557  				Action:     ActionWrite,
   558  			},
   559  		},
   560  		isAuthorized: true,
   561  	}
   562  	//
   563  	//canNotCreatePublicContracts = &testCase{
   564  	//	msg: "0xb1b1b1 can not create public contracts",
   565  	//	granted: []string{
   566  	//		"public://0x0000000000000000000000000000000000a1a1a1/create/contracts",
   567  	//		"public://0x0000000000000000000000000000000000b1b1b1/read/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   568  	//	},
   569  	//	ask: []*ContractSecurityAttribute{{
   570  	//		AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   571  	//			From: common.HexToAddress("0xb1b1b1"),
   572  	//		},
   573  	//		Visibility: VisibilityPublic,
   574  	//		Action:     ActionCreate,
   575  	//	}},
   576  	//	isAuthorized: false,
   577  	//}
   578  	canReadOwnedPublicContracts = &testCase{
   579  		msg: "0x0a1a1a1 can read public contracts created by self",
   580  		granted: []string{
   581  			"public://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   582  		},
   583  		ask: []*ContractSecurityAttribute{{
   584  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   585  				From: common.HexToAddress("0xa1a1a1"),
   586  			},
   587  			Visibility: VisibilityPublic,
   588  			Action:     ActionRead,
   589  		}},
   590  		isAuthorized: true,
   591  	}
   592  	canReadOtherPublicContracts = &testCase{
   593  		msg: "0x0a1a1a1 can read public contracts created by 0xb1b1b1",
   594  		granted: []string{
   595  			"public://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1",
   596  		},
   597  		ask: []*ContractSecurityAttribute{{
   598  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   599  				From: common.HexToAddress("0xa1a1a1"),
   600  				To:   common.HexToAddress("0xb1b1b1"),
   601  			},
   602  			Visibility: VisibilityPublic,
   603  			Action:     ActionRead,
   604  		}},
   605  		isAuthorized: true,
   606  	}
   607  	//canNotReadOtherPublicContracts = &testCase{
   608  	//	msg: "0x0a1a1a1 can only read public contracts created by self",
   609  	//	granted: []string{
   610  	//		"public://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   611  	//	},
   612  	//	ask: []*ContractSecurityAttribute{{
   613  	//		AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   614  	//			From: common.HexToAddress("0xa1a1a1"),
   615  	//			To:   common.HexToAddress("0xb1b1b1"),
   616  	//		},
   617  	//		Visibility: VisibilityPublic,
   618  	//		Action:     ActionRead,
   619  	//	}},
   620  	//	isAuthorized: false,
   621  	//}
   622  	canWriteOwnedPublicContracts = &testCase{
   623  		msg: "0x0a1a1a1 can send transactions to public contracts created by self",
   624  		granted: []string{
   625  			"public://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   626  		},
   627  		ask: []*ContractSecurityAttribute{{
   628  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   629  				From: common.HexToAddress("0xa1a1a1"),
   630  			},
   631  			Visibility: VisibilityPublic,
   632  			Action:     ActionWrite,
   633  		}},
   634  		isAuthorized: true,
   635  	}
   636  	canWriteOtherPublicContracts1 = &testCase{
   637  		msg: "0xa1a1a1 can send transactions to public contracts created by 0xb1b1b1",
   638  		granted: []string{
   639  			"public://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&owned.eoa=0x0000000000000000000000000000000000c1c1c1",
   640  		},
   641  		ask: []*ContractSecurityAttribute{{
   642  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   643  				From: common.HexToAddress("0xa1a1a1"),
   644  				To:   common.HexToAddress("0xb1b1b1"),
   645  			},
   646  			Visibility: VisibilityPublic,
   647  			Action:     ActionWrite,
   648  		}},
   649  		isAuthorized: true,
   650  	}
   651  	canWriteOtherPublicContracts2 = &testCase{
   652  		msg: "0xa1a1a1 can send transactions to public contracts created by 0xb1b1b1",
   653  		granted: []string{
   654  			"public://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&owned.eoa=0x0000000000000000000000000000000000c1c1c1",
   655  		},
   656  		ask: []*ContractSecurityAttribute{{
   657  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   658  				From: common.HexToAddress("0xa1a1a1"),
   659  				To:   common.HexToAddress("0xc1c1c1"),
   660  			},
   661  			Visibility: VisibilityPublic,
   662  			Action:     ActionWrite,
   663  		}},
   664  		isAuthorized: true,
   665  	}
   666  	//canNotWriteOtherPublicContracts = &testCase{
   667  	//	msg: "0x0a1a1a1 can only send transactions to public contracts created by self",
   668  	//	granted: []string{
   669  	//		"public://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   670  	//		"public://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1",
   671  	//	},
   672  	//	ask: []*ContractSecurityAttribute{{
   673  	//		AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   674  	//			From: common.HexToAddress("0xa1a1a1"),
   675  	//			To:   common.HexToAddress("0xb1b1b1"),
   676  	//		},
   677  	//		Visibility: VisibilityPublic,
   678  	//		Action:     ActionWrite,
   679  	//	}},
   680  	//	isAuthorized: false,
   681  	//}
   682  	// private contracts
   683  	canCreatePrivateContracts = &testCase{
   684  		msg: "0x0a1a1a1 can create private contracts with sender key A",
   685  		granted: []string{
   686  			"private://0x0000000000000000000000000000000000a1a1a1/create/contracts?from.tm=A",
   687  		},
   688  		ask: []*ContractSecurityAttribute{{
   689  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   690  				From: common.HexToAddress("0xa1a1a1"),
   691  			},
   692  			Visibility:  VisibilityPrivate,
   693  			Action:      ActionCreate,
   694  			PrivateFrom: "A",
   695  			Parties:     []string{},
   696  		}},
   697  		isAuthorized: true,
   698  	}
   699  	canNotCreatePrivateContracts = &testCase{
   700  		msg: "0x0a1a1a1 can NOT create private contracts with sender key A if only own key B",
   701  		granted: []string{
   702  			"private://0x0000000000000000000000000000000000a1a1a1/create/contracts?from.tm=B",
   703  		},
   704  		ask: []*ContractSecurityAttribute{{
   705  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   706  				From: common.HexToAddress("0xa1a1a1"),
   707  			},
   708  			Visibility:  VisibilityPrivate,
   709  			Action:      ActionCreate,
   710  			PrivateFrom: "A",
   711  			Parties:     []string{},
   712  		}},
   713  		isAuthorized: false,
   714  	}
   715  	canReadOwnedPrivateContracts = &testCase{
   716  		msg: "0x0a1a1a1 can read private contracts created by self and was privy to a key A",
   717  		granted: []string{
   718  			"private://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1&from.tm=A&from.tm=B",
   719  		},
   720  		ask: []*ContractSecurityAttribute{{
   721  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   722  				From: common.HexToAddress("0xa1a1a1"),
   723  			},
   724  			Visibility: VisibilityPrivate,
   725  			Action:     ActionRead,
   726  			Parties:    []string{"A"},
   727  		}},
   728  		isAuthorized: true,
   729  	}
   730  	canReadOtherPrivateContracts = &testCase{
   731  		msg: "0x0a1a1a1 can read private contracts created by 0xb1b1b1 and was privy to a key A",
   732  		granted: []string{
   733  			"private://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=A",
   734  		},
   735  		ask: []*ContractSecurityAttribute{{
   736  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   737  				From: common.HexToAddress("0xa1a1a1"),
   738  				To:   common.HexToAddress("0xb1b1b1"),
   739  			},
   740  			Visibility: VisibilityPrivate,
   741  			Action:     ActionRead,
   742  			Parties:    []string{"A"},
   743  		}},
   744  		isAuthorized: true,
   745  	}
   746  	canNotReadOtherPrivateContracts = &testCase{
   747  		msg: "0x0a1a1a1 can NOT read private contracts created by 0xb1b1b1 even it was privy to a key A",
   748  		granted: []string{
   749  			"private://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000c1c1c1&from.tm=A",
   750  		},
   751  		ask: []*ContractSecurityAttribute{{
   752  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   753  				From: common.HexToAddress("0xa1a1a1"),
   754  				To:   common.HexToAddress("0xb1b1b1"),
   755  			},
   756  			Visibility: VisibilityPrivate,
   757  			Action:     ActionRead,
   758  			Parties:    []string{"A"},
   759  		}},
   760  		isAuthorized: false,
   761  	}
   762  	canNotReadOtherPrivateContractsNoPrivy = &testCase{
   763  		msg: "0x0a1a1a1 can NOT read private contracts created by 0xb1b1b1 as it was privy to a key B",
   764  		granted: []string{
   765  			"private://0x0000000000000000000000000000000000a1a1a1/read/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=B",
   766  		},
   767  		ask: []*ContractSecurityAttribute{{
   768  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   769  				From: common.HexToAddress("0xa1a1a1"),
   770  				To:   common.HexToAddress("0xb1b1b1"),
   771  			},
   772  			Visibility: VisibilityPrivate,
   773  			Action:     ActionRead,
   774  			Parties:    []string{"A"},
   775  		}},
   776  		isAuthorized: false,
   777  	}
   778  	canWriteOwnedPrivateContracts = &testCase{
   779  		msg: "0x0a1a1a1 can write private contracts created by self and was privy to a key A",
   780  		granted: []string{
   781  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000a1a1a1&from.tm=A&from.tm=B",
   782  		},
   783  		ask: []*ContractSecurityAttribute{{
   784  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   785  				From: common.HexToAddress("0xa1a1a1"),
   786  			},
   787  			Visibility:  VisibilityPrivate,
   788  			Action:      ActionWrite,
   789  			PrivateFrom: "A",
   790  			Parties:     []string{"A"},
   791  		}},
   792  		isAuthorized: true,
   793  	}
   794  	canWriteOtherPrivateContracts = &testCase{
   795  		msg: "0x0a1a1a1 can write private contracts created by 0xb1b1b1 and was privy to a key A",
   796  		granted: []string{
   797  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=A",
   798  		},
   799  		ask: []*ContractSecurityAttribute{{
   800  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   801  				From: common.HexToAddress("0xa1a1a1"),
   802  				To:   common.HexToAddress("0xb1b1b1"),
   803  			},
   804  			Visibility:  VisibilityPrivate,
   805  			Action:      ActionWrite,
   806  			PrivateFrom: "A",
   807  			Parties:     []string{"A"},
   808  		}},
   809  		isAuthorized: true,
   810  	}
   811  	canWriteOtherPrivateContractsWithOverlappedScope = &testCase{
   812  		msg: "0x0a1a1a1 can write private contracts created by 0xb1b1b1 and was privy to a key A",
   813  		granted: []string{
   814  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=A",
   815  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=A&from.tm=B",
   816  		},
   817  		ask: []*ContractSecurityAttribute{{
   818  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   819  				From: common.HexToAddress("0xa1a1a1"),
   820  				To:   common.HexToAddress("0xb1b1b1"),
   821  			},
   822  			Visibility:  VisibilityPrivate,
   823  			Action:      ActionWrite,
   824  			PrivateFrom: "A",
   825  			Parties:     []string{"A"},
   826  		}},
   827  		isAuthorized: true,
   828  	}
   829  	canNotWriteOtherPrivateContracts = &testCase{
   830  		msg: "0x0a1a1a1 can NOT write private contracts created by 0xb1b1b1 even it was privy to a key A",
   831  		granted: []string{
   832  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000c1c1c1&from.tm=A",
   833  		},
   834  		ask: []*ContractSecurityAttribute{{
   835  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   836  				From: common.HexToAddress("0xa1a1a1"),
   837  				To:   common.HexToAddress("0xb1b1b1"),
   838  			},
   839  			Visibility: VisibilityPrivate,
   840  			Action:     ActionWrite,
   841  			Parties:    []string{"A"},
   842  		}},
   843  		isAuthorized: false,
   844  	}
   845  	canNotWriteOtherPrivateContractsNoPrivy = &testCase{
   846  		msg: "0x0a1a1a1 can NOT write private contracts created by 0xb1b1b1 as it was privy to a key B",
   847  		granted: []string{
   848  			"private://0x0000000000000000000000000000000000a1a1a1/write/contracts?owned.eoa=0x0000000000000000000000000000000000b1b1b1&from.tm=B",
   849  		},
   850  		ask: []*ContractSecurityAttribute{{
   851  			AccountStateSecurityAttribute: &AccountStateSecurityAttribute{
   852  				From: common.HexToAddress("0xa1a1a1"),
   853  				To:   common.HexToAddress("0xb1b1b1"),
   854  			},
   855  			Visibility: VisibilityPrivate,
   856  			Action:     ActionWrite,
   857  			Parties:    []string{"A"},
   858  		}},
   859  		isAuthorized: false,
   860  	}
   861  )