diff --git a/cmd/dcld/cmd/genaccounts.go b/cmd/dcld/cmd/genaccounts.go index 5ff895c52..c074c2e36 100644 --- a/cmd/dcld/cmd/genaccounts.go +++ b/cmd/dcld/cmd/genaccounts.go @@ -19,6 +19,7 @@ import ( "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclgenutil" dclgenutiltypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclgenutil/types" @@ -29,6 +30,7 @@ const ( FlagPubKey = "pubkey" FlagRoles = "roles" FlagVID = "vid" + FlagPIDs = "pid_ranges" ) // AddGenesisAccountCmd returns add-genesis-account cobra Command. @@ -109,8 +111,36 @@ the address will be looked up in the local Keybase. } } + var pidRanges []*types.Uint16Range + if pidStrRanges := viper.GetString(FlagPIDs); len(pidStrRanges) > 0 { //nolint:nestif + var lastMax int32 + for _, pidStrRange := range strings.Split(pidStrRanges, ",") { + pidRange := strings.Split(pidStrRange, "-") + if len(pidRange) != 2 { + return fmt.Errorf("failed to parse PID Range") + } + min, err := cast.ToInt32E(pidRange[0]) + if err != nil { + return err + } + max, err := cast.ToInt32E(pidRange[1]) + if err != nil { + return err + } + if min > max || max == 0 || min == 0 { + return fmt.Errorf("invalid PID Range is provided: min=%d, max=%d", min, max) + } + if max <= lastMax || min <= lastMax { + return fmt.Errorf("invalid PID Range is provided: {%d-%d}, ranges are overlapped, range items must be provided in increased order", min, max) + } + pid := types.Uint16Range{Min: min, Max: max} + pidRanges = append(pidRanges, &pid) + lastMax = max + } + } + // FIXME issue 99 VendorID - genAccount = dclauthtypes.NewAccount(ba, roles, []*dclauthtypes.Grant{}, []*dclauthtypes.Grant{}, vendorID) + genAccount = dclauthtypes.NewAccount(ba, roles, []*dclauthtypes.Grant{}, []*dclauthtypes.Grant{}, vendorID, pidRanges) if err := genAccount.Validate(); err != nil { return fmt.Errorf("failed to validate new genesis account: %w", err) @@ -154,6 +184,7 @@ the address will be looked up in the local Keybase. cmd.Flags().String(FlagRoles, "", fmt.Sprintf("The list of roles (split by comma) to assign to account (supported roles: %v)", dclauthtypes.Roles)) cmd.Flags().String(FlagVID, "", "Vendor ID associated with this account. Required only for Vendor Roles") + cmd.Flags().String(FlagPIDs, "", "The list of Product ID ranges (split by \"-\") associated with this account (for example: 1-101,101-6554)") cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") diff --git a/docs/how-to.md b/docs/how-to.md index 74e54a5c0..dc32f0e85 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -127,7 +127,7 @@ Once approved the account can be used to send transactions. See [use_case_txn_au ### 1. Create an Account proposal for the user ```bash -dcld tx auth propose-add-account --address= --pubkey= --roles= --vid= --from= +dcld tx auth propose-add-account --address= --pubkey= --roles= --vid= --pid_ranges= --from= ``` ### 2. Approve proposed Account @@ -211,6 +211,7 @@ Minimal command: ```bash dcld tx model add-model --vid= --pid= --deviceTypeID= --productName= --from= ``` +Note that if `account` was created with product ID ranges then the `pid` must fall within that specified range Full command: @@ -229,6 +230,7 @@ Minimal command: dcld tx model add-model-version --vid= --pid= --softwareVersion= --softwareVersionString= --cdVersionNumber= --minApplicableSoftwareVersion= --maxApplicableSoftwareVersion= --from= ``` +Note that if `account` was created with product ID ranges then the `pid` must fall within that specified range Full command: @@ -250,12 +252,14 @@ dcld tx vendorinfo update-vendor --vid= ... --from= ```bash dcld tx model update-model --vid= --pid= ... --from= ``` +Note that if `account` was created with product ID ranges then the `pid` must fall within that specified range ### 7. Edit Model Version ```bash dcld tx model update-model-version --vid= --pid= --softwareVersion= ... --from= ``` +Note that if `account` was created with product ID ranges then the `pid` must fall within that specified range ### 8. Add PKI Revocation Distribution Point diff --git a/docs/transactions.md b/docs/transactions.md index 077487040..b9a8e7ca8 100644 --- a/docs/transactions.md +++ b/docs/transactions.md @@ -188,7 +188,7 @@ Should be sent to trusted nodes only. **Status: Implemented** -Adds a new Model identified by a unique combination of `vid` (vendor ID) and `pid` (product ID). +Adds a new Model identified by a unique combination of `vid` (vendor ID) and `pid` (product ID). If `account` was created with product ID ranges then the `pid` must fall within that specified range. Not all fields can be edited (see `EDIT_MODEL`). @@ -234,7 +234,7 @@ dcld tx model add-model --vid= --pid= --deviceTypeID= -- **Status: Implemented** Edits an existing Model identified by a unique combination of `vid` (vendor ID) and `pid` (product ID) -by the vendor account. +by the vendor account. If `account` was created with product ID ranges then the `pid` must fall within that specified range. Only the fields listed below (except `vid` and `pid`) can be edited. If other fields need to be edited - a new model info with a new `vid` or `pid` can be created. @@ -266,7 +266,7 @@ All non-edited fields remain the same. **Status: Implemented** Deletes an existing Model identified by a unique combination of `vid` (vendor ID) and `pid` (product ID) -by the vendor account. +by the vendor account. If `account` was created with product ID ranges then the `pid` must fall within that specified range. If one of Model Versions associated with the Model is certified then Model can not be deleted. When Model is deleted, all associated Model Versions will be deleted as well. @@ -284,6 +284,7 @@ If one of Model Versions associated with the Model is certified then Model can n **Status: Implemented** Adds a new Model Software Version identified by a unique combination of `vid` (vendor ID), `pid` (product ID) and `softwareVersion`. +If `account` was created with product ID ranges then the `pid` must fall within that specified range Not all Model Software Version fields can be edited (see `EDIT_MODEL_VERSION`). @@ -330,7 +331,7 @@ dcld tx model add-model-version --vid= --pid= --softwareVersion= **Status: Implemented** Edits an existing Model Software Version identified by a unique combination of `vid` (vendor ID) `pid` (product ID) and `softwareVersion` -by the vendor. +by the vendor. If `account` was created with product ID ranges then the `pid` must fall within that specified range. Only the fields listed below (except `vid` `pid` and `softwareVersion`) can be edited. @@ -362,7 +363,7 @@ All non-edited fields remain the same. **Status: Implemented** Deletes an existing Model Version identified by a unique combination of `vid` (vendor ID), `pid` (product ID) and `softwareVersion` -by the vendor account. +by the vendor account. If `account` was created with product ID ranges then the `pid` must fall within that specified range. Model Version can be deleted only before it is certified. @@ -1383,6 +1384,7 @@ will be in a pending state until sufficient number of approvals is received. - address: `string` - account address; Bech32 encoded - pub_key: `string` - account's Protobuf JSON encoded public key - vid: `optional(uint16)` - vendor ID (only needed for vendor role) + - pid_ranges: `optional(array)` - the list of product-id ranges (range item separated with "-"), comma-separated, in increasing order, associated with this account: `1-100,201-300...` - roles: `array` - the list of roles, comma-separated, assigning to the account. Supported roles: `Vendor`, `TestHouse`, `CertificationCenter`, `Trustee`, `NodeAdmin`, `VendorAdmin`. - info: `optional(string)` - information/notes for the proposal - time: `optional(int64)` - proposal time (number of nanoseconds elapsed since January 1, 1970 UTC). CLI uses the current time for that field. @@ -1390,7 +1392,7 @@ will be in a pending state until sufficient number of approvals is received. - Who can send: - Trustee - CLI command: - - `dcld tx auth propose-add-account --address= --pubkey= --roles= --vid= --from=` + - `dcld tx auth propose-add-account --address= --pubkey= --roles= --vid= --pid_ranges= --from=` ### APPROVE_ADD_ACCOUNT diff --git a/integration_tests/cli/auth-demo.sh b/integration_tests/cli/auth-demo.sh index 0f4f9ecb4..895d8b03c 100755 --- a/integration_tests/cli/auth-demo.sh +++ b/integration_tests/cli/auth-demo.sh @@ -761,6 +761,106 @@ check_response "$result" "\[\]" test_divider +# Check creating Vendor Account with valid pid ranges: success-case +pid_ranges="1-100,101-200" + +test_divider +echo "Check creating Vendor Account with valid pid ranges: success-case" +random_string user +echo "$user generates keys" +cmd="(echo $passphrase; echo $passphrase) | dcld keys add $user" +result="$(bash -c "$cmd")" + +test_divider + +echo "Get key info for $user" +result=$(echo $passphrase | dcld keys show $user) +check_response "$result" "\"name\": \"$user\"" + +test_divider + +user_address=$(echo $passphrase | dcld keys show $user -a) +user_pubkey=$(echo $passphrase | dcld keys show $user -p) + +test_divider + +echo "Jack proposes account for $user" +result=$(echo $passphrase | dcld tx auth propose-add-account --info="Jack is proposing this account" --address="$user_address" --pubkey="$user_pubkey" --roles="Vendor" --vid=$vid --pid_ranges=$pid_ranges --from jack --yes) +check_response "$result" "\"code\": 0" + +test_divider + +echo "Get all active accounts. $user account in the list because has enough approvals" +result=$(dcld query auth all-accounts) +check_response "$result" "\"address\": \"$user_address\"" + +test_divider + +echo "Get an account for $user" +result=$(dcld query auth account --address=$user_address) +check_response "$result" "\"address\": \"$user_address\"" +check_response_and_report "$result" $jack_address "json" +check_response_and_report "$result" '"info": "Jack is proposing this account"' "json" + +test_divider + +echo "Get an proposed account for $user is not found" +result=$(dcld query auth proposed-account --address=$user_address) +check_response "$result" "Not Found" + +test_divider + +echo "Get all proposed accounts. $user account is not in the list" +result=$(dcld query auth all-proposed-accounts) +check_response "$result" "\[\]" + +test_divider + +# Check creating Vendor Account with invalid pid ranges: negative-case +invalid_pid_ranges="100-101,1-200" + +test_divider +echo "Check creating Vendor Account with invalid pid ranges: negative-case" +random_string user +echo "$user generates keys" +cmd="(echo $passphrase; echo $passphrase) | dcld keys add $user" +result="$(bash -c "$cmd")" + +test_divider + +echo "Get key info for $user" +result=$(echo $passphrase | dcld keys show $user) +check_response "$result" "\"name\": \"$user\"" + +test_divider + +user_address=$(echo $passphrase | dcld keys show $user -a) +user_pubkey=$(echo $passphrase | dcld keys show $user -p) + +test_divider + +echo "Jack proposes account for $user" +result=$(echo $passphrase | dcld tx auth propose-add-account --info="Jack is proposing this account" --address="$user_address" --pubkey="$user_pubkey" --roles="Vendor" --vid=$vid --pid_ranges=$invalid_pid_ranges --from jack --yes 2>&1) || true +check_response "$result" "invalid PID Range is provided" raw + +echo "Get an proposed account for $user is not found" +result=$(dcld query auth proposed-account --address=$user_address) +check_response "$result" "Not Found" + +test_divider + +echo "Get all proposed accounts. $user account is not in the list" +result=$(dcld query auth all-proposed-accounts) +check_response "$result" "\[\]" + +test_divider + +echo "Get all active accounts. $user account is not in the list because has not enough approvals received" +result=$(dcld query auth all-accounts) +response_does_not_contain "$result" "\"address\": \"$user_address\"" + +test_divider + random_string new_trustee1 echo "$new_trustee1 generates keys" cmd="(echo $passphrase; echo $passphrase) | dcld keys add $new_trustee1" diff --git a/integration_tests/cli/common.sh b/integration_tests/cli/common.sh index bb1bf51fb..a23706f76 100755 --- a/integration_tests/cli/common.sh +++ b/integration_tests/cli/common.sh @@ -140,8 +140,15 @@ create_new_vendor_account(){ _address=$(echo $passphrase | dcld keys show $_name -a) _pubkey=$(echo $passphrase | dcld keys show $_name -p) - echo "Jack proposes account for \"$_name\" with Vendor role" - _result=$(echo $passphrase | dcld tx auth propose-add-account --address="$_address" --pubkey="$_pubkey" --roles=Vendor --vid=$_vid --from jack --yes) + local _result="" + if [ $# -eq 3 ]; then + local _pid_ranges="$3" + echo "Jack proposes account for \"$_name\" with Vendor role and with [$_pid_ranges] associated Product IDs" + _result=$(echo $passphrase | dcld tx auth propose-add-account --address="$_address" --pubkey="$_pubkey" --roles=Vendor --vid=$_vid --pid_ranges=$_pid_ranges --from jack --yes) + else + echo "Jack proposes account for \"$_name\" with Vendor role" + _result=$(echo $passphrase | dcld tx auth propose-add-account --address="$_address" --pubkey="$_pubkey" --roles=Vendor --vid=$_vid --from jack --yes) + fi check_response "$_result" "\"code\": 0" } diff --git a/integration_tests/cli/model-demo.sh b/integration_tests/cli/model-demo.sh index 17d908805..6f804ad3e 100755 --- a/integration_tests/cli/model-demo.sh +++ b/integration_tests/cli/model-demo.sh @@ -26,6 +26,14 @@ create_new_vendor_account $vendor_account $vid test_divider +((vid_with_pids=vid + 1)) +pid_ranges="$pid-$pid" +vendor_account_with_pids=vendor_account_$vid_with_pids +echo "Create Vendor account - $vid_with_pids with ProductIDs - $pid_ranges" +create_new_vendor_account $vendor_account_with_pids $vid_with_pids $pid_ranges + +test_divider + # Body echo "Query non existent model" @@ -57,6 +65,14 @@ echo "$result" test_divider +productLabel="Device #1" +echo "Add Model with VID: $vid_with_pids PID: $pid" +result=$(echo "test1234" | dcld tx model add-model --vid=$vid_with_pids --pid=$pid --deviceTypeID=1 --productName=TestProduct --productLabel="$productLabel" --partNumber=1 --commissioningCustomFlow=0 --from=$vendor_account_with_pids --yes) +check_response "$result" "\"code\": 0" +echo "$result" + +test_divider + echo "Get Model with VID: $vid PID: $pid" result=$(dcld query model get-model --vid=$vid --pid=$pid) check_response "$result" "\"vid\": $vid" @@ -75,6 +91,13 @@ echo "$result" test_divider +echo "Create Model Versions with VID: $vid_with_pids PID: $pid SoftwareVersion: $sv" +result=$(echo "test1234" | dcld tx model add-model-version --vid=$vid_with_pids --pid=$pid --softwareVersion=$sv --minApplicableSoftwareVersion=1 --maxApplicableSoftwareVersion=15 --softwareVersionString=$sv --cdVersionNumber=$cd_version_num --from=$vendor_account_with_pids --yes) +check_response "$result" "\"code\": 0" +echo "$result" + +test_divider + echo "Get all models" result=$(dcld query model all-models) check_response "$result" "\"vid\": $vid" @@ -98,6 +121,13 @@ echo "$result" test_divider +echo "Update Model with VID: ${vid_with_pids} PID: ${pid} with new description" +result=$(echo "test1234" | dcld tx model update-model --vid=$vid_with_pids --pid=$pid --from $vendor_account_with_pids --yes --productLabel "$description") +check_response "$result" "\"code\": 0" +echo "$result" + +test_divider + echo "Get Model with VID: ${vid} PID: ${pid}" result=$(dcld query model get-model --vid=$vid --pid=$pid) check_response "$result" "\"vid\": $vid" @@ -130,6 +160,12 @@ echo "$result" test_divider +echo "Delete Model with VID: ${vid_with_pids} PID: ${pid}" +result=$(dcld tx model delete-model --vid=$vid_with_pids --pid=$pid --from=$vendor_account_with_pids --yes) +echo "$result" + +test_divider + echo "Query non existent model" result=$(dcld query model get-model --vid=$vid --pid=$pid) check_response "$result" "Not Found" @@ -137,7 +173,19 @@ echo "$result" test_divider +echo "Query non existent model" +result=$(dcld query model get-model --vid=$vid_with_pids --pid=$pid) +check_response "$result" "Not Found" +echo "$result" + +test_divider + echo "Query model versions for deleted model" result=$(dcld query model model-version --vid=$vid --pid=$pid --softwareVersion=$sv) check_response "$result" "Not Found" +echo "$result" + +echo "Query model versions for deleted model" +result=$(dcld query model model-version --vid=$vid_with_pids --pid=$pid --softwareVersion=$sv) +check_response "$result" "Not Found" echo "$result" \ No newline at end of file diff --git a/integration_tests/cli/model-negative-cases.sh b/integration_tests/cli/model-negative-cases.sh index 57d4fd3f2..3e84c4af9 100755 --- a/integration_tests/cli/model-negative-cases.sh +++ b/integration_tests/cli/model-negative-cases.sh @@ -33,6 +33,12 @@ test_divider echo "Create CertificationCenter account" create_new_account zb_account "CertificationCenter" +((vid_with_pids=vid + 1)) +pid_ranges="1-100" +vendor_account_with_pids=vendor_account_$vid_with_pids +echo "Create Vendor account - $vid_with_pids with ProductIDs - $pid_ranges" +create_new_vendor_account $vendor_account_with_pids $vid_with_pids $pid_ranges + # Body # Ledger side errors @@ -42,6 +48,11 @@ result=$(echo "test1234" | dcld tx model add-model --vid=$vid --pid=$pid --devic check_response_and_report "$result" "\"code\": 4" echo "$result" +echo "Add Model with VID: $vid_with_pids PID: 101 :Vendor with non-associated PID" +result=$(echo "test1234" | dcld tx model add-model --vid=$vid_with_pids --pid=101 --deviceTypeID=1 --productName=TestProduct --productLabel=TestingProductLabel --partNumber=1 --commissioningCustomFlow=0 --from=$vendor_account_with_pids --yes) +check_response_and_report "$result" "\"code\": 4" +echo "$result" + test_divider vid1=$RANDOM diff --git a/integration_tests/constants/constants.go b/integration_tests/constants/constants.go index 79cacf514..3c5d51727 100644 --- a/integration_tests/constants/constants.go +++ b/integration_tests/constants/constants.go @@ -19,6 +19,7 @@ import ( cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/simapp" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) func strToPubKey(pkStr string, cdc codec.Codec) cryptotypes.PubKey { @@ -130,15 +131,19 @@ var ( UpgradePlanInfo = "Some upgrade info" // - Address1, _ = sdk.AccAddressFromBech32("cosmos1s5xf3aanx7w84hgplk9z3l90qfpantg6nsmhpf") - Address2, _ = sdk.AccAddressFromBech32("cosmos1nl4uaesk9gtu7su3n89lne6xpa6lq8gljn79rq") - Address3, _ = sdk.AccAddressFromBech32("cosmos12r9vsus5js32pvnayt33zhcd4y9wcqcly45gr9") - Address4, _ = sdk.AccAddressFromBech32("cosmos1vvwldfef3yuggm7ge9p34d6dvpz5s74nus6n7g") - VendorID1 int32 = 1000 - VendorID2 int32 = 2000 - VendorID3 int32 = 3000 - VendorID4 int32 = 4000 - PubKey1 = strToPubKey( + Address1, _ = sdk.AccAddressFromBech32("cosmos1s5xf3aanx7w84hgplk9z3l90qfpantg6nsmhpf") + Address2, _ = sdk.AccAddressFromBech32("cosmos1nl4uaesk9gtu7su3n89lne6xpa6lq8gljn79rq") + Address3, _ = sdk.AccAddressFromBech32("cosmos12r9vsus5js32pvnayt33zhcd4y9wcqcly45gr9") + Address4, _ = sdk.AccAddressFromBech32("cosmos1vvwldfef3yuggm7ge9p34d6dvpz5s74nus6n7g") + VendorID1 int32 = 1000 + VendorID2 int32 = 2000 + VendorID3 int32 = 3000 + VendorID4 int32 = 4000 + ProductIDsEmpty []*types.Uint16Range + ProductIDsFull = append([]*types.Uint16Range{}, &types.Uint16Range{Min: 1, Max: 65535}) + ProductIDs100 = append([]*types.Uint16Range{}, &types.Uint16Range{Min: 1, Max: 100}) + ProductIDs200 = append([]*types.Uint16Range{}, &types.Uint16Range{Min: 1, Max: 100}, &types.Uint16Range{Min: 101, Max: 200}) + PubKey1 = strToPubKey( `{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"Aw1XXHQ8i6JVNKsFQ9eQArJVt2GXEO0EBFsQL6XJ5BxY"}`, defEncConfig.Marshaler, ) diff --git a/integration_tests/grpc_rest/compliance/helpers.go b/integration_tests/grpc_rest/compliance/helpers.go index 80d2d4e2f..225c7f431 100644 --- a/integration_tests/grpc_rest/compliance/helpers.go +++ b/integration_tests/grpc_rest/compliance/helpers.go @@ -523,6 +523,7 @@ func CDCertificateIDUpdateChangesOnlyOneComplianceInfo(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -538,6 +539,7 @@ func CDCertificateIDUpdateChangesOnlyOneComplianceInfo(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -646,6 +648,7 @@ func DeleteComplianceInfoForAllCertStatuses(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -661,6 +664,7 @@ func DeleteComplianceInfoForAllCertStatuses(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -835,6 +839,7 @@ func DemoTrackCompliance(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -850,6 +855,7 @@ func DemoTrackCompliance(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1162,6 +1168,7 @@ func DemoTrackRevocation(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1177,6 +1184,7 @@ func DemoTrackRevocation(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1339,6 +1347,7 @@ func DemoTrackProvision(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1354,6 +1363,7 @@ func DemoTrackProvision(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1682,6 +1692,7 @@ func DemoTrackComplianceWithHexVidAndPid(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1698,6 +1709,7 @@ func DemoTrackComplianceWithHexVidAndPid(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1791,6 +1803,7 @@ func DemoTrackRevocationWithHexVidAndPid(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1807,6 +1820,7 @@ func DemoTrackRevocationWithHexVidAndPid(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1924,6 +1938,7 @@ func DemoTrackProvisionByHexVidAndPid(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1939,6 +1954,7 @@ func DemoTrackProvisionByHexVidAndPid(suite *utils.TestSuite) { certCenter, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, 1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, diff --git a/integration_tests/grpc_rest/dclauth/helpers.go b/integration_tests/grpc_rest/dclauth/helpers.go index 081a04301..e8ee7b0c3 100644 --- a/integration_tests/grpc_rest/dclauth/helpers.go +++ b/integration_tests/grpc_rest/dclauth/helpers.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/require" testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/utils" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" modeltypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/model/types" ) @@ -333,12 +334,13 @@ func ProposeAddAccount( accKey cryptotypes.PubKey, roles dclauthtypes.AccountRoles, vendorID int32, + productIDs []*types.Uint16Range, signerName string, signerAccount *dclauthtypes.Account, info string, ) (*sdk.TxResponse, error) { msg, err := dclauthtypes.NewMsgProposeAddAccount( - suite.GetAddress(signerName), accAddr, accKey, roles, vendorID, info) + suite.GetAddress(signerName), accAddr, accKey, roles, vendorID, productIDs, info) require.NoError(suite.T, err) return suite.BuildAndBroadcastTx([]sdk.Msg{msg}, signerName, signerAccount) @@ -410,6 +412,7 @@ func CreateAccount( accountName string, roles dclauthtypes.AccountRoles, vendorID int32, + productIDs []*types.Uint16Range, proposerName string, proposerAccount *dclauthtypes.Account, approverName string, @@ -424,6 +427,7 @@ func CreateAccount( accountInfo.GetPubKey(), roles, vendorID, + productIDs, proposerName, proposerAccount, info, @@ -450,6 +454,7 @@ func CreateVendorAccount( accountName string, roles dclauthtypes.AccountRoles, vendorID int32, + productIDs []*types.Uint16Range, proposerName string, proposerAccount *dclauthtypes.Account, approverName string, @@ -464,6 +469,7 @@ func CreateVendorAccount( accountInfo.GetPubKey(), roles, vendorID, + productIDs, proposerName, proposerAccount, info, @@ -565,7 +571,7 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -718,7 +724,7 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -823,7 +829,7 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, 0, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -964,7 +970,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Vendor, dclauthtypes.NodeAdmin}, testconstants.Vid, + dclauthtypes.AccountRoles{dclauthtypes.Vendor, dclauthtypes.NodeAdmin}, + testconstants.Vid, testconstants.ProductIDs100, jackName, jackAccount, testconstants.Info, ) @@ -987,6 +994,7 @@ func AuthDemo(suite *utils.TestSuite) { require.NoError(suite.T, err) require.Equal(suite.T, testAccAddr, testProposedVendorAccount.GetAddress()) require.Equal(suite.T, []dclauthtypes.AccountRole{dclauthtypes.Vendor, dclauthtypes.NodeAdmin}, testProposedVendorAccount.GetRoles()) + require.Equal(suite.T, testconstants.ProductIDs100, testProposedVendorAccount.GetProductIDs()) // Alice approves new account _, err = ApproveAddAccount(suite, testAccAddr, aliceName, aliceAccount, testconstants.Info) @@ -1037,7 +1045,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Vendor}, testconstants.Vid, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + testconstants.Vid, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -1052,6 +1061,7 @@ func AuthDemo(suite *utils.TestSuite) { require.NoError(suite.T, err) require.Equal(suite.T, testAccAddr, testVendorAccount.GetAddress()) require.Equal(suite.T, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testVendorAccount.GetRoles()) + require.Equal(suite.T, 0, len(testVendorAccount.GetProductIDs())) // Query all proposed accounts receivedProposedAccounts, _ = GetProposedAccounts(suite) @@ -1072,7 +1082,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, 0, + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, + 0, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -1095,7 +1106,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, 0, + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, + 0, testconstants.ProductIDsEmpty, jackName, jackAccount, testconstants.Info, ) @@ -1146,7 +1158,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Vendor}, testconstants.Vid, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + testconstants.Vid, testconstants.ProductIDsFull, jackName, jackAccount, testconstants.Info, ) @@ -1177,7 +1190,8 @@ func AuthDemo(suite *utils.TestSuite) { _, err = ProposeAddAccount( suite, testAccAddr, testAccPubKey, - dclauthtypes.AccountRoles{dclauthtypes.Vendor}, testconstants.Vid, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + testconstants.Vid, testconstants.ProductIDsFull, jackName, jackAccount, testconstants.Info, ) @@ -1200,6 +1214,7 @@ func AuthDemo(suite *utils.TestSuite) { require.NoError(suite.T, err) require.Equal(suite.T, testAccAddr, testProposedVendorAccount.GetAddress()) require.Equal(suite.T, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testProposedVendorAccount.GetRoles()) + require.Equal(suite.T, testconstants.ProductIDsFull, testProposedVendorAccount.GetProductIDs()) // Alice approves new account _, err = ApproveAddAccount(suite, testAccAddr, aliceName, aliceAccount, testconstants.Info) @@ -1218,4 +1233,5 @@ func AuthDemo(suite *utils.TestSuite) { require.NoError(suite.T, err) require.Equal(suite.T, testAccAddr, testVendorAccount.GetAddress()) require.Equal(suite.T, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testVendorAccount.GetRoles()) + require.Equal(suite.T, testconstants.ProductIDsFull, testVendorAccount.GetProductIDs()) } diff --git a/integration_tests/grpc_rest/dclupgrade/helpers.go b/integration_tests/grpc_rest/dclupgrade/helpers.go index aac0f1c8f..c94d7884a 100644 --- a/integration_tests/grpc_rest/dclupgrade/helpers.go +++ b/integration_tests/grpc_rest/dclupgrade/helpers.go @@ -446,6 +446,7 @@ func ProposeUpgradeByNonTrustee(suite *utils.TestSuite) { dclauthtypes.NodeAdmin, }, int32(tmrand.Uint16()+1), + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -490,6 +491,7 @@ func ApproveUpgradeByNonTrustee(suite *utils.TestSuite) { dclauthtypes.NodeAdmin, }, int32(tmrand.Uint16()+1), + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, diff --git a/integration_tests/grpc_rest/model/grpc_test.go b/integration_tests/grpc_rest/model/grpc_test.go index 5502c372f..b18b196c7 100644 --- a/integration_tests/grpc_rest/model/grpc_test.go +++ b/integration_tests/grpc_rest/model/grpc_test.go @@ -87,3 +87,27 @@ func TestDeleteModelVersionCertifiedGRPC(t *testing.T) { suite := utils.SetupTest(t, testconstants.ChainID, false) model.DeleteModelVersionCertified(&suite) } +func TestAddModelByVendorProductIdsGRPC(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.AddModelByVendorWithProductIds(&suite) +} + +func TestUpdateByVendorWithProductIdsGRPC(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.UpdateByVendorWithProductIds(&suite) +} + +func TestAddModelByVendorWithNonAssociatedProductIdsGRPC(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.AddModelByVendorWithNonAssociatedProductIds(&suite) +} + +func TestUpdateModelByVendorWithNonAssociatedProductIdsGRPC(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.UpdateModelByVendorWithNonAssociatedProductIds(&suite) +} + +func TestDeleteModelByVendorWithNonAssociatedProductIdsGRPC(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.DeleteModelByVendorWithNonAssociatedProductIds(&suite) +} diff --git a/integration_tests/grpc_rest/model/helpers.go b/integration_tests/grpc_rest/model/helpers.go index b2a4f29e6..9f53235ae 100644 --- a/integration_tests/grpc_rest/model/helpers.go +++ b/integration_tests/grpc_rest/model/helpers.go @@ -25,6 +25,7 @@ import ( testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" testDclauth "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/grpc_rest/dclauth" "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/utils" + commontypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/compliance/types" dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" modeltypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/model/types" @@ -363,6 +364,85 @@ func GetVendorModelsByHexVid( return &res, nil } +func AddModelByVendorWithProductIds(suite *utils.TestSuite) { + // Alice and Bob are predefined Trustees + aliceName := testconstants.AliceAccount + aliceKeyInfo, err := suite.Kr.Key(aliceName) + require.NoError(suite.T, err) + aliceAccount, err := testDclauth.GetAccount(suite, aliceKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + bobName := testconstants.BobAccount + bobKeyInfo, err := suite.Kr.Key(bobName) + require.NoError(suite.T, err) + bobAccount, err := testDclauth.GetAccount(suite, bobKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + // register new account with Vendor role + vendorAccountName := utils.RandString() + vid := int32(tmrand.Uint16()) + pid := int32(100) + vendorAccount := testDclauth.CreateVendorAccount( + suite, + vendorAccountName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + vid, + testconstants.ProductIDs100, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + + createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorAccountName, vendorAccount) + require.NoError(suite.T, err) +} + +func UpdateByVendorWithProductIds(suite *utils.TestSuite) { + // Alice and Bob are predefined Trustees + aliceName := testconstants.AliceAccount + aliceKeyInfo, err := suite.Kr.Key(aliceName) + require.NoError(suite.T, err) + aliceAccount, err := testDclauth.GetAccount(suite, aliceKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + bobName := testconstants.BobAccount + bobKeyInfo, err := suite.Kr.Key(bobName) + require.NoError(suite.T, err) + bobAccount, err := testDclauth.GetAccount(suite, bobKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + // register new account with Vendor role + ownerName := utils.RandString() + vid := int32(tmrand.Uint16()) + pid := int32(200) + owner := testDclauth.CreateVendorAccount( + suite, + ownerName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + vid, + testconstants.ProductIDs200, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + + createModelMsg := NewMsgCreateModel(vid, pid, owner.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, ownerName, owner) + require.NoError(suite.T, err) + + updateModelMsg := NewMsgUpdateModel(vid, pid, owner.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{updateModelMsg}, ownerName, owner) + require.NoError(suite.T, err) + + model, _ := GetModel(suite, vid, pid) + require.Equal(suite.T, int32(2), model.LsfRevision) +} + func DeleteModelWithAssociatedModelVersions(suite *utils.TestSuite) { // Alice and Bob are predefined Trustees aliceName := testconstants.AliceAccount @@ -379,12 +459,14 @@ func DeleteModelWithAssociatedModelVersions(suite *utils.TestSuite) { // Register new Vendor account vid := int32(tmrand.Uint16()) + pid := int32(tmrand.Uint16()) vendorName := utils.RandString() vendorAccount := testDclauth.CreateVendorAccount( suite, vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + []*commontypes.Uint16Range{{Min: pid, Max: pid}}, aliceName, aliceAccount, bobName, @@ -394,7 +476,6 @@ func DeleteModelWithAssociatedModelVersions(suite *utils.TestSuite) { require.NotNil(suite.T, vendorAccount) // New vendor adds a model - pid := int32(tmrand.Uint16()) createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -449,6 +530,7 @@ func DeleteModelWithAssociatedModelVersionsCertified(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -460,11 +542,13 @@ func DeleteModelWithAssociatedModelVersionsCertified(suite *utils.TestSuite) { // Register new Certification center ccvid := int32(tmrand.Uint16()) ccName := utils.RandString() + pid := int32(tmrand.Uint16()) ccAccount := testDclauth.CreateAccount( suite, ccName, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, ccvid, + []*commontypes.Uint16Range{{Min: pid, Max: pid}}, aliceName, aliceAccount, bobName, @@ -474,7 +558,6 @@ func DeleteModelWithAssociatedModelVersionsCertified(suite *utils.TestSuite) { require.NotNil(suite.T, vendorAccount) // New vendor adds a model - pid := int32(tmrand.Uint16()) createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -529,11 +612,13 @@ func DeleteModelVersion(suite *utils.TestSuite) { // Register new Vendor account vid := int32(tmrand.Uint16()) vendorName := utils.RandString() + pid := int32(tmrand.Uint16()) vendorAccount := testDclauth.CreateVendorAccount( suite, vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + []*commontypes.Uint16Range{{Min: pid, Max: pid}}, aliceName, aliceAccount, bobName, @@ -543,7 +628,6 @@ func DeleteModelVersion(suite *utils.TestSuite) { require.NotNil(suite.T, vendorAccount) // New vendor adds a model - pid := int32(tmrand.Uint16()) createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -578,12 +662,14 @@ func DeleteModelVersionDifferentVid(suite *utils.TestSuite) { // Register new Vendor account vid := int32(tmrand.Uint16()) + pid := int32(tmrand.Uint16()) vendorName := utils.RandString() vendorAccount := testDclauth.CreateVendorAccount( suite, vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + []*commontypes.Uint16Range{{Min: pid, Max: pid}}, aliceName, aliceAccount, bobName, @@ -593,7 +679,6 @@ func DeleteModelVersionDifferentVid(suite *utils.TestSuite) { require.NotNil(suite.T, vendorAccount) // vendor adds a model - pid := int32(tmrand.Uint16()) createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -610,6 +695,7 @@ func DeleteModelVersionDifferentVid(suite *utils.TestSuite) { vendor2Name, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid2, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -652,6 +738,7 @@ func DeleteModelVersionDoesNotExist(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -688,6 +775,7 @@ func DeleteModelVersionNotByCreator(suite *utils.TestSuite) { vendor1Name, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -704,6 +792,7 @@ func DeleteModelVersionNotByCreator(suite *utils.TestSuite) { vendor2Name, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid2, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -756,6 +845,7 @@ func DeleteModelVersionCertified(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -780,6 +870,7 @@ func DeleteModelVersionCertified(suite *utils.TestSuite) { certCenterName, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -834,12 +925,15 @@ func Demo(suite *utils.TestSuite) { // Register new Vendor account vid := int32(tmrand.Uint16()) + var pid1 int32 = 1 + var pid2 int32 = 2 vendorName := utils.RandString() vendorAccount := testDclauth.CreateVendorAccount( suite, vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + []*commontypes.Uint16Range{{Min: pid1, Max: pid2}}, aliceName, aliceAccount, bobName, @@ -853,7 +947,6 @@ func Demo(suite *utils.TestSuite) { require.NoError(suite.T, err) // New vendor adds first model - pid1 := int32(tmrand.Uint16()) createFirstModelMsg := NewMsgCreateModel(vid, pid1, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createFirstModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -867,7 +960,6 @@ func Demo(suite *utils.TestSuite) { require.Equal(suite.T, createFirstModelMsg.ProductLabel, receivedModel.ProductLabel) // Add second model - pid2 := int32(tmrand.Uint16()) createSecondModelMsg := NewMsgCreateModel(vid, pid2, vendorAccount.Address) _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createSecondModelMsg}, vendorName, vendorAccount) require.NoError(suite.T, err) @@ -943,6 +1035,7 @@ func AddModelByNonVendor(suite *utils.TestSuite) { nonVendorAccountName, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -960,6 +1053,150 @@ func AddModelByNonVendor(suite *utils.TestSuite) { require.True(suite.T, sdkerrors.ErrUnauthorized.Is(err)) } +func AddModelByVendorWithNonAssociatedProductIds(suite *utils.TestSuite) { + // Alice and Bob are predefined Trustees + aliceName := testconstants.AliceAccount + aliceKeyInfo, err := suite.Kr.Key(aliceName) + require.NoError(suite.T, err) + aliceAccount, err := testDclauth.GetAccount(suite, aliceKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + bobName := testconstants.BobAccount + bobKeyInfo, err := suite.Kr.Key(bobName) + require.NoError(suite.T, err) + bobAccount, err := testDclauth.GetAccount(suite, bobKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + // register new account with Vendor role + vendorAccountName := utils.RandString() + vid := int32(tmrand.Uint16()) + pid := int32(101) + vendorAccount := testDclauth.CreateVendorAccount( + suite, + vendorAccountName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + vid, + testconstants.ProductIDs100, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + + // try to add createModelMsg + createModelMsg := NewMsgCreateModel(vid, pid, vendorAccount.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, vendorAccountName, vendorAccount) + require.Error(suite.T, err) + require.True(suite.T, sdkerrors.ErrUnauthorized.Is(err)) +} + +func UpdateModelByVendorWithNonAssociatedProductIds(suite *utils.TestSuite) { + // Alice and Bob are predefined Trustees + aliceName := testconstants.AliceAccount + aliceKeyInfo, err := suite.Kr.Key(aliceName) + require.NoError(suite.T, err) + aliceAccount, err := testDclauth.GetAccount(suite, aliceKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + bobName := testconstants.BobAccount + bobKeyInfo, err := suite.Kr.Key(bobName) + require.NoError(suite.T, err) + bobAccount, err := testDclauth.GetAccount(suite, bobKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + // register new account with Vendor role + ownerName := utils.RandString() + pid := int32(200) + owner := testDclauth.CreateVendorAccount( + suite, + ownerName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + int32(tmrand.Uint16()), + testconstants.ProductIDs200, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + vendorName := utils.RandString() + vendor := testDclauth.CreateVendorAccount( + suite, + vendorName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + int32(tmrand.Uint16()), + testconstants.ProductIDs100, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + + createModelMsg := NewMsgCreateModel(owner.VendorID, pid, owner.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, ownerName, owner) + require.NoError(suite.T, err) + + updateModelMsg := NewMsgUpdateModel(vendor.VendorID, pid, vendor.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{updateModelMsg}, vendorName, vendor) + require.Error(suite.T, err) + require.True(suite.T, sdkerrors.ErrUnauthorized.Is(err)) +} + +func DeleteModelByVendorWithNonAssociatedProductIds(suite *utils.TestSuite) { + // Alice and Bob are predefined Trustees + aliceName := testconstants.AliceAccount + aliceKeyInfo, err := suite.Kr.Key(aliceName) + require.NoError(suite.T, err) + aliceAccount, err := testDclauth.GetAccount(suite, aliceKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + bobName := testconstants.BobAccount + bobKeyInfo, err := suite.Kr.Key(bobName) + require.NoError(suite.T, err) + bobAccount, err := testDclauth.GetAccount(suite, bobKeyInfo.GetAddress()) + require.NoError(suite.T, err) + + // register new account with Vendor role + ownerName := utils.RandString() + pid := int32(200) + owner := testDclauth.CreateVendorAccount( + suite, + ownerName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + int32(tmrand.Uint16()), + testconstants.ProductIDs200, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + vendorName := utils.RandString() + vendor := testDclauth.CreateVendorAccount( + suite, + vendorName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + int32(tmrand.Uint16()), + testconstants.ProductIDs100, + aliceName, + aliceAccount, + bobName, + bobAccount, + testconstants.Info, + ) + + createModelMsg := NewMsgCreateModel(owner.VendorID, pid, owner.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{createModelMsg}, ownerName, owner) + require.NoError(suite.T, err) + + deleteModel := NewMsgDeleteModel(vendor.VendorID, pid, vendor.Address) + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{deleteModel}, vendorName, vendor) + require.Error(suite.T, err) + require.True(suite.T, sdkerrors.ErrUnauthorized.Is(err)) +} + func AddModelByDifferentVendor(suite *utils.TestSuite) { // Alice and Bob are predefined Trustees aliceName := testconstants.AliceAccount @@ -982,6 +1219,7 @@ func AddModelByDifferentVendor(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid+1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -1019,6 +1257,7 @@ func AddModelTwice(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -1090,6 +1329,7 @@ func DemoWithHexVidAndPid(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, diff --git a/integration_tests/grpc_rest/model/rest_test.go b/integration_tests/grpc_rest/model/rest_test.go index 91c993472..b28b9e963 100644 --- a/integration_tests/grpc_rest/model/rest_test.go +++ b/integration_tests/grpc_rest/model/rest_test.go @@ -97,3 +97,28 @@ func TestDeleteModelVersionCertifiedREST(t *testing.T) { suite := utils.SetupTest(t, testconstants.ChainID, true) model.DeleteModelVersionCertified(&suite) } + +func TestAddModelByVendorProductIdsREST(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.AddModelByVendorWithProductIds(&suite) +} + +func TestUpdateByVendorWithProductIdsREST(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.UpdateByVendorWithProductIds(&suite) +} + +func TestAddModelByVendorWithNonAssociatedProductIdsREST(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.AddModelByVendorWithNonAssociatedProductIds(&suite) +} + +func TestUpdateModelByVendorWithNonAssociatedProductIdsREST(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.UpdateModelByVendorWithNonAssociatedProductIds(&suite) +} + +func TestDeleteModelByVendorWithNonAssociatedProductIdsREST(t *testing.T) { + suite := utils.SetupTest(t, testconstants.ChainID, false) + model.DeleteModelByVendorWithNonAssociatedProductIds(&suite) +} diff --git a/integration_tests/grpc_rest/pki/helpers.go b/integration_tests/grpc_rest/pki/helpers.go index 92b381f7c..32591ae19 100644 --- a/integration_tests/grpc_rest/pki/helpers.go +++ b/integration_tests/grpc_rest/pki/helpers.go @@ -641,6 +641,7 @@ func Demo(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -656,6 +657,7 @@ func Demo(suite *utils.TestSuite) { vendorAdminName, dclauthtypes.AccountRoles{dclauthtypes.VendorAdmin}, 0, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1427,6 +1429,7 @@ func Demo(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, 65521, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, @@ -1519,6 +1522,7 @@ func Demo(suite *utils.TestSuite) { venName65522, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, 65522, + testconstants.ProductIDsEmpty, jackName, jackAccount, aliceName, diff --git a/integration_tests/grpc_rest/validator/helpers.go b/integration_tests/grpc_rest/validator/helpers.go index b1ec52953..fff674b78 100644 --- a/integration_tests/grpc_rest/validator/helpers.go +++ b/integration_tests/grpc_rest/validator/helpers.go @@ -298,6 +298,7 @@ func Demo(suite *utils.TestSuite) { nodeAdminName, dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, jackName, diff --git a/integration_tests/grpc_rest/vendorinfo/helpers.go b/integration_tests/grpc_rest/vendorinfo/helpers.go index 6881de4c9..753de4a10 100644 --- a/integration_tests/grpc_rest/vendorinfo/helpers.go +++ b/integration_tests/grpc_rest/vendorinfo/helpers.go @@ -147,6 +147,7 @@ func Demo(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -198,6 +199,7 @@ func AddVendorInfoByNonVendor(suite *utils.TestSuite) { nonVendorAccountNamew, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -236,6 +238,7 @@ func AddVendorInfoByDifferentVendor(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid+1, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -272,6 +275,7 @@ func AddVendorInfoByNonVendorAdmin(suite *utils.TestSuite) { nonVendorAdminAccountNamew, dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter, dclauthtypes.NodeAdmin}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -310,6 +314,7 @@ func AddVendorInfoByVendorAdmin(suite *utils.TestSuite) { vendorAdminAccountName, dclauthtypes.AccountRoles{dclauthtypes.VendorAdmin}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -347,6 +352,7 @@ func UpdateVendorInfoByVendorAdmin(suite *utils.TestSuite) { vendorAdminAccountName, dclauthtypes.AccountRoles{dclauthtypes.VendorAdmin}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -396,6 +402,7 @@ func AddVendorInfoTwice(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, @@ -451,6 +458,7 @@ func DemoWithHexVid(suite *utils.TestSuite) { vendorName, dclauthtypes.AccountRoles{dclauthtypes.Vendor}, vid, + testconstants.ProductIDsEmpty, aliceName, aliceAccount, bobName, diff --git a/proto/common/uint16_range.proto b/proto/common/uint16_range.proto new file mode 100644 index 000000000..d2320643b --- /dev/null +++ b/proto/common/uint16_range.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package zigbeealliance.distributedcomplianceledger.common; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types"; + +message Uint16Range { + int32 min = 1 [(gogoproto.moretags) = "validate:\"gte=0,lte=65535\""]; + int32 max = 2 [(gogoproto.moretags) = "validate:\"gte=0,lte=65535\""]; +} \ No newline at end of file diff --git a/proto/dclauth/account.proto b/proto/dclauth/account.proto index 2ca70d4cc..14e2e0562 100644 --- a/proto/dclauth/account.proto +++ b/proto/dclauth/account.proto @@ -5,6 +5,7 @@ option go_package = "github.com/zigbee-alliance/distributed-compliance-ledger/x/ import "gogoproto/gogo.proto"; import "cosmos/auth/v1beta1/auth.proto"; +import "common/uint16_range.proto"; import "dclauth/grant.proto"; @@ -21,5 +22,6 @@ message Account { repeated Grant approvals = 3; int32 vendorID = 4; repeated Grant rejects = 5; + repeated common.Uint16Range productIDs = 6; } diff --git a/proto/dclauth/tx.proto b/proto/dclauth/tx.proto index af0fdf67f..72c172244 100644 --- a/proto/dclauth/tx.proto +++ b/proto/dclauth/tx.proto @@ -8,6 +8,7 @@ option go_package = "github.com/zigbee-alliance/distributed-compliance-ledger/x/ import "google/protobuf/any.proto"; import "gogoproto/gogo.proto"; import "cosmos_proto/cosmos.proto"; +import "common/uint16_range.proto"; // Msg defines the Msg service. service Msg { @@ -27,6 +28,7 @@ message MsgProposeAddAccount { int32 vendorID = 5 [(gogoproto.moretags) = "validate:\"gte=0,lte=65535\""]; string info = 6 [(gogoproto.moretags) = "validate:\"max=4096\""]; int64 time = 7; + repeated common.Uint16Range productIDs = 8; } message MsgProposeAddAccountResponse { diff --git a/testutil/network/network.go b/testutil/network/network.go index 7b1887f02..a742ce254 100644 --- a/testutil/network/network.go +++ b/testutil/network/network.go @@ -341,6 +341,7 @@ func newNetwork(t *testing.T, cfg Config) *Network { nil, nil, testconstants.Vid, + testconstants.ProductIDsEmpty, ) genAccounts = append(genAccounts, *account) diff --git a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/rest.ts b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/rest.ts index d0b9bf82f..4b9efa438 100644 --- a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/rest.ts +++ b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/rest.ts @@ -14,6 +14,14 @@ export enum RevokedAccountReason { MaliciousValidator = "MaliciousValidator", } +export interface CommonUint16Range { + /** @format int32 */ + min?: number; + + /** @format int32 */ + max?: number; +} + export interface DclauthAccount { /** * BaseAccount defines a base account type. It contains all the necessary fields @@ -27,6 +35,7 @@ export interface DclauthAccount { /** @format int32 */ vendorID?: number; rejects?: DclauthGrant[]; + productIDs?: CommonUint16Range[]; } export interface DclauthAccountStat { diff --git a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/common/uint16_range.ts b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/common/uint16_range.ts new file mode 100644 index 000000000..d82d138c7 --- /dev/null +++ b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/common/uint16_range.ts @@ -0,0 +1,92 @@ +/* eslint-disable */ +import { Writer, Reader } from 'protobufjs/minimal' + +export const protobufPackage = 'zigbeealliance.distributedcomplianceledger.common' + +export interface Uint16Range { + min: number + max: number +} + +const baseUint16Range: object = { min: 0, max: 0 } + +export const Uint16Range = { + encode(message: Uint16Range, writer: Writer = Writer.create()): Writer { + if (message.min !== 0) { + writer.uint32(8).int32(message.min) + } + if (message.max !== 0) { + writer.uint32(16).int32(message.max) + } + return writer + }, + + decode(input: Reader | Uint8Array, length?: number): Uint16Range { + const reader = input instanceof Uint8Array ? new Reader(input) : input + let end = length === undefined ? reader.len : reader.pos + length + const message = { ...baseUint16Range } as Uint16Range + while (reader.pos < end) { + const tag = reader.uint32() + switch (tag >>> 3) { + case 1: + message.min = reader.int32() + break + case 2: + message.max = reader.int32() + break + default: + reader.skipType(tag & 7) + break + } + } + return message + }, + + fromJSON(object: any): Uint16Range { + const message = { ...baseUint16Range } as Uint16Range + if (object.min !== undefined && object.min !== null) { + message.min = Number(object.min) + } else { + message.min = 0 + } + if (object.max !== undefined && object.max !== null) { + message.max = Number(object.max) + } else { + message.max = 0 + } + return message + }, + + toJSON(message: Uint16Range): unknown { + const obj: any = {} + message.min !== undefined && (obj.min = message.min) + message.max !== undefined && (obj.max = message.max) + return obj + }, + + fromPartial(object: DeepPartial): Uint16Range { + const message = { ...baseUint16Range } as Uint16Range + if (object.min !== undefined && object.min !== null) { + message.min = object.min + } else { + message.min = 0 + } + if (object.max !== undefined && object.max !== null) { + message.max = object.max + } else { + message.max = 0 + } + return message + } +} + +type Builtin = Date | Function | Uint8Array | string | number | undefined +export type DeepPartial = T extends Builtin + ? T + : T extends Array + ? Array> + : T extends ReadonlyArray + ? ReadonlyArray> + : T extends {} + ? { [K in keyof T]?: DeepPartial } + : Partial diff --git a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/account.ts b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/account.ts index ab2d48ced..6d3253206 100644 --- a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/account.ts +++ b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/account.ts @@ -1,6 +1,7 @@ /* eslint-disable */ import { BaseAccount } from '../cosmos/auth/v1beta1/auth' import { Grant } from '../dclauth/grant' +import { Uint16Range } from '../common/uint16_range' import { Writer, Reader } from 'protobufjs/minimal' export const protobufPackage = 'zigbeealliance.distributedcomplianceledger.dclauth' @@ -16,6 +17,7 @@ export interface Account { approvals: Grant[] vendorID: number rejects: Grant[] + productIDs: Uint16Range[] } const baseAccount: object = { roles: '', vendorID: 0 } @@ -37,6 +39,9 @@ export const Account = { for (const v of message.rejects) { Grant.encode(v!, writer.uint32(42).fork()).ldelim() } + for (const v of message.productIDs) { + Uint16Range.encode(v!, writer.uint32(50).fork()).ldelim() + } return writer }, @@ -47,6 +52,7 @@ export const Account = { message.roles = [] message.approvals = [] message.rejects = [] + message.productIDs = [] while (reader.pos < end) { const tag = reader.uint32() switch (tag >>> 3) { @@ -65,6 +71,9 @@ export const Account = { case 5: message.rejects.push(Grant.decode(reader, reader.uint32())) break + case 6: + message.productIDs.push(Uint16Range.decode(reader, reader.uint32())) + break default: reader.skipType(tag & 7) break @@ -78,7 +87,8 @@ export const Account = { message.roles = [] message.approvals = [] message.rejects = [] - if (object.baseAccount !== undefined && object.baseAccount !== null) { + message.productIDs = [] + if (object.baseAccount !== undefined && object.baseAccount !== null) { message.baseAccount = BaseAccount.fromJSON(object.baseAccount) } else { message.baseAccount = undefined @@ -103,6 +113,11 @@ export const Account = { message.rejects.push(Grant.fromJSON(e)) } } + if (object.productIDs !== undefined && object.productIDs !== null) { + for (const e of object.productIDs) { + message.productIDs.push(Uint16Range.fromJSON(e)) + } + } return message }, @@ -125,6 +140,11 @@ export const Account = { } else { obj.rejects = [] } + if (message.productIDs) { + obj.productIDs = message.productIDs.map((e) => (e ? Uint16Range.toJSON(e) : undefined)) + } else { + obj.productIDs = [] + } return obj }, @@ -133,6 +153,7 @@ export const Account = { message.roles = [] message.approvals = [] message.rejects = [] + message.productIDs = [] if (object.baseAccount !== undefined && object.baseAccount !== null) { message.baseAccount = BaseAccount.fromPartial(object.baseAccount) } else { @@ -158,6 +179,11 @@ export const Account = { message.rejects.push(Grant.fromPartial(e)) } } + if (object.productIDs !== undefined && object.productIDs !== null) { + for (const e of object.productIDs) { + message.productIDs.push(Uint16Range.fromPartial(e)) + } + } return message } } diff --git a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/tx.ts b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/tx.ts index 0fbb23d92..1412da61b 100644 --- a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/tx.ts +++ b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.dclauth/module/types/dclauth/tx.ts @@ -2,6 +2,7 @@ import { Reader, util, configure, Writer } from 'protobufjs/minimal' import * as Long from 'long' import { Any } from '../google/protobuf/any' +import { Uint16Range } from '../common/uint16_range' export const protobufPackage = 'zigbeealliance.distributedcomplianceledger.dclauth' @@ -13,6 +14,7 @@ export interface MsgProposeAddAccount { vendorID: number info: string time: number + productIDs: Uint16Range[] } export interface MsgProposeAddAccountResponse {} @@ -78,6 +80,9 @@ export const MsgProposeAddAccount = { if (message.time !== 0) { writer.uint32(56).int64(message.time) } + for (const v of message.productIDs) { + Uint16Range.encode(v!, writer.uint32(66).fork()).ldelim() + } return writer }, @@ -86,6 +91,7 @@ export const MsgProposeAddAccount = { let end = length === undefined ? reader.len : reader.pos + length const message = { ...baseMsgProposeAddAccount } as MsgProposeAddAccount message.roles = [] + message.productIDs = [] while (reader.pos < end) { const tag = reader.uint32() switch (tag >>> 3) { @@ -110,6 +116,9 @@ export const MsgProposeAddAccount = { case 7: message.time = longToNumber(reader.int64() as Long) break + case 8: + message.productIDs.push(Uint16Range.decode(reader, reader.uint32())) + break default: reader.skipType(tag & 7) break @@ -121,6 +130,7 @@ export const MsgProposeAddAccount = { fromJSON(object: any): MsgProposeAddAccount { const message = { ...baseMsgProposeAddAccount } as MsgProposeAddAccount message.roles = [] + message.productIDs = [] if (object.signer !== undefined && object.signer !== null) { message.signer = String(object.signer) } else { @@ -156,6 +166,11 @@ export const MsgProposeAddAccount = { } else { message.time = 0 } + if (object.productIDs !== undefined && object.productIDs !== null) { + for (const e of object.productIDs) { + message.productIDs.push(Uint16Range.fromJSON(e)) + } + } return message }, @@ -172,12 +187,18 @@ export const MsgProposeAddAccount = { message.vendorID !== undefined && (obj.vendorID = message.vendorID) message.info !== undefined && (obj.info = message.info) message.time !== undefined && (obj.time = message.time) + if (message.productIDs) { + obj.productIDs = message.productIDs.map((e) => (e ? Uint16Range.toJSON(e) : undefined)) + } else { + obj.productIDs = [] + } return obj }, fromPartial(object: DeepPartial): MsgProposeAddAccount { const message = { ...baseMsgProposeAddAccount } as MsgProposeAddAccount message.roles = [] + message.productIDs = [] if (object.signer !== undefined && object.signer !== null) { message.signer = object.signer } else { @@ -213,6 +234,11 @@ export const MsgProposeAddAccount = { } else { message.time = 0 } + if (object.productIDs !== undefined && object.productIDs !== null) { + for (const e of object.productIDs) { + message.productIDs.push(Uint16Range.fromPartial(e)) + } + } return message } } diff --git a/x/common/types/uint16_range.pb.go b/x/common/types/uint16_range.pb.go new file mode 100644 index 000000000..a9364123c --- /dev/null +++ b/x/common/types/uint16_range.pb.go @@ -0,0 +1,340 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: common/uint16_range.proto + +package types + +import ( + fmt "fmt" + _ "github.com/gogo/protobuf/gogoproto" + proto "github.com/gogo/protobuf/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Uint16Range struct { + Min int32 `protobuf:"varint,1,opt,name=min,proto3" json:"min,omitempty" validate:"gte=0,lte=65535"` + Max int32 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty" validate:"gte=0,lte=65535"` +} + +func (m *Uint16Range) Reset() { *m = Uint16Range{} } +func (m *Uint16Range) String() string { return proto.CompactTextString(m) } +func (*Uint16Range) ProtoMessage() {} +func (*Uint16Range) Descriptor() ([]byte, []int) { + return fileDescriptor_476afb83b0d37b89, []int{0} +} +func (m *Uint16Range) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Uint16Range) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Uint16Range.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Uint16Range) XXX_Merge(src proto.Message) { + xxx_messageInfo_Uint16Range.Merge(m, src) +} +func (m *Uint16Range) XXX_Size() int { + return m.Size() +} +func (m *Uint16Range) XXX_DiscardUnknown() { + xxx_messageInfo_Uint16Range.DiscardUnknown(m) +} + +var xxx_messageInfo_Uint16Range proto.InternalMessageInfo + +func (m *Uint16Range) GetMin() int32 { + if m != nil { + return m.Min + } + return 0 +} + +func (m *Uint16Range) GetMax() int32 { + if m != nil { + return m.Max + } + return 0 +} + +func init() { + proto.RegisterType((*Uint16Range)(nil), "zigbeealliance.distributedcomplianceledger.common.Uint16Range") +} + +func init() { proto.RegisterFile("common/uint16_range.proto", fileDescriptor_476afb83b0d37b89) } + +var fileDescriptor_476afb83b0d37b89 = []byte{ + // 246 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x4c, 0xce, 0xcf, 0xcd, + 0xcd, 0xcf, 0xd3, 0x2f, 0xcd, 0xcc, 0x2b, 0x31, 0x34, 0x8b, 0x2f, 0x4a, 0xcc, 0x4b, 0x4f, 0xd5, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x32, 0xac, 0xca, 0x4c, 0x4f, 0x4a, 0x4d, 0x4d, 0xcc, 0xc9, + 0xc9, 0x4c, 0xcc, 0x4b, 0x4e, 0xd5, 0x4b, 0xc9, 0x2c, 0x2e, 0x29, 0xca, 0x4c, 0x2a, 0x2d, 0x49, + 0x4d, 0x49, 0xce, 0xcf, 0x2d, 0x80, 0x88, 0xe6, 0xa4, 0xa6, 0xa4, 0xa7, 0x16, 0xe9, 0x41, 0x4c, + 0x91, 0x12, 0x49, 0xcf, 0x4f, 0xcf, 0x07, 0xeb, 0xd6, 0x07, 0xb1, 0x20, 0x06, 0x29, 0x15, 0x72, + 0x71, 0x87, 0x82, 0x8d, 0x0f, 0x02, 0x99, 0x2e, 0x64, 0xc0, 0xc5, 0x9c, 0x9b, 0x99, 0x27, 0xc1, + 0xa8, 0xc0, 0xa8, 0xc1, 0xea, 0x24, 0xf7, 0xe9, 0x9e, 0xbc, 0x54, 0x59, 0x62, 0x4e, 0x66, 0x4a, + 0x62, 0x49, 0xaa, 0x95, 0x52, 0x7a, 0x49, 0xaa, 0xad, 0x81, 0x4e, 0x4e, 0x49, 0xaa, 0xad, 0x99, + 0xa9, 0xa9, 0xb1, 0xa9, 0x52, 0x10, 0x48, 0x29, 0x58, 0x47, 0x62, 0x85, 0x04, 0x13, 0x91, 0x3a, + 0x12, 0x2b, 0x9c, 0x12, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, 0x8e, 0xf1, 0xc1, 0x23, 0x39, + 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, 0x58, 0x8e, 0x21, 0xca, 0x3d, + 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x09, 0xe4, 0x62, 0x7d, 0x88, 0x07, 0x75, 0x61, 0x3e, 0xd4, 0x47, + 0xf2, 0xa1, 0x2e, 0xc2, 0x8b, 0xba, 0x10, 0x3f, 0xea, 0x57, 0xe8, 0x43, 0xc3, 0xaa, 0xa4, 0xb2, + 0x20, 0xb5, 0x38, 0x89, 0x0d, 0xec, 0x39, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xa7, 0xe1, + 0x11, 0x4e, 0x42, 0x01, 0x00, 0x00, +} + +func (m *Uint16Range) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Uint16Range) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Uint16Range) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Max != 0 { + i = encodeVarintUint16Range(dAtA, i, uint64(m.Max)) + i-- + dAtA[i] = 0x10 + } + if m.Min != 0 { + i = encodeVarintUint16Range(dAtA, i, uint64(m.Min)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + +func encodeVarintUint16Range(dAtA []byte, offset int, v uint64) int { + offset -= sovUint16Range(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Uint16Range) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Min != 0 { + n += 1 + sovUint16Range(uint64(m.Min)) + } + if m.Max != 0 { + n += 1 + sovUint16Range(uint64(m.Max)) + } + return n +} + +func sovUint16Range(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozUint16Range(x uint64) (n int) { + return sovUint16Range(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Uint16Range) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUint16Range + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Uint16Range: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Uint16Range: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Min", wireType) + } + m.Min = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUint16Range + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Min |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Max", wireType) + } + m.Max = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowUint16Range + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Max |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipUint16Range(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthUint16Range + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipUint16Range(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUint16Range + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUint16Range + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowUint16Range + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthUint16Range + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupUint16Range + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthUint16Range + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthUint16Range = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowUint16Range = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupUint16Range = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/dclauth/client/cli/flags.go b/x/dclauth/client/cli/flags.go index e4bac1905..35e014630 100644 --- a/x/dclauth/client/cli/flags.go +++ b/x/dclauth/client/cli/flags.go @@ -6,6 +6,7 @@ const ( FlagPubKey = "pubkey" FlagRoles = "roles" FlagVID = "vid" + FlagPIDs = "pid_ranges" FlagRolesUsage = "amount of accounts to take" FlagInfo = "info" FlagInfoUsage = "Optional information/notes for approval, proposal or revocation" diff --git a/x/dclauth/client/cli/tx_propose_add_account.go b/x/dclauth/client/cli/tx_propose_add_account.go index 063b3deba..152ba3c27 100644 --- a/x/dclauth/client/cli/tx_propose_add_account.go +++ b/x/dclauth/client/cli/tx_propose_add_account.go @@ -14,6 +14,7 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/zigbee-alliance/distributed-compliance-ledger/utils/cli" + commontypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" ) @@ -58,6 +59,14 @@ func CmdProposeAddAccount() *cobra.Command { } } + var pidRanges []*commontypes.Uint16Range + if pidStrRanges := viper.GetString(FlagPIDs); len(pidStrRanges) > 0 { //nolint:nestif + pidRanges, err = getPidRanges(pidStrRanges) + if err != nil { + return err + } + } + argInfo := viper.GetString(FlagInfo) msg, err := types.NewMsgProposeAddAccount( @@ -66,6 +75,7 @@ func CmdProposeAddAccount() *cobra.Command { argPubKey, argRoles, argVendorID, + pidRanges, argInfo, ) if err != nil { @@ -88,6 +98,7 @@ func CmdProposeAddAccount() *cobra.Command { fmt.Sprintf("The list of roles, comma-separated, assigning to the account (supported roles: %v)", types.Roles)) cmd.Flags().String(FlagVID, "", "Vendor ID associated with this account (positive non-zero uint16). Required only for Vendor Roles.") + cmd.Flags().String(FlagPIDs, "", "Optional list of Product ID ranges (inclusive numbers split by \"-\") associated with this account (for example: 1-100,200-65535, positive non-zero uint16)") cmd.Flags().String(FlagInfo, "", FlagInfoUsage) cli.AddTxFlagsToCmd(cmd) @@ -98,3 +109,32 @@ func CmdProposeAddAccount() *cobra.Command { return cmd } + +func getPidRanges(pidStrRanges string) ([]*commontypes.Uint16Range, error) { + var pidRanges []*commontypes.Uint16Range + var lastMax int32 + for _, pidStrRange := range strings.Split(pidStrRanges, ",") { + pidRange := strings.Split(pidStrRange, "-") + if len(pidRange) != 2 { + return nil, fmt.Errorf("failed to parse PID Range") + } + min, err := cast.ToInt32E(pidRange[0]) + if err != nil { + return nil, fmt.Errorf("failed to parse PID Range: %w", err) + } + max, err := cast.ToInt32E(pidRange[1]) + if err != nil { + return nil, fmt.Errorf("failed to parse PID Range: %w", err) + } + if min > max || max <= 0 || min <= 0 { + return nil, fmt.Errorf("invalid PID Range is provided: min=%d, max=%d", min, max) + } + if max <= lastMax || min <= lastMax { + return nil, fmt.Errorf("invalid PID Range is provided: {%d-%d}, ranges are overlapped, range items must be provided in increased order", min, max) + } + pid := commontypes.Uint16Range{Min: min, Max: max} + pidRanges = append(pidRanges, &pid) + lastMax = max + } + return pidRanges, nil +} diff --git a/x/dclauth/client/cli/tx_propose_add_account_test.go b/x/dclauth/client/cli/tx_propose_add_account_test.go new file mode 100644 index 000000000..af17188fc --- /dev/null +++ b/x/dclauth/client/cli/tx_propose_add_account_test.go @@ -0,0 +1,81 @@ +package cli + +import ( + "fmt" + "github.com/stretchr/testify/require" + commontypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" + "testing" +) + +func TestAccount_getPidRanges(t *testing.T) { + tests := []struct { + name string + pidRanges string + want []*commontypes.Uint16Range + err error + }{ + { + name: "get ProductID ranges from \"1-100\"", + pidRanges: "1-100", + want: []*commontypes.Uint16Range{{Min: 1, Max: 100}}, + err: nil, + }, + { + name: "get ProductID ranges from \"1-100,200-300\"", + pidRanges: "1-100,200-300", + want: []*commontypes.Uint16Range{{Min: 1, Max: 100}, {Min: 200, Max: 300}}, + err: nil, + }, + { + name: "get ProductID ranges from \"100-100\"", + pidRanges: "100-100", + want: []*commontypes.Uint16Range{{Min: 100, Max: 100}}, + err: nil, + }, + { + name: "get ProductID ranges from \"1-100-200\"", + pidRanges: "1-100-200", + want: nil, + err: fmt.Errorf("failed to parse PID Range"), + }, + { + name: "get ProductID ranges from \"1-10a,200-300\"", + pidRanges: "1-10a,100-200", + want: nil, + err: fmt.Errorf("failed to parse PID Range"), + }, + { + name: "get ProductID ranges from \"1O-100\"", + pidRanges: "1O-100", + want: nil, + err: fmt.Errorf("failed to parse PID Range"), + }, + { + name: "get ProductID ranges from \"1-10O,101-200\"", + pidRanges: "1-10O,101-200", + want: nil, + err: fmt.Errorf("failed to parse PID Range"), + }, + { + name: "get ProductID ranges from \"0-100,200-300\"", + pidRanges: "0-100,200-300", + want: nil, + err: fmt.Errorf("invalid PID Range is provided"), + }, + { + name: "get ProductID ranges from \"1-100,100-200\"", + pidRanges: "1-100,100-200", + want: nil, + err: fmt.Errorf("invalid PID Range is provided"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got, err := getPidRanges(tt.pidRanges); err != nil && tt.err == nil { + t.Errorf("getPidRanges(%s) = %v, want %v", tt.pidRanges, got, tt.want) + } else { + require.Equal(t, tt.want, got) + } + }) + } +} diff --git a/x/dclauth/handler_test.go b/x/dclauth/handler_test.go index a629ae96f..2b2f34c6d 100644 --- a/x/dclauth/handler_test.go +++ b/x/dclauth/handler_test.go @@ -356,6 +356,7 @@ func TestHandler_ProposeAddAccount_ForExistingActiveAccount(t *testing.T) { pubKey, types.AccountRoles{types.Vendor}, testconstants.VendorID1, + testconstants.ProductIDsEmpty, testconstants.Info, ) require.NoError(t, err) @@ -385,6 +386,7 @@ func TestHandler_ProposeAddAccount_ForExistingPendingAccount(t *testing.T) { pubKey, types.AccountRoles{types.Vendor}, testconstants.VendorID1, + testconstants.ProductIDsEmpty, testconstants.Info, ) require.NoError(t, err) @@ -862,6 +864,7 @@ func TestHandler_ProposeAddAccount_VendorIDNotRequiredForNonVendorAccounts(t *te pubKey, types.AccountRoles{types.Trustee}, 0, + testconstants.ProductIDsEmpty, testconstants.Info, ) require.NoError(t, err) @@ -875,6 +878,7 @@ func TestHandler_ProposeAddAccount_VendorIDNotRequiredForNonVendorAccounts(t *te pubKey, types.AccountRoles{types.CertificationCenter}, 0, + testconstants.ProductIDsEmpty, testconstants.Info, ) require.NoError(t, err) @@ -893,6 +897,7 @@ func TestHandler_ProposeAddAccount_VendorIDRequiredForVendorAccounts(t *testing. pubKey, types.AccountRoles{types.Vendor}, 0, + testconstants.ProductIDsEmpty, testconstants.Info, ) require.NoError(t, err) @@ -1264,6 +1269,60 @@ func TestHandler_CreateVendorAccount_OneApprovalIsNeeded(t *testing.T) { } } +func TestHandler_CreateVendorAccount_WithProductIds(t *testing.T) { + setup := Setup(t) + + // store 4 trustees + trustee1 := storeTrustee(setup) + trustee2 := storeTrustee(setup) + trustee3 := storeTrustee(setup) + _ = storeTrustee(setup) + + require.Equal(t, 3, setup.Keeper.AccountApprovalsCount(setup.Ctx, types.AccountApprovalsPercent)) + + // trustee1 propose account + _, pubKey, address := testdata.KeyTestPubAddr() + proposeAddAccount, _ := types.NewMsgProposeAddAccount( + trustee1, + address, + pubKey, + types.AccountRoles{types.VendorAdmin}, + testconstants.VendorID1, + testconstants.ProductIDs200, + testconstants.Info, + ) + _, err := setup.Handler(setup.Ctx, proposeAddAccount) + require.NoError(t, err) + + // trustee2 approves account + approveAddAccount := types.NewMsgApproveAddAccount(trustee2, address, testconstants.Info2) + _, err = setup.Handler(setup.Ctx, approveAddAccount) + require.NoError(t, err) + + // ensure no active account created + require.False(t, setup.Keeper.IsAccountPresent(setup.Ctx, address)) + + // trustee3 approves account + approveAddAccount = types.NewMsgApproveAddAccount(trustee3, address, testconstants.Info3) + _, err = setup.Handler(setup.Ctx, approveAddAccount) + require.NoError(t, err) + + // active account must be created + account := setup.Keeper.GetAccount(setup.Ctx, address) + require.Equal(t, address, account.GetAddress()) + require.Equal(t, pubKey, account.GetPubKey()) + + // check for info field and approvals + dclAccount, _ := setup.Keeper.GetAccountO(setup.Ctx, address) + require.Equal(t, proposeAddAccount.ProductIDs, dclAccount.ProductIDs) + + // ensure pending account removed + require.False(t, setup.Keeper.IsPendingAccountPresent(setup.Ctx, address)) + + // check that account revoked from entity RevokedAccount + require.False(t, setup.Keeper.IsRevokedAccountPresent(setup.Ctx, address)) +} + func TestHandler_CreateVendorAccount_TwoApprovalsAreNeeded(t *testing.T) { setup := Setup(t) @@ -1761,7 +1820,7 @@ func storeTrustee(setup TestSetup) sdk.AccAddress { func storeAccountWithVendorID(setup TestSetup, role types.AccountRole, vendorID int32) sdk.AccAddress { _, pubKey, address := testdata.KeyTestPubAddr() ba := authtypes.NewBaseAccount(address, pubKey, 0, 0) - account := types.NewAccount(ba, types.AccountRoles{role}, nil, nil, vendorID) + account := types.NewAccount(ba, types.AccountRoles{role}, nil, nil, vendorID, testconstants.ProductIDsEmpty) account.AccountNumber = setup.Keeper.GetNextAccountNumber(setup.Ctx) setup.Keeper.SetAccount(setup.Ctx, account) @@ -1776,6 +1835,7 @@ func proposeAddAccount(setup TestSetup, signer sdk.AccAddress, roles types.Accou pubKey, roles, testconstants.VendorID1, + testconstants.ProductIDsEmpty, testconstants.Info, ) // TODO check the err here diff --git a/x/dclauth/keeper/account.go b/x/dclauth/keeper/account.go index 81ae1c934..0c040764e 100644 --- a/x/dclauth/keeper/account.go +++ b/x/dclauth/keeper/account.go @@ -4,6 +4,7 @@ import ( "github.com/cosmos/cosmos-sdk/store/prefix" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" ) @@ -30,7 +31,7 @@ func (k Keeper) SetAccount(ctx sdk.Context, account authtypes.AccountI) { dclAcc.GetAddress(), dclAcc.GetPubKey(), dclAcc.GetAccountNumber(), dclAcc.GetSequence(), ) - dclAccO := types.NewAccount(ba, dclAcc.GetRoles(), dclAcc.GetApprovals(), dclAcc.GetRejects(), dclAcc.GetVendorID()) + dclAccO := types.NewAccount(ba, dclAcc.GetRoles(), dclAcc.GetApprovals(), dclAcc.GetRejects(), dclAcc.GetVendorID(), dclAcc.GetProductIDs()) k.SetAccountO(ctx, *dclAccO) } @@ -143,6 +144,16 @@ func (k Keeper) HasVendorID(ctx sdk.Context, addr sdk.AccAddress, vid int32) boo return false } +func (k Keeper) HasRightsToChange(ctx sdk.Context, addr sdk.AccAddress, pid int32) bool { + account, found := k.GetAccountO(ctx, addr) + + if !found { + return false + } + + return account.HasRightsToChange(pid) +} + // Count account with assigned role. func (k Keeper) CountAccountsWithRole(ctx sdk.Context, roleToCount types.AccountRole) int { res := 0 diff --git a/x/dclauth/keeper/msg_server_approve_add_account.go b/x/dclauth/keeper/msg_server_approve_add_account.go index 21d0f20d2..01812e58f 100644 --- a/x/dclauth/keeper/msg_server_approve_add_account.go +++ b/x/dclauth/keeper/msg_server_approve_add_account.go @@ -80,7 +80,7 @@ func (k msgServer) ApproveAddAccount( // create approved account, assign account number and store it // TODO issue 99: create a separate instance of BaseAccount with // AccountNumber and Sequence set to zero - account := types.NewAccount(pendAcc.BaseAccount, pendAcc.Roles, pendAcc.Approvals, pendAcc.Rejects, pendAcc.VendorID) + account := types.NewAccount(pendAcc.BaseAccount, pendAcc.Roles, pendAcc.Approvals, pendAcc.Rejects, pendAcc.VendorID, pendAcc.ProductIDs) err = account.SetAccountNumber(k.GetNextAccountNumber(ctx)) if err != nil { return nil, err diff --git a/x/dclauth/keeper/msg_server_propose_add_account.go b/x/dclauth/keeper/msg_server_propose_add_account.go index 53833995f..b54a19a18 100644 --- a/x/dclauth/keeper/msg_server_propose_add_account.go +++ b/x/dclauth/keeper/msg_server_propose_add_account.go @@ -54,7 +54,7 @@ func (k msgServer) ProposeAddAccount(goCtx context.Context, msg *types.MsgPropos } ba := authtypes.NewBaseAccount(accAddr, pk, 0, 0) - account := types.NewAccount(ba, msg.Roles, nil, nil, msg.VendorID) + account := types.NewAccount(ba, msg.Roles, nil, nil, msg.VendorID, msg.ProductIDs) var percent float64 if account.HasOnlyVendorRole(types.Vendor) { diff --git a/x/dclauth/keeper/msg_server_reject_add_account.go b/x/dclauth/keeper/msg_server_reject_add_account.go index 2f188e173..94ecb840e 100644 --- a/x/dclauth/keeper/msg_server_reject_add_account.go +++ b/x/dclauth/keeper/msg_server_reject_add_account.go @@ -84,7 +84,7 @@ func (k msgServer) RejectAddAccount( // check if pending account has enough reject approvals if len(pendAcc.Rejects) >= k.AccountRejectApprovalsCount(ctx, percent) { - account := types.NewAccount(pendAcc.BaseAccount, pendAcc.Roles, pendAcc.Approvals, pendAcc.Rejects, pendAcc.VendorID) + account := types.NewAccount(pendAcc.BaseAccount, pendAcc.Roles, pendAcc.Approvals, pendAcc.Rejects, pendAcc.VendorID, pendAcc.ProductIDs) err = account.SetAccountNumber(k.GetNextAccountNumber(ctx)) if err != nil { return nil, err diff --git a/x/dclauth/types/account.go b/x/dclauth/types/account.go index c0614add6..2ee1693a8 100644 --- a/x/dclauth/types/account.go +++ b/x/dclauth/types/account.go @@ -20,6 +20,8 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) /* @@ -65,16 +67,18 @@ type DCLAccountI interface { GetVendorID() int32 GetApprovals() []*Grant GetRejects() []*Grant + GetProductIDs() []*types.Uint16Range } // NewAccount creates a new Account object. -func NewAccount(ba *authtypes.BaseAccount, roles AccountRoles, approvals []*Grant, rejects []*Grant, vendorID int32) *Account { +func NewAccount(ba *authtypes.BaseAccount, roles AccountRoles, approvals []*Grant, rejects []*Grant, vendorID int32, productIDs []*types.Uint16Range) *Account { return &Account{ BaseAccount: ba, Roles: roles, Approvals: approvals, Rejects: rejects, VendorID: vendorID, + ProductIDs: productIDs, } } @@ -111,6 +115,10 @@ func (acc Account) GetRejects() []*Grant { return acc.Rejects } +func (acc Account) GetProductIDs() []*types.Uint16Range { + return acc.ProductIDs +} + func (acc Account) GetVendorID() int32 { return acc.VendorID } @@ -133,6 +141,21 @@ func (acc Account) HasOnlyVendorRole(targetRole AccountRole) bool { return false } +func (acc Account) HasRightsToChange(productID int32) bool { + // Account is not associated with any products + if len(acc.ProductIDs) == 0 { + return true + } + + for _, productRange := range acc.ProductIDs { + if (productRange.Min <= productID) && (productID <= productRange.Max) { + return true + } + } + + return false +} + func (acc Account) String() string { out, _ := acc.MarshalYAML() diff --git a/x/dclauth/types/account.pb.go b/x/dclauth/types/account.pb.go index b82f43391..168ce01b3 100644 --- a/x/dclauth/types/account.pb.go +++ b/x/dclauth/types/account.pb.go @@ -11,6 +11,8 @@ import ( io "io" math "math" math_bits "math/bits" + + types1 "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) // Reference imports to suppress errors if they are not otherwise used. @@ -29,10 +31,11 @@ type Account struct { // NOTE. we do not user AccountRoles casting here to preserve repeated form // so protobuf takes care about repeated items in generated code, // (but that might be not the final solution) - Roles []AccountRole `protobuf:"bytes,2,rep,name=roles,proto3,casttype=AccountRole" json:"roles,omitempty"` - Approvals []*Grant `protobuf:"bytes,3,rep,name=approvals,proto3" json:"approvals,omitempty"` - VendorID int32 `protobuf:"varint,4,opt,name=vendorID,proto3" json:"vendorID,omitempty"` - Rejects []*Grant `protobuf:"bytes,5,rep,name=rejects,proto3" json:"rejects,omitempty"` + Roles []AccountRole `protobuf:"bytes,2,rep,name=roles,proto3,casttype=AccountRole" json:"roles,omitempty"` + Approvals []*Grant `protobuf:"bytes,3,rep,name=approvals,proto3" json:"approvals,omitempty"` + VendorID int32 `protobuf:"varint,4,opt,name=vendorID,proto3" json:"vendorID,omitempty"` + Rejects []*Grant `protobuf:"bytes,5,rep,name=rejects,proto3" json:"rejects,omitempty"` + ProductIDs []*types1.Uint16Range `protobuf:"bytes,6,rep,name=productIDs,proto3" json:"productIDs,omitempty"` } func (m *Account) Reset() { *m = Account{} } @@ -74,30 +77,33 @@ func init() { func init() { proto.RegisterFile("dclauth/account.proto", fileDescriptor_3a2d3e1e8208016c) } var fileDescriptor_3a2d3e1e8208016c = []byte{ - // 362 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x91, 0xcf, 0x4a, 0xeb, 0x40, - 0x14, 0x87, 0x93, 0xfe, 0xb9, 0x6d, 0x93, 0x0b, 0x17, 0x72, 0x15, 0x42, 0x17, 0x49, 0x10, 0x84, - 0x6c, 0x3a, 0xa1, 0x75, 0xa5, 0x3b, 0x83, 0xa0, 0xdd, 0xc6, 0x85, 0xe0, 0x46, 0x66, 0x26, 0x87, - 0x34, 0x92, 0x76, 0xc2, 0xcc, 0xa4, 0xa8, 0x4f, 0xe0, 0xd2, 0xa5, 0xcb, 0x3e, 0x8e, 0x3b, 0xbb, - 0x74, 0x55, 0xa4, 0x7d, 0x0b, 0x57, 0xd2, 0x4c, 0x62, 0xdd, 0x8a, 0xbb, 0x9c, 0x73, 0x38, 0xdf, - 0xf7, 0xcb, 0x1c, 0x63, 0x3f, 0xa6, 0x19, 0x2e, 0xe4, 0x24, 0xc0, 0x94, 0xb2, 0x62, 0x26, 0x51, - 0xce, 0x99, 0x64, 0xd6, 0xe8, 0x21, 0x4d, 0x08, 0x00, 0xce, 0xb2, 0x14, 0xcf, 0x28, 0xa0, 0x38, - 0x15, 0x92, 0xa7, 0xa4, 0x90, 0x10, 0x53, 0x36, 0xcd, 0x55, 0x37, 0x83, 0x38, 0x01, 0x8e, 0x2a, - 0x42, 0x7f, 0x2f, 0x61, 0x09, 0x2b, 0xd7, 0x83, 0xed, 0x97, 0x22, 0xf5, 0x1d, 0xca, 0xc4, 0x94, - 0x89, 0xa0, 0x94, 0xcc, 0x87, 0x04, 0x24, 0x1e, 0x96, 0x45, 0x35, 0xff, 0x5f, 0x07, 0x48, 0x38, - 0xae, 0xf5, 0x07, 0xaf, 0x0d, 0xa3, 0x73, 0xaa, 0x02, 0x59, 0x63, 0xe3, 0x2f, 0xc1, 0x02, 0x6e, - 0xaa, 0x80, 0xb6, 0xee, 0xe9, 0xbe, 0x39, 0xf2, 0x90, 0xe2, 0xa2, 0x12, 0x55, 0x71, 0x51, 0x88, - 0x05, 0x54, 0x7b, 0x61, 0x6b, 0xb9, 0x72, 0xf5, 0xc8, 0x24, 0xbb, 0x96, 0x75, 0x68, 0xb4, 0x39, - 0xcb, 0x40, 0xd8, 0x0d, 0xaf, 0xe9, 0xf7, 0xc2, 0x7f, 0x1f, 0x2b, 0xd7, 0xac, 0x66, 0x11, 0xcb, - 0x20, 0x52, 0x53, 0xeb, 0xca, 0xe8, 0xe1, 0x3c, 0xe7, 0x6c, 0x8e, 0x33, 0x61, 0x37, 0xbd, 0xa6, - 0x6f, 0x8e, 0x8e, 0xd1, 0xcf, 0x1f, 0x04, 0x9d, 0x6f, 0xff, 0x28, 0xda, 0xb1, 0xac, 0xbe, 0xd1, - 0x9d, 0xc3, 0x2c, 0x66, 0x7c, 0x7c, 0x66, 0xb7, 0x3c, 0xdd, 0x6f, 0x47, 0x5f, 0xb5, 0x75, 0x69, - 0x74, 0x38, 0xdc, 0x02, 0x95, 0xc2, 0x6e, 0xff, 0x56, 0x59, 0x93, 0x4e, 0xba, 0x8f, 0x0b, 0x57, - 0x7b, 0x5e, 0xb8, 0x5a, 0x48, 0x5e, 0xd6, 0x8e, 0xbe, 0x5c, 0x3b, 0xfa, 0xfb, 0xda, 0xd1, 0x9f, - 0x36, 0x8e, 0xb6, 0xdc, 0x38, 0xda, 0xdb, 0xc6, 0xd1, 0xae, 0x2f, 0x92, 0x54, 0x4e, 0x0a, 0x82, - 0x28, 0x9b, 0x06, 0xca, 0x38, 0xa8, 0x95, 0xc1, 0x37, 0xe5, 0x60, 0xe7, 0x1c, 0x28, 0x69, 0x70, - 0x17, 0xd4, 0xb7, 0x93, 0xf7, 0x39, 0x08, 0xf2, 0xa7, 0x3c, 0xde, 0xd1, 0x67, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x69, 0xd1, 0x8b, 0x9f, 0x54, 0x02, 0x00, 0x00, + // 412 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x92, 0xcf, 0x8a, 0xd4, 0x30, + 0x1c, 0xc7, 0x5b, 0xbb, 0xb3, 0x7f, 0x52, 0x41, 0xa8, 0x0a, 0x75, 0x0e, 0x6d, 0x11, 0x84, 0x5e, + 0x26, 0x61, 0x46, 0x10, 0xf4, 0x20, 0x58, 0x16, 0x74, 0xae, 0x15, 0x11, 0x3c, 0xb8, 0x24, 0xe9, + 0x8f, 0x6e, 0xa5, 0x6d, 0x4a, 0x92, 0x0e, 0xea, 0x13, 0x78, 0xf4, 0xe8, 0x71, 0xdf, 0xc0, 0xd7, + 0xf0, 0x38, 0x47, 0x4f, 0x83, 0xcc, 0xbc, 0x85, 0x27, 0x69, 0xd3, 0x3a, 0x73, 0x1d, 0xf6, 0xd6, + 0xe4, 0x4b, 0x3e, 0x9f, 0x6f, 0xf3, 0x0b, 0x7a, 0x98, 0xf1, 0x92, 0xb6, 0xfa, 0x9a, 0x50, 0xce, + 0x45, 0x5b, 0x6b, 0xdc, 0x48, 0xa1, 0x85, 0xb7, 0xf8, 0x5a, 0xe4, 0x0c, 0x80, 0x96, 0x65, 0x41, + 0x6b, 0x0e, 0x38, 0x2b, 0x94, 0x96, 0x05, 0x6b, 0x35, 0x64, 0x5c, 0x54, 0x8d, 0xd9, 0x2d, 0x21, + 0xcb, 0x41, 0xe2, 0x81, 0x30, 0x7d, 0x90, 0x8b, 0x5c, 0xf4, 0xc7, 0x49, 0xf7, 0x65, 0x48, 0xd3, + 0x80, 0x0b, 0x55, 0x09, 0x45, 0x7a, 0xc9, 0x6a, 0xce, 0x40, 0xd3, 0x79, 0xbf, 0x18, 0xf2, 0x47, + 0x5c, 0x54, 0x95, 0xa8, 0x49, 0x5b, 0xd4, 0x7a, 0xfe, 0xec, 0x4a, 0xd2, 0x3a, 0x87, 0x21, 0xba, + 0x3f, 0x76, 0xcb, 0x25, 0x1d, 0x9b, 0x3d, 0xfe, 0xe9, 0xa0, 0xb3, 0x57, 0xa6, 0xab, 0xb7, 0x44, + 0x77, 0x19, 0x55, 0x70, 0x35, 0x74, 0xf7, 0xed, 0xc8, 0x8e, 0xdd, 0x45, 0x84, 0x8d, 0x12, 0xf7, + 0x96, 0x41, 0x89, 0x13, 0xaa, 0x60, 0x38, 0x97, 0x9c, 0xac, 0x37, 0xa1, 0x9d, 0xba, 0x6c, 0xbf, + 0xe5, 0x3d, 0x41, 0x13, 0x29, 0x4a, 0x50, 0xfe, 0x9d, 0xc8, 0x89, 0x2f, 0x92, 0x7b, 0x7f, 0x37, + 0xa1, 0x3b, 0x64, 0xa9, 0x28, 0x21, 0x35, 0xa9, 0xf7, 0x1e, 0x5d, 0xd0, 0xa6, 0x91, 0x62, 0x45, + 0x4b, 0xe5, 0x3b, 0x91, 0x13, 0xbb, 0x8b, 0xe7, 0xf8, 0xf8, 0xbb, 0xc2, 0xaf, 0xbb, 0x3f, 0x4a, + 0xf7, 0x2c, 0x6f, 0x8a, 0xce, 0x57, 0x50, 0x67, 0x42, 0x2e, 0x2f, 0xfd, 0x93, 0xc8, 0x8e, 0x27, + 0xe9, 0xff, 0xb5, 0xf7, 0x16, 0x9d, 0x49, 0xf8, 0x04, 0x5c, 0x2b, 0x7f, 0x72, 0x5b, 0xe5, 0x48, + 0xf2, 0x3e, 0x22, 0xd4, 0x48, 0x91, 0xb5, 0x5c, 0x2f, 0x2f, 0x95, 0x7f, 0xda, 0x73, 0x5f, 0x1e, + 0xc3, 0x35, 0x73, 0xc3, 0xef, 0xfa, 0xb9, 0xa5, 0xdd, 0xd8, 0xd2, 0x03, 0xe2, 0x8b, 0xf3, 0x6f, + 0x37, 0xa1, 0xf5, 0xe3, 0x26, 0xb4, 0x12, 0xf6, 0x6b, 0x1b, 0xd8, 0xeb, 0x6d, 0x60, 0xff, 0xd9, + 0x06, 0xf6, 0xf7, 0x5d, 0x60, 0xad, 0x77, 0x81, 0xf5, 0x7b, 0x17, 0x58, 0x1f, 0xde, 0xe4, 0x85, + 0xbe, 0x6e, 0x59, 0x87, 0x22, 0xc6, 0x3c, 0x1b, 0xd5, 0xe4, 0x40, 0x3d, 0xdb, 0xbb, 0x67, 0x46, + 0x4e, 0x3e, 0x93, 0xf1, 0x6d, 0xe8, 0x2f, 0x0d, 0x28, 0x76, 0xda, 0x3f, 0x8e, 0xa7, 0xff, 0x02, + 0x00, 0x00, 0xff, 0xff, 0xf5, 0x78, 0x0b, 0x74, 0xcf, 0x02, 0x00, 0x00, } func (m *Account) Marshal() (dAtA []byte, err error) { @@ -120,6 +126,20 @@ func (m *Account) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ProductIDs) > 0 { + for iNdEx := len(m.ProductIDs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ProductIDs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintAccount(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x32 + } + } if len(m.Rejects) > 0 { for iNdEx := len(m.Rejects) - 1; iNdEx >= 0; iNdEx-- { { @@ -219,6 +239,12 @@ func (m *Account) Size() (n int) { n += 1 + l + sovAccount(uint64(l)) } } + if len(m.ProductIDs) > 0 { + for _, e := range m.ProductIDs { + l = e.Size() + n += 1 + l + sovAccount(uint64(l)) + } + } return n } @@ -412,6 +438,40 @@ func (m *Account) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 6: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProductIDs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowAccount + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthAccount + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthAccount + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProductIDs = append(m.ProductIDs, &types1.Uint16Range{}) + if err := m.ProductIDs[len(m.ProductIDs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipAccount(dAtA[iNdEx:]) diff --git a/x/dclauth/types/account_test.go b/x/dclauth/types/account_test.go index 03550fc65..4f4b33023 100644 --- a/x/dclauth/types/account_test.go +++ b/x/dclauth/types/account_test.go @@ -20,6 +20,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" types "github.com/cosmos/cosmos-sdk/x/auth/types" + commontypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) func TestAccountRole_Validate(t *testing.T) { @@ -64,11 +65,12 @@ func TestAccountRole_Validate(t *testing.T) { func TestNewAccount(t *testing.T) { type args struct { - ba *types.BaseAccount - roles AccountRoles - approvals []*Grant - rejects []*Grant - vendorID int32 + ba *types.BaseAccount + roles AccountRoles + approvals []*Grant + rejects []*Grant + vendorID int32 + productIDs []*commontypes.Uint16Range } tests := []struct { name string @@ -78,11 +80,12 @@ func TestNewAccount(t *testing.T) { { name: "valid account all roles", args: args{ - ba: &types.BaseAccount{}, - roles: []AccountRole{Vendor, CertificationCenter, Trustee, NodeAdmin}, - approvals: []*Grant{}, - rejects: []*Grant{}, - vendorID: 1, + ba: &types.BaseAccount{}, + roles: []AccountRole{Vendor, CertificationCenter, Trustee, NodeAdmin}, + approvals: []*Grant{}, + rejects: []*Grant{}, + vendorID: 1, + productIDs: []*commontypes.Uint16Range{}, }, want: &Account{ BaseAccount: &types.BaseAccount{}, @@ -90,16 +93,18 @@ func TestNewAccount(t *testing.T) { Approvals: []*Grant{}, Rejects: []*Grant{}, VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{}, }, }, { name: "invalid account vendor role", args: args{ - ba: &types.BaseAccount{}, - roles: []AccountRole{Vendor}, - approvals: []*Grant{}, - rejects: []*Grant{}, - vendorID: 2, + ba: &types.BaseAccount{}, + roles: []AccountRole{Vendor}, + approvals: []*Grant{}, + rejects: []*Grant{}, + vendorID: 2, + productIDs: []*commontypes.Uint16Range{}, }, want: &Account{ BaseAccount: &types.BaseAccount{}, @@ -107,13 +112,14 @@ func TestNewAccount(t *testing.T) { Approvals: []*Grant{}, Rejects: []*Grant{}, VendorID: 2, + ProductIDs: []*commontypes.Uint16Range{}, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := NewAccount(tt.args.ba, tt.args.roles, tt.args.approvals, tt.args.rejects, tt.args.vendorID); !reflect.DeepEqual(got, tt.want) { + if got := NewAccount(tt.args.ba, tt.args.roles, tt.args.approvals, tt.args.rejects, tt.args.vendorID, []*commontypes.Uint16Range{}); !reflect.DeepEqual(got, tt.want) { t.Errorf("NewAccount() = %v, want %v", got, tt.want) } }) @@ -347,6 +353,110 @@ func TestAccount_HasRole(t *testing.T) { } } +func TestAccount_HasRightsToChange(t *testing.T) { + type fields struct { + BaseAccount *types.BaseAccount + Roles []AccountRole + Approvals []*Grant + VendorID int32 + ProductIDs []*commontypes.Uint16Range + } + type args struct { + pid int32 + } + tests := []struct { + name string + fields fields + args args + want bool + }{ + { + name: "Account with associated ProductIDs: [1-100], wants to modify product with pid=1", + fields: fields{ + BaseAccount: &types.BaseAccount{}, + Roles: []AccountRole{Vendor, Trustee}, + Approvals: []*Grant{}, + VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{{Min: 1, Max: 100}}, + }, + args: args{ + pid: 1, + }, + want: true, + }, + { + name: "Account with associated ProductIDs: [1-100,200-300], wants to modify product with pid=300", + fields: fields{ + BaseAccount: &types.BaseAccount{}, + Roles: []AccountRole{Vendor, Trustee, NodeAdmin}, + Approvals: []*Grant{}, + VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{{Min: 1, Max: 100}, {Min: 200, Max: 300}}, + }, + args: args{ + pid: 300, + }, + want: true, + }, + { + name: "Account with associated ProductIDs: [100-100], wants to modify product with pid=100", + fields: fields{ + BaseAccount: &types.BaseAccount{}, + Roles: []AccountRole{Vendor, Trustee, NodeAdmin}, + Approvals: []*Grant{}, + VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{{Min: 100, Max: 100}}, + }, + args: args{ + pid: 100, + }, + want: true, + }, + { + name: "Account without associated ProductIDs: [1-100], wants to modify product with pid=101", + fields: fields{ + BaseAccount: &types.BaseAccount{}, + Roles: []AccountRole{Vendor, Trustee, NodeAdmin}, + Approvals: []*Grant{}, + VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{{Min: 1, Max: 100}}, + }, + args: args{ + pid: 101, + }, + want: false, + }, + { + name: "Account without associated ProductIDs: [100-100], wants to modify product with pid=99", + fields: fields{ + BaseAccount: &types.BaseAccount{}, + Roles: []AccountRole{Vendor, Trustee, NodeAdmin}, + Approvals: []*Grant{}, + VendorID: 1, + ProductIDs: []*commontypes.Uint16Range{{Min: 100, Max: 100}}, + }, + args: args{ + pid: 99, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + acc := Account{ + BaseAccount: tt.fields.BaseAccount, + Roles: tt.fields.Roles, + Approvals: tt.fields.Approvals, + VendorID: tt.fields.VendorID, + ProductIDs: tt.fields.ProductIDs, + } + if got := acc.HasRightsToChange(tt.args.pid); got != tt.want { + t.Errorf("Account.HasRightsToChange() = %v, want %v", got, tt.want) + } + }) + } +} + func TestPendingAccount_HasApprovalFrom(t *testing.T) { type fields struct { Account *Account diff --git a/x/dclauth/types/message_propose_add_account.go b/x/dclauth/types/message_propose_add_account.go index 874b039ae..6f999921b 100644 --- a/x/dclauth/types/message_propose_add_account.go +++ b/x/dclauth/types/message_propose_add_account.go @@ -2,6 +2,7 @@ package types import ( "bytes" + "fmt" "time" codectypes "github.com/cosmos/cosmos-sdk/codec/types" @@ -9,6 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/zigbee-alliance/distributed-compliance-ledger/utils/validator" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) const TypeMsgProposeAddAccount = "propose_add_account" @@ -22,6 +24,7 @@ func NewMsgProposeAddAccount( roles AccountRoles, // roles []string, vendorID int32, + productIDs []*types.Uint16Range, info string, ) (*MsgProposeAddAccount, error) { var pkAny *codectypes.Any @@ -33,13 +36,14 @@ func NewMsgProposeAddAccount( } return &MsgProposeAddAccount{ - Signer: signer.String(), - Address: address.String(), - PubKey: pkAny, - Roles: roles, - VendorID: vendorID, - Info: info, - Time: time.Now().Unix(), + Signer: signer.String(), + Address: address.String(), + PubKey: pkAny, + Roles: roles, + VendorID: vendorID, + ProductIDs: productIDs, + Info: info, + Time: time.Now().Unix(), }, nil } @@ -61,6 +65,21 @@ func (msg *MsgProposeAddAccount) HasRole(targetRole AccountRole) bool { return false } +func (msg *MsgProposeAddAccount) HasValidProductIDs() error { + var lastMax int32 + for _, productRange := range msg.ProductIDs { + if productRange.Min > productRange.Max { + return fmt.Errorf("Uint16Range.Max should be greater or equal to Uint16Range.Max: min=%d, max=%d", productRange.Min, productRange.Max) + } + if productRange.Max <= lastMax || productRange.Min <= lastMax { + return fmt.Errorf("range items should not overlap") + } + lastMax = productRange.Max + } + + return nil +} + func (msg *MsgProposeAddAccount) GetSigners() []sdk.AccAddress { signer, err := sdk.AccAddressFromBech32(msg.Signer) if err != nil { @@ -123,6 +142,11 @@ func (msg *MsgProposeAddAccount) ValidateBasic() error { return ErrMissingVendorIDForVendorAccount() } + err = msg.HasValidProductIDs() + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidRequest, "Invalid ProductID ranges are provided: %s", err) + } + err = validator.Validate(msg) if err != nil { return err diff --git a/x/dclauth/types/message_propose_add_account_test.go b/x/dclauth/types/message_propose_add_account_test.go index 2bde74cb0..296426ebd 100644 --- a/x/dclauth/types/message_propose_add_account_test.go +++ b/x/dclauth/types/message_propose_add_account_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/require" testconstants "github.com/zigbee-alliance/distributed-compliance-ledger/integration_tests/constants" validator "github.com/zigbee-alliance/distributed-compliance-ledger/utils/validator" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" ) func NewMsgProposeAddAccountWrapper( @@ -20,9 +21,10 @@ func NewMsgProposeAddAccountWrapper( pubKey cryptotypes.PubKey, roles AccountRoles, vendorID int32, + productIDs []*types.Uint16Range, ) *MsgProposeAddAccount { t.Helper() - msg, err := NewMsgProposeAddAccount(signer, address, pubKey, roles, vendorID, testconstants.Info) + msg, err := NewMsgProposeAddAccount(signer, address, pubKey, roles, vendorID, productIDs, testconstants.Info) require.NoError(t, err) return msg @@ -33,7 +35,7 @@ func TestNewMsgProposeAddAccount(t *testing.T) { t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{}, testconstants.VendorID1, + AccountRoles{}, testconstants.VendorID1, testconstants.ProductIDsEmpty, ) require.Equal(t, msg.Route(), RouterKey) @@ -49,23 +51,33 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: true, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{NodeAdmin}, 1), + AccountRoles{NodeAdmin}, 1, []*types.Uint16Range{{Min: 1, Max: 1000}}), }, { valid: true, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1), + AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1, []*types.Uint16Range{{Min: 1, Max: 65535}}), + }, + { + valid: true, + msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, + AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1, testconstants.ProductIDsEmpty), }, // zero VID without Vendor role - no error { valid: true, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{NodeAdmin}, 0), + AccountRoles{NodeAdmin}, 0, []*types.Uint16Range{{Min: 1, Max: 2}}), + }, + { + valid: true, + msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, + AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1, []*types.Uint16Range{{Min: 1, Max: 1}}), }, { valid: true, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1), + AccountRoles{Vendor, NodeAdmin}, testconstants.VendorID1, []*types.Uint16Range{{Min: 1, Max: 1}, {Min: 2, Max: 2}}), }, } @@ -77,7 +89,7 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{}, 1), // no roles provided + AccountRoles{}, 1, testconstants.ProductIDsEmpty), // no roles provided err: sdkerrors.Wrapf(MissingRoles, "No roles provided"), }, @@ -85,7 +97,7 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{Vendor, NodeAdmin}, 0), + AccountRoles{Vendor, NodeAdmin}, 0, testconstants.ProductIDsEmpty), err: sdkerrors.Wrapf(MissingVendorIDForVendorAccount, "No Vendor ID is provided in the Vendor Role for the new account"), }, @@ -93,7 +105,7 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{Vendor, NodeAdmin}, -1), + AccountRoles{Vendor, NodeAdmin}, -1, testconstants.ProductIDsEmpty), err: sdkerrors.Wrapf(MissingVendorIDForVendorAccount, "No Vendor ID is provided in the Vendor Role for the new account"), }, @@ -101,13 +113,13 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{Vendor, NodeAdmin}, 65535+1), + AccountRoles{Vendor, NodeAdmin}, 65535+1, testconstants.ProductIDsEmpty), err: validator.ErrFieldUpperBoundViolated, }, { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, nil, testconstants.PubKey1, - AccountRoles{NodeAdmin}, 1), + AccountRoles{NodeAdmin}, 1, testconstants.ProductIDsEmpty), err: sdkerrors.ErrInvalidAddress, }, // { @@ -119,15 +131,33 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { { valid: false, msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, - AccountRoles{"Wrong Role"}, 1), + AccountRoles{"Wrong Role"}, 1, testconstants.ProductIDsEmpty), err: sdkerrors.ErrUnknownRequest, }, { valid: false, msg: NewMsgProposeAddAccountWrapper(t, nil, testconstants.Address1, testconstants.PubKey1, - AccountRoles{NodeAdmin}, 1), + AccountRoles{NodeAdmin}, 1, testconstants.ProductIDsEmpty), err: sdkerrors.ErrInvalidAddress, }, + { + valid: false, + msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, + AccountRoles{Vendor}, 1, []*types.Uint16Range{{Min: 1, Max: 200}, {Min: 101, Max: 200}}), + err: sdkerrors.ErrInvalidRequest, + }, + { + valid: false, + msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, + AccountRoles{Vendor}, 1, []*types.Uint16Range{{Min: 10, Max: 100}, {Min: 100, Max: 200}}), + err: sdkerrors.ErrInvalidRequest, + }, + { + valid: false, + msg: NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address1, testconstants.PubKey1, + AccountRoles{Vendor}, 1, []*types.Uint16Range{{Min: 100, Max: 1}}), + err: sdkerrors.ErrInvalidRequest, + }, } for _, tt := range positiveTests { @@ -154,10 +184,10 @@ func TestValidateMsgProposeAddAccount(t *testing.T) { func TestMsgProposeAddAccountGetSignBytes(t *testing.T) { msg := NewMsgProposeAddAccountWrapper(t, testconstants.Signer, testconstants.Address2, testconstants.PubKey2, - AccountRoles{}, testconstants.VendorID1) - transcationTime := msg.Time - expected := fmt.Sprintf(`{"address":"cosmos1nl4uaesk9gtu7su3n89lne6xpa6lq8gljn79rq","info":"Information for Proposal/Approval/Revoke","pubKey":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A2wJ7uOEE5Zm04K52czFTXfDj1qF2mholzi1zOJVlKlr"},"roles":[],"signer":"cosmos1s5xf3aanx7w84hgplk9z3l90qfpantg6nsmhpf","time":"%v","vendorID":1000}`, - transcationTime) + AccountRoles{}, testconstants.VendorID1, testconstants.ProductIDsEmpty) + transactionTime := msg.Time + expected := fmt.Sprintf(`{"address":"cosmos1nl4uaesk9gtu7su3n89lne6xpa6lq8gljn79rq","info":"Information for Proposal/Approval/Revoke","productIDs":[],"pubKey":{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"A2wJ7uOEE5Zm04K52czFTXfDj1qF2mholzi1zOJVlKlr"},"roles":[],"signer":"cosmos1s5xf3aanx7w84hgplk9z3l90qfpantg6nsmhpf","time":"%v","vendorID":1000}`, + transactionTime) require.Equal(t, expected, string(msg.GetSignBytes())) } diff --git a/x/dclauth/types/tx.pb.go b/x/dclauth/types/tx.pb.go index a81a92306..f6f75c2ac 100644 --- a/x/dclauth/types/tx.pb.go +++ b/x/dclauth/types/tx.pb.go @@ -11,6 +11,7 @@ import ( _ "github.com/gogo/protobuf/gogoproto" grpc1 "github.com/gogo/protobuf/grpc" proto "github.com/gogo/protobuf/proto" + types1 "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" @@ -31,13 +32,14 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgProposeAddAccount struct { - Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty" validate:"required"` - Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty" validate:"required"` - PubKey *types.Any `protobuf:"bytes,3,opt,name=pubKey,proto3" json:"pubKey,omitempty" validate:"required"` - Roles []AccountRole `protobuf:"bytes,4,rep,name=roles,proto3,casttype=AccountRole" json:"roles,omitempty" validate:"required"` - VendorID int32 `protobuf:"varint,5,opt,name=vendorID,proto3" json:"vendorID,omitempty" validate:"gte=0,lte=65535"` - Info string `protobuf:"bytes,6,opt,name=info,proto3" json:"info,omitempty" validate:"max=4096"` - Time int64 `protobuf:"varint,7,opt,name=time,proto3" json:"time,omitempty"` + Signer string `protobuf:"bytes,1,opt,name=signer,proto3" json:"signer,omitempty" validate:"required"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty" validate:"required"` + PubKey *types.Any `protobuf:"bytes,3,opt,name=pubKey,proto3" json:"pubKey,omitempty" validate:"required"` + Roles []AccountRole `protobuf:"bytes,4,rep,name=roles,proto3,casttype=AccountRole" json:"roles,omitempty" validate:"required"` + VendorID int32 `protobuf:"varint,5,opt,name=vendorID,proto3" json:"vendorID,omitempty" validate:"gte=0,lte=65535"` + Info string `protobuf:"bytes,6,opt,name=info,proto3" json:"info,omitempty" validate:"max=4096"` + Time int64 `protobuf:"varint,7,opt,name=time,proto3" json:"time,omitempty"` + ProductIDs []*types1.Uint16Range `protobuf:"bytes,8,rep,name=productIDs,proto3" json:"productIDs,omitempty"` } func (m *MsgProposeAddAccount) Reset() { *m = MsgProposeAddAccount{} } @@ -122,6 +124,13 @@ func (m *MsgProposeAddAccount) GetTime() int64 { return 0 } +func (m *MsgProposeAddAccount) GetProductIDs() []*types1.Uint16Range { + if m != nil { + return m.ProductIDs + } + return nil +} + type MsgProposeAddAccountResponse struct { } @@ -590,49 +599,52 @@ func init() { func init() { proto.RegisterFile("dclauth/tx.proto", fileDescriptor_ba91727cb044acc7) } var fileDescriptor_ba91727cb044acc7 = []byte{ - // 667 bytes of a gzipped FileDescriptorProto + // 720 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x96, 0x4f, 0x4f, 0x13, 0x4f, - 0x18, 0xc7, 0x99, 0x5f, 0x4b, 0xf9, 0x31, 0x5c, 0x70, 0x69, 0x64, 0xa9, 0xba, 0xad, 0x7b, 0x30, - 0x4d, 0xb4, 0xbb, 0x04, 0x84, 0x44, 0x22, 0x87, 0x36, 0x26, 0x40, 0x08, 0x91, 0x2c, 0x37, 0x13, - 0x63, 0xf6, 0xcf, 0xc3, 0xb0, 0xba, 0xdd, 0x59, 0x67, 0x66, 0x1b, 0xea, 0x2b, 0xf0, 0x64, 0x7c, - 0x21, 0x26, 0x5e, 0x3c, 0xf8, 0x02, 0x3c, 0x18, 0x4f, 0xc4, 0x93, 0x27, 0x62, 0xe0, 0x68, 0xe2, - 0x81, 0xa3, 0x27, 0xe3, 0xfe, 0x69, 0x69, 0xbb, 0x35, 0xa1, 0xf4, 0x60, 0xf4, 0x36, 0xdd, 0x99, - 0xe7, 0xfb, 0x7c, 0x9f, 0xcf, 0xe4, 0x79, 0x3a, 0x78, 0xd6, 0xb1, 0x3d, 0x33, 0x14, 0x07, 0xba, - 0x38, 0xd4, 0x02, 0x46, 0x05, 0x95, 0x96, 0x5e, 0xb8, 0xc4, 0x02, 0x30, 0x3d, 0xcf, 0x35, 0x7d, - 0x1b, 0x34, 0xc7, 0xe5, 0x82, 0xb9, 0x56, 0x28, 0xc0, 0xb1, 0x69, 0x33, 0x88, 0xbf, 0x7a, 0xe0, - 0x10, 0x60, 0x5a, 0x12, 0x5c, 0x5a, 0x20, 0x94, 0x12, 0x0f, 0xf4, 0x48, 0xc1, 0x0a, 0xf7, 0x75, - 0xd3, 0x6f, 0xc7, 0x72, 0xa5, 0x22, 0xa1, 0x84, 0x46, 0x4b, 0xfd, 0xd7, 0x2a, 0xf9, 0xba, 0x60, - 0x53, 0xde, 0xa4, 0xfc, 0x49, 0xbc, 0x11, 0xff, 0x88, 0xb7, 0xd4, 0x0f, 0x39, 0x5c, 0xdc, 0xe1, - 0x64, 0x97, 0xd1, 0x80, 0x72, 0xa8, 0x3b, 0x4e, 0xdd, 0xb6, 0x69, 0xe8, 0x0b, 0x69, 0x03, 0x17, - 0xb8, 0x4b, 0x7c, 0x60, 0x32, 0xaa, 0xa0, 0xea, 0x74, 0x43, 0x3f, 0x3b, 0x2e, 0xcf, 0xb5, 0x4c, - 0xcf, 0x75, 0x4c, 0x01, 0x6b, 0x2a, 0x83, 0xe7, 0xa1, 0xcb, 0xc0, 0x51, 0x3f, 0xbf, 0xab, 0x15, - 0x13, 0xc5, 0xba, 0xe3, 0x30, 0xe0, 0x7c, 0x4f, 0x30, 0xd7, 0x27, 0x46, 0x12, 0x2e, 0x6d, 0xe1, - 0x29, 0x33, 0xde, 0x90, 0xff, 0x1b, 0x4d, 0x29, 0x8d, 0x97, 0x1e, 0xe3, 0x42, 0x10, 0x5a, 0xdb, - 0xd0, 0x96, 0x73, 0x15, 0x54, 0x9d, 0x59, 0x2a, 0x6a, 0x31, 0x09, 0x2d, 0x25, 0xa1, 0xd5, 0xfd, - 0xf6, 0x50, 0xfd, 0x4f, 0x5d, 0x7d, 0x9b, 0xb5, 0x03, 0x41, 0xb5, 0xdd, 0x48, 0xcc, 0x48, 0x44, - 0xa5, 0xfb, 0x78, 0x92, 0x51, 0x0f, 0xb8, 0x9c, 0xaf, 0xe4, 0xaa, 0xd3, 0x8d, 0x5b, 0x43, 0x74, - 0x7e, 0x1c, 0x97, 0x67, 0x12, 0x4a, 0x06, 0xf5, 0xc0, 0x88, 0x83, 0xa4, 0x35, 0xfc, 0x7f, 0x0b, - 0x7c, 0x87, 0xb2, 0xad, 0x07, 0xf2, 0x64, 0x05, 0x55, 0x27, 0x1b, 0xca, 0xd9, 0x71, 0xb9, 0xd4, - 0x15, 0x20, 0x02, 0xd6, 0x17, 0xef, 0x78, 0x02, 0xd6, 0x57, 0x57, 0x56, 0x96, 0x57, 0x54, 0xa3, - 0x73, 0x5e, 0xba, 0x8d, 0xf3, 0xae, 0xbf, 0x4f, 0xe5, 0x42, 0x04, 0x68, 0xbe, 0x37, 0x71, 0xd3, - 0x3c, 0x5c, 0xbf, 0xbb, 0x78, 0x6f, 0x55, 0x35, 0xa2, 0x43, 0x92, 0x84, 0xf3, 0xc2, 0x6d, 0x82, - 0x3c, 0x55, 0x41, 0xd5, 0x9c, 0x11, 0xad, 0x55, 0x05, 0x5f, 0xcf, 0xba, 0x45, 0x03, 0x78, 0x40, - 0x7d, 0x0e, 0xea, 0x37, 0x14, 0x5d, 0x73, 0x3d, 0x08, 0x18, 0x6d, 0xfd, 0xe9, 0xd7, 0x9c, 0xd2, - 0xc8, 0x5d, 0x84, 0x46, 0x7e, 0x80, 0xc6, 0x40, 0xb1, 0x1d, 0x1a, 0xdf, 0x11, 0x9e, 0xef, 0xe2, - 0x32, 0xa0, 0x45, 0x9f, 0xc1, 0x5f, 0x0d, 0xe4, 0x26, 0x2e, 0x0f, 0xa9, 0xb7, 0x9f, 0x49, 0x02, - 0xed, 0x9f, 0x61, 0x92, 0x55, 0x6f, 0x87, 0xc9, 0x4b, 0x84, 0xe7, 0x76, 0x38, 0x31, 0xe0, 0x29, - 0xd8, 0xe2, 0x5c, 0xd3, 0x5c, 0xed, 0xe5, 0xd1, 0x29, 0x4f, 0xee, 0x2b, 0x6f, 0x8c, 0x6e, 0x6f, - 0xe0, 0x6b, 0x19, 0x4e, 0x52, 0xa7, 0x4b, 0xaf, 0xa6, 0x70, 0x6e, 0x87, 0x13, 0xe9, 0x2d, 0xc2, - 0x57, 0x06, 0x67, 0xf9, 0xa6, 0x76, 0xf1, 0x7f, 0x19, 0x2d, 0x6b, 0x9e, 0x94, 0x76, 0xc7, 0xa5, - 0x94, 0x3a, 0x8f, 0x1c, 0x0f, 0x8e, 0xa5, 0x51, 0x1d, 0x0f, 0x28, 0x8d, 0xec, 0x78, 0xe8, 0xf4, - 0x90, 0xde, 0x23, 0x5c, 0xcc, 0x1c, 0x1d, 0xdb, 0x97, 0x83, 0xd3, 0x23, 0x56, 0xda, 0x1b, 0xa3, - 0x58, 0x8f, 0xf5, 0xcc, 0x0e, 0xdf, 0xbe, 0x1c, 0xa5, 0xf1, 0x58, 0xff, 0x5d, 0x2f, 0x4a, 0x6f, - 0x10, 0x9e, 0x1d, 0x68, 0xc4, 0x8d, 0x11, 0x33, 0xf5, 0x0b, 0x95, 0x1e, 0x8e, 0x49, 0x28, 0xb5, - 0xdb, 0xb0, 0x3e, 0x9e, 0x28, 0xe8, 0xe8, 0x44, 0x41, 0x5f, 0x4f, 0x14, 0xf4, 0xfa, 0x54, 0x99, - 0x38, 0x3a, 0x55, 0x26, 0xbe, 0x9c, 0x2a, 0x13, 0x8f, 0x36, 0x89, 0x2b, 0x0e, 0x42, 0x4b, 0xb3, - 0x69, 0x53, 0x8f, 0x93, 0xd6, 0xd2, 0xac, 0xfa, 0xb9, 0xac, 0xb5, 0x6e, 0xda, 0x5a, 0x9c, 0x57, - 0x3f, 0xd4, 0x3b, 0xcf, 0xc7, 0x76, 0x00, 0xdc, 0x2a, 0x44, 0xcf, 0x9e, 0xe5, 0x9f, 0x01, 0x00, - 0x00, 0xff, 0xff, 0x81, 0xd6, 0xbd, 0x54, 0x56, 0x0a, 0x00, 0x00, + 0x18, 0xc7, 0x99, 0x5f, 0x4b, 0x81, 0xe1, 0xc2, 0x6f, 0x69, 0x64, 0xa9, 0xba, 0xad, 0x3d, 0x98, + 0x26, 0xda, 0x5d, 0x2c, 0x42, 0x22, 0x11, 0x93, 0x36, 0x24, 0x40, 0x08, 0x91, 0x2c, 0xf1, 0x62, + 0xa2, 0x64, 0xff, 0x3c, 0x0c, 0xab, 0xdb, 0x9d, 0x75, 0x66, 0xb6, 0xa1, 0xbe, 0x02, 0x4f, 0xc6, + 0x17, 0xe1, 0xd1, 0xc4, 0x8b, 0x07, 0x5f, 0x82, 0xf1, 0x44, 0x3c, 0x79, 0x22, 0x06, 0x8e, 0x26, + 0x1e, 0x38, 0x7a, 0x32, 0xec, 0x9f, 0x96, 0xd2, 0xd6, 0x84, 0xd2, 0x83, 0xd1, 0xdb, 0xec, 0xce, + 0xce, 0xf7, 0xfb, 0x7d, 0x3e, 0x79, 0x66, 0x66, 0xf1, 0x94, 0x6d, 0xb9, 0x46, 0x20, 0xf6, 0x34, + 0xb1, 0xaf, 0xfa, 0x8c, 0x0a, 0x2a, 0x55, 0x5e, 0x3a, 0xc4, 0x04, 0x30, 0x5c, 0xd7, 0x31, 0x3c, + 0x0b, 0x54, 0xdb, 0xe1, 0x82, 0x39, 0x66, 0x20, 0xc0, 0xb6, 0x68, 0xdd, 0x8f, 0xde, 0xba, 0x60, + 0x13, 0x60, 0x6a, 0xbc, 0x38, 0x37, 0x4b, 0x28, 0x25, 0x2e, 0x68, 0xa1, 0x82, 0x19, 0xec, 0x6a, + 0x86, 0xd7, 0x8c, 0xe4, 0x72, 0x59, 0x42, 0x09, 0x0d, 0x87, 0xda, 0xe9, 0x28, 0x7e, 0x3b, 0x6b, + 0x51, 0x5e, 0xa7, 0x7c, 0x27, 0x9a, 0x88, 0x1e, 0xda, 0x53, 0xf5, 0x3a, 0xf5, 0xb4, 0xc0, 0xf1, + 0xc4, 0x9d, 0xc5, 0x1d, 0x66, 0x78, 0x04, 0xa2, 0xa9, 0xe2, 0xdb, 0x34, 0xce, 0x6e, 0x72, 0xb2, + 0xc5, 0xa8, 0x4f, 0x39, 0x54, 0x6d, 0xbb, 0x6a, 0x59, 0x34, 0xf0, 0x84, 0xb4, 0x8a, 0x33, 0xdc, + 0x21, 0x1e, 0x30, 0x19, 0x15, 0x50, 0x69, 0xa2, 0xa6, 0x9d, 0x1c, 0xe6, 0xa7, 0x1b, 0x86, 0xeb, + 0xd8, 0x86, 0x80, 0xa5, 0x22, 0x83, 0x17, 0x81, 0xc3, 0xc0, 0x2e, 0x7e, 0xf9, 0x50, 0xce, 0xc6, + 0x66, 0x55, 0xdb, 0x66, 0xc0, 0xf9, 0xb6, 0x60, 0x8e, 0x47, 0xf4, 0x78, 0xb9, 0xb4, 0x8e, 0xc7, + 0x8c, 0x68, 0x42, 0xfe, 0x6f, 0x30, 0xa5, 0x64, 0xbd, 0xf4, 0x04, 0x67, 0xfc, 0xc0, 0xdc, 0x80, + 0xa6, 0x9c, 0x2a, 0xa0, 0xd2, 0x64, 0x25, 0xab, 0x46, 0x90, 0xd4, 0x04, 0x92, 0x5a, 0xf5, 0x9a, + 0x7d, 0xf5, 0x3f, 0xb7, 0xf5, 0x2d, 0xd6, 0xf4, 0x05, 0x55, 0xb7, 0x42, 0x31, 0x3d, 0x16, 0x95, + 0xee, 0xe3, 0x51, 0x46, 0x5d, 0xe0, 0x72, 0xba, 0x90, 0x2a, 0x4d, 0xd4, 0x6e, 0xf6, 0xd1, 0xf9, + 0x79, 0x98, 0x9f, 0x8c, 0x29, 0xe9, 0xd4, 0x05, 0x3d, 0x5a, 0x24, 0x2d, 0xe1, 0xf1, 0x06, 0x78, + 0x36, 0x65, 0xeb, 0x2b, 0xf2, 0x68, 0x01, 0x95, 0x46, 0x6b, 0xca, 0xc9, 0x61, 0x3e, 0xd7, 0x16, + 0x20, 0x02, 0x96, 0xe7, 0x6e, 0xbb, 0x02, 0x96, 0x17, 0x17, 0x16, 0xe6, 0x17, 0x8a, 0x7a, 0xeb, + 0x7b, 0xe9, 0x16, 0x4e, 0x3b, 0xde, 0x2e, 0x95, 0x33, 0x21, 0xa0, 0x99, 0x4e, 0xe3, 0xba, 0xb1, + 0xbf, 0x7c, 0x77, 0xee, 0xde, 0x62, 0x51, 0x0f, 0x3f, 0x92, 0x24, 0x9c, 0x16, 0x4e, 0x1d, 0xe4, + 0xb1, 0x02, 0x2a, 0xa5, 0xf4, 0x70, 0x2c, 0x3d, 0xc5, 0xd8, 0x67, 0xd4, 0x0e, 0x2c, 0xb1, 0xbe, + 0xc2, 0xe5, 0xf1, 0x42, 0xaa, 0x34, 0x59, 0x79, 0xa0, 0x5e, 0xa0, 0xed, 0xa2, 0x0e, 0x51, 0x1f, + 0x85, 0x1d, 0xa2, 0x9f, 0x36, 0x88, 0x7e, 0x46, 0xb1, 0xa8, 0xe0, 0x6b, 0xbd, 0xba, 0x44, 0x07, + 0xee, 0x53, 0x8f, 0x43, 0xf1, 0x3b, 0x0a, 0xdb, 0xa8, 0xea, 0xfb, 0x8c, 0x36, 0xfe, 0xf4, 0x36, + 0x4a, 0x68, 0xa7, 0x2e, 0x42, 0x3b, 0xdd, 0xa6, 0x1d, 0xd3, 0xe8, 0x2a, 0xb6, 0x45, 0xe3, 0x07, + 0xc2, 0x33, 0x6d, 0x5c, 0x3a, 0x34, 0xe8, 0x73, 0xf8, 0xab, 0x81, 0xdc, 0xc0, 0xf9, 0x3e, 0xf5, + 0x9e, 0x67, 0x12, 0x43, 0xfb, 0x67, 0x98, 0xf4, 0xaa, 0xb7, 0xc5, 0xe4, 0x15, 0xc2, 0xd3, 0x9b, + 0x9c, 0xe8, 0xf0, 0x0c, 0x2c, 0x71, 0x66, 0xd3, 0x5c, 0xe9, 0xe4, 0xd1, 0x2a, 0x4f, 0x3e, 0x57, + 0xde, 0x10, 0xd3, 0x5e, 0xc7, 0x57, 0x7b, 0x24, 0x49, 0x92, 0x56, 0x5e, 0x8f, 0xe1, 0xd4, 0x26, + 0x27, 0xd2, 0x7b, 0x84, 0xff, 0xef, 0xbe, 0x2b, 0xd6, 0xd4, 0x8b, 0x5f, 0x70, 0x6a, 0xaf, 0xf3, + 0x24, 0xb7, 0x35, 0x2c, 0xa5, 0x24, 0x79, 0x98, 0xb8, 0xfb, 0x58, 0x1a, 0x34, 0x71, 0x97, 0xd2, + 0xc0, 0x89, 0xfb, 0x9e, 0x1e, 0xd2, 0x47, 0x84, 0xb3, 0x3d, 0x8f, 0x8e, 0x8d, 0xcb, 0xc1, 0xe9, + 0x10, 0xcb, 0x6d, 0x0f, 0x51, 0xac, 0x23, 0x7a, 0xcf, 0x1d, 0xbe, 0x71, 0x39, 0x4a, 0xc3, 0x89, + 0xfe, 0xbb, 0xbd, 0x28, 0xbd, 0x43, 0x78, 0xaa, 0x6b, 0x23, 0xae, 0x0e, 0xe8, 0x74, 0x5e, 0x28, + 0xf7, 0x70, 0x48, 0x42, 0x49, 0xdc, 0x9a, 0xf9, 0xe9, 0x48, 0x41, 0x07, 0x47, 0x0a, 0xfa, 0x76, + 0xa4, 0xa0, 0x37, 0xc7, 0xca, 0xc8, 0xc1, 0xb1, 0x32, 0xf2, 0xf5, 0x58, 0x19, 0x79, 0xbc, 0x46, + 0x1c, 0xb1, 0x17, 0x98, 0xa7, 0x37, 0xba, 0x16, 0x99, 0x96, 0x13, 0x57, 0xed, 0x8c, 0x6b, 0xb9, + 0x6d, 0x5b, 0x8e, 0x7c, 0xb5, 0x7d, 0xad, 0xf5, 0xe7, 0xda, 0xf4, 0x81, 0x9b, 0x99, 0xf0, 0xb7, + 0x6a, 0xfe, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x2c, 0x26, 0xc6, 0x46, 0xd1, 0x0a, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -879,6 +891,20 @@ func (m *MsgProposeAddAccount) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.ProductIDs) > 0 { + for iNdEx := len(m.ProductIDs) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.ProductIDs[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x42 + } + } if m.Time != 0 { i = encodeVarintTx(dAtA, i, uint64(m.Time)) i-- @@ -1290,6 +1316,12 @@ func (m *MsgProposeAddAccount) Size() (n int) { if m.Time != 0 { n += 1 + sovTx(uint64(m.Time)) } + if len(m.ProductIDs) > 0 { + for _, e := range m.ProductIDs { + l = e.Size() + n += 1 + l + sovTx(uint64(l)) + } + } return n } @@ -1671,6 +1703,40 @@ func (m *MsgProposeAddAccount) Unmarshal(dAtA []byte) error { break } } + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ProductIDs", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ProductIDs = append(m.ProductIDs, &types1.Uint16Range{}) + if err := m.ProductIDs[len(m.ProductIDs)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/x/model/handler_test.go b/x/model/handler_test.go index 740c64fa3..854e241da 100644 --- a/x/model/handler_test.go +++ b/x/model/handler_test.go @@ -27,6 +27,7 @@ import ( testkeeper "github.com/zigbee-alliance/distributed-compliance-ledger/testutil/keeper" "github.com/zigbee-alliance/distributed-compliance-ledger/testutil/testdata" dclcompltypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/compliance" + commontypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/common/types" dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" "github.com/zigbee-alliance/distributed-compliance-ledger/x/model/keeper" "github.com/zigbee-alliance/distributed-compliance-ledger/x/model/types" @@ -38,6 +39,12 @@ type DclauthKeeperMock struct { mock.Mock } +func (m *DclauthKeeperMock) HasRightsToChange(ctx sdk.Context, addr sdk.AccAddress, pid int32) bool { + args := m.Called(ctx, addr, pid) + + return args.Bool(0) +} + func (m *DclauthKeeperMock) HasRole( ctx sdk.Context, addr sdk.AccAddress, @@ -88,14 +95,16 @@ type TestSetup struct { ComplianceKeeper *ComplianceKeeperMock Handler sdk.Handler // Querier sdk.Querier - Vendor sdk.AccAddress - VendorID int32 + Vendor sdk.AccAddress + VendorID int32 + ProductIDs []*commontypes.Uint16Range } func (setup *TestSetup) AddAccount( accAddress sdk.AccAddress, roles []dclauthtypes.AccountRole, vendorID int32, + productIDs []*commontypes.Uint16Range, ) { dclauthKeeper := setup.DclauthKeeper @@ -106,6 +115,16 @@ func (setup *TestSetup) AddAccount( dclauthKeeper.On("HasVendorID", mock.Anything, accAddress, vendorID).Return(true) dclauthKeeper.On("HasVendorID", mock.Anything, accAddress, mock.Anything).Return(false) + + if len(productIDs) == 0 { + dclauthKeeper.On("HasRightsToChange", mock.Anything, accAddress, mock.Anything).Return(true) + } + for _, productIDRange := range productIDs { + for productID := productIDRange.Min; productID <= productIDRange.Max; productID++ { + dclauthKeeper.On("HasRightsToChange", mock.Anything, accAddress, productID).Return(true) + } + } + dclauthKeeper.On("HasRightsToChange", mock.Anything, accAddress, mock.Anything).Return(false) } func Setup(t *testing.T) *TestSetup { @@ -116,7 +135,7 @@ func Setup(t *testing.T) *TestSetup { vendor := testdata.GenerateAccAddress() vendorID := testconstants.VendorID1 - + productIDs := testconstants.ProductIDsEmpty setup := &TestSetup{ T: t, Ctx: ctx, @@ -127,9 +146,10 @@ func Setup(t *testing.T) *TestSetup { Handler: NewHandler(*keeper), Vendor: vendor, VendorID: vendorID, + ProductIDs: productIDs, } - setup.AddAccount(vendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, vendorID) + setup.AddAccount(vendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, vendorID, productIDs) return setup } @@ -182,6 +202,45 @@ func TestHandler_UpdateModel(t *testing.T) { require.Equal(t, msgUpdateModel.ProductLabel, receivedModel.ProductLabel) } +func TestHandler_UpdateModelByVendorWithProductIds(t *testing.T) { + setup := Setup(t) + + owner := testdata.GenerateAccAddress() + setup.AddAccount(owner, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1, testconstants.ProductIDs200) + + // add new model + msgCreateModel := NewMsgCreateModel(owner) + msgCreateModel.Pid = 200 + _, err := setup.Handler(setup.Ctx, msgCreateModel) + require.NoError(t, err) + + anotherVendor := testdata.GenerateAccAddress() + setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDs100) + + // update existing model by vendor with another VendorID + msgUpdateModel := NewMsgUpdateModel(anotherVendor) + _, err = setup.Handler(setup.Ctx, msgUpdateModel) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + + // update existing model by owner + msgUpdateModel = NewMsgUpdateModel(owner) + msgUpdateModel.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgUpdateModel) + require.NoError(t, err) + + vendorWithoutProductIDs := testdata.GenerateAccAddress() + setup.AddAccount(vendorWithoutProductIDs, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDsEmpty) + + // update existing model by vendor with the same VendorID as owner's one + msgUpdateModel = NewMsgUpdateModel(vendorWithoutProductIDs) + msgUpdateModel.Pid = 200 + msgUpdateModel.ProductLabel += "-updated-once-more" + msgUpdateModel.LsfRevision++ + _, err = setup.Handler(setup.Ctx, msgUpdateModel) + require.NoError(t, err) +} + func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModel(t *testing.T) { setup := Setup(t) @@ -196,7 +255,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModel(t *testing.T) { dclauthtypes.NodeAdmin, } { accAddress := testdata.GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID) + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID, setup.ProductIDs) // update existing model by user without Vendor role msgUpdateModel := NewMsgUpdateModel(accAddress) @@ -206,7 +265,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModel(t *testing.T) { } anotherVendor := testdata.GenerateAccAddress() - setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2) + setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, setup.ProductIDs) // update existing model by vendor with another VendorID msgUpdateModel := NewMsgUpdateModel(anotherVendor) @@ -220,7 +279,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModel(t *testing.T) { require.NoError(t, err) vendorWithSameVid := testdata.GenerateAccAddress() - setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID) + setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, setup.ProductIDs) // update existing model by vendor with the same VendorID as owner's one msgUpdateModel = NewMsgUpdateModel(vendorWithSameVid) @@ -353,7 +412,7 @@ func TestHandler_AddModelByNonVendor(t *testing.T) { dclauthtypes.NodeAdmin, } { accAddress := testdata.GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID) + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID, setup.ProductIDs) // add new model model := NewMsgCreateModel(accAddress) @@ -367,7 +426,7 @@ func TestHandler_AddModelByVendorWithAnotherVendorId(t *testing.T) { setup := Setup(t) anotherVendor := testdata.GenerateAccAddress() - setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2) + setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDsEmpty) // add new model model := NewMsgCreateModel(anotherVendor) @@ -376,6 +435,35 @@ func TestHandler_AddModelByVendorWithAnotherVendorId(t *testing.T) { require.True(t, sdkerrors.ErrUnauthorized.Is(err)) } +func TestHandler_AddModelByVendorWithProductIds(t *testing.T) { + setup := Setup(t) + + owner := testdata.GenerateAccAddress() + setup.AddAccount(owner, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDs200) + + model := NewMsgCreateModel(owner) + model.Pid = 200 + _, err := setup.Handler(setup.Ctx, model) + require.NoError(t, err) + + vendor := testdata.GenerateAccAddress() + setup.AddAccount(vendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDs100) + model = NewMsgCreateModel(vendor) + model.Pid = 101 + _, err = setup.Handler(setup.Ctx, model) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + + vendorWithSameVid := testdata.GenerateAccAddress() + setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDsEmpty) + + // add model by vendor with non-assigned PIDs + model = NewMsgCreateModel(vendorWithSameVid) + model.Pid = 201 + _, err = setup.Handler(setup.Ctx, model) + require.NoError(t, err) +} + func TestHandler_PartiallyUpdateModel(t *testing.T) { setup := Setup(t) @@ -529,6 +617,50 @@ func TestHandler_DeleteModelWithAssociatedModelVersionsCertified(t *testing.T) { require.NoError(t, err) } +func TestHandler_DeleteModelByVendorWitProductIds(t *testing.T) { + setup := Setup(t) + + owner := testdata.GenerateAccAddress() + setup.AddAccount(owner, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1, testconstants.ProductIDs200) + + // add new model + msgCreateModel := NewMsgCreateModel(owner) + msgCreateModel.Pid = 200 + _, err := setup.Handler(setup.Ctx, msgCreateModel) + require.NoError(t, err) + + vendor := testdata.GenerateAccAddress() + setup.AddAccount(vendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDs100) + + // delete existing model by vendor with another VendorID + msgDeleteModel := NewMsgDeleteModel(vendor) + msgDeleteModel.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgDeleteModel) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + + // delete existing model by owner + msgDeleteModel = NewMsgDeleteModel(owner) + msgDeleteModel.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgDeleteModel) + require.NoError(t, err) + + // add new model + msgCreateModel = NewMsgCreateModel(owner) + msgCreateModel.Pid = 199 + _, err = setup.Handler(setup.Ctx, msgCreateModel) + require.NoError(t, err) + + vendorWithSameVid := testdata.GenerateAccAddress() + setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDsEmpty) + + // delete existing model by vendor with non-assigned PIDs + msgDeleteModel = NewMsgDeleteModel(vendorWithSameVid) + msgDeleteModel.Pid = 199 + _, err = setup.Handler(setup.Ctx, msgDeleteModel) + require.NoError(t, err) +} + func TestHandler_OnlyOwnerAndVendorWithSameVidCanDeleteModel(t *testing.T) { setup := Setup(t) @@ -543,7 +675,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanDeleteModel(t *testing.T) { dclauthtypes.NodeAdmin, } { accAddress := testdata.GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID) + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID, setup.ProductIDs) // delete existing model by user without Vendor role msgDeleteModel := NewMsgDeleteModel(accAddress) @@ -553,7 +685,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanDeleteModel(t *testing.T) { } anotherVendor := testdata.GenerateAccAddress() - setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2) + setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDsEmpty) // delete existing model by vendor with another VendorID msgDeleteModel := NewMsgDeleteModel(anotherVendor) @@ -572,7 +704,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanDeleteModel(t *testing.T) { require.NoError(t, err) vendorWithSameVid := testdata.GenerateAccAddress() - setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID) + setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, setup.ProductIDs) // delete existing model by vendor with the same VendorID as owner's one msgDeleteModel = NewMsgDeleteModel(vendorWithSameVid) @@ -755,6 +887,51 @@ func TestHandler_UpdateModelVersion(t *testing.T) { require.Equal(t, []uint32{msgCreateModelVersion.SoftwareVersion}, receivedModelVersions.SoftwareVersions) } +func TestHandler_UpdateModelVersionByVendorWithProductIds(t *testing.T) { + setup := Setup(t) + + owner := testdata.GenerateAccAddress() + setup.AddAccount(owner, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1, testconstants.ProductIDs200) + + // add new model + msgCreteModel := NewMsgCreateModel(owner) + msgCreteModel.Pid = 200 + _, err := setup.Handler(setup.Ctx, msgCreteModel) + require.NoError(t, err) + + // add new model version + msgCreateModelVersion := NewMsgCreateModelVersion(owner, testconstants.SoftwareVersion) + msgCreateModelVersion.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgCreateModelVersion) + require.NoError(t, err) + + vendor := testdata.GenerateAccAddress() + setup.AddAccount(vendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDs100) + + // update existing model by vendor with another productIDs + msgUpdateModelVersion := NewMsgUpdateModelVersion(vendor) + msgUpdateModelVersion.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgUpdateModelVersion) + require.Error(t, err) + require.True(t, sdkerrors.ErrUnauthorized.Is(err)) + + // update existing model version by owner + msgUpdateModelVersion = NewMsgUpdateModelVersion(owner) + msgUpdateModelVersion.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgUpdateModelVersion) + require.NoError(t, err) + + vendorWithoutProductIDs := testdata.GenerateAccAddress() + setup.AddAccount(vendorWithoutProductIDs, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, testconstants.ProductIDsEmpty) + + msgUpdateModelVersion = NewMsgUpdateModelVersion(vendorWithoutProductIDs) + msgUpdateModelVersion.Pid = 200 + + msgUpdateModelVersion.ReleaseNotesUrl += "/updated-once-more" + _, err = setup.Handler(setup.Ctx, msgUpdateModelVersion) + require.NoError(t, err) +} + func TestHandler_PartiallyUpdateModelVersion(t *testing.T) { setup := Setup(t) @@ -1024,7 +1201,6 @@ func TestHandler_UpdateOTAFieldsInitiallySet(t *testing.T) { require.Equal(t, receivedModelVersion.OtaChecksum, msgUpdateModelVersion.OtaChecksum) require.Equal(t, receivedModelVersion.OtaFileSize, msgUpdateModelVersion.OtaFileSize) } - func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModelVersion(t *testing.T) { setup := Setup(t) @@ -1044,7 +1220,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModelVersion(t *testing.T dclauthtypes.NodeAdmin, } { accAddress := testdata.GenerateAccAddress() - setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID) + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{role}, setup.VendorID, setup.ProductIDs) // update existing model version by user without Vendor role msgUpdateModelVersion := NewMsgUpdateModelVersion(accAddress) @@ -1054,7 +1230,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModelVersion(t *testing.T } anotherVendor := testdata.GenerateAccAddress() - setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2) + setup.AddAccount(anotherVendor, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDsEmpty) // update existing model by vendor with another VendorID msgUpdateModelVersion := NewMsgUpdateModelVersion(anotherVendor) @@ -1069,7 +1245,7 @@ func TestHandler_OnlyOwnerAndVendorWithSameVidCanUpdateModelVersion(t *testing.T require.NoError(t, err) vendorWithSameVid := testdata.GenerateAccAddress() - setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID) + setup.AddAccount(vendorWithSameVid, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, setup.VendorID, setup.ProductIDs) // update existing model by vendor with the same VendorID as owner's one msgUpdateModelVersion = NewMsgUpdateModelVersion(vendorWithSameVid) @@ -1112,7 +1288,7 @@ func TestHandler_DeleteModelVersion(t *testing.T) { require.Equal(t, codes.NotFound, status.Code(err)) } -func TestHandler_DeleteModelVersionDifferendAccSameVid(t *testing.T) { +func TestHandler_DeleteModelVersionDifferentAccSameVid(t *testing.T) { setup := Setup(t) // add new model @@ -1128,7 +1304,7 @@ func TestHandler_DeleteModelVersionDifferendAccSameVid(t *testing.T) { secondAcc := testdata.GenerateAccAddress() secondAccVid := testconstants.VendorID1 - setup.AddAccount(secondAcc, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, secondAccVid) + setup.AddAccount(secondAcc, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, secondAccVid, testconstants.ProductIDsEmpty) msgDeleteModelVersion := NewMsgDeleteModelVersion(secondAcc) @@ -1163,14 +1339,13 @@ func TestHandler_DeleteModelVersionNotByVendor(t *testing.T) { _, err = setup.Handler(setup.Ctx, msgCreateModelVersion) require.NoError(t, err) - setup.AddAccount(testconstants.Address1, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, testconstants.VendorID2) + setup.AddAccount(testconstants.Address1, []dclauthtypes.AccountRole{dclauthtypes.Trustee}, testconstants.VendorID2, testconstants.ProductIDsEmpty) msgDeleteModelVersion := NewMsgDeleteModelVersion(testconstants.Address1) _, err = setup.Handler(setup.Ctx, msgDeleteModelVersion) require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) } - func TestHandler_DeleteModelVersionDifferentVid(t *testing.T) { setup := Setup(t) @@ -1224,7 +1399,7 @@ func TestHandler_DeleteModelVersionNotByCreator(t *testing.T) { _, err = setup.Handler(setup.Ctx, msgCreateModelVersion) require.NoError(t, err) - setup.AddAccount(testconstants.Address1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2) + setup.AddAccount(testconstants.Address1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID2, testconstants.ProductIDsEmpty) msgDeleteModelVersion := NewMsgDeleteModelVersion(testconstants.Address1) @@ -1255,6 +1430,53 @@ func TestHandler_DeleteModelVersionCertified(t *testing.T) { require.ErrorIs(t, err, types.ErrModelVersionDeletionCertified) } +func TestHandler_DeleteModelVersionByVendorWithProductIds(t *testing.T) { + setup := Setup(t) + + owner := testdata.GenerateAccAddress() + setup.AddAccount(owner, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1, testconstants.ProductIDs200) + + // add new model + msgCreateModel := NewMsgCreateModel(owner) + msgCreateModel.Pid = 200 + _, err := setup.Handler(setup.Ctx, msgCreateModel) + require.NoError(t, err) + + // add new model version + msgCreateModelVersion := NewMsgCreateModelVersion(owner, testconstants.SoftwareVersion) + msgCreateModelVersion.Pid = 200 + _, err = setup.Handler(setup.Ctx, msgCreateModelVersion) + require.NoError(t, err) + + setup.AddAccount(testconstants.Address1, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.VendorID1, testconstants.ProductIDs100) + + msgDeleteModelVersion := NewMsgDeleteModelVersion(testconstants.Address1) + msgDeleteModelVersion.Pid = 200 + + _, err = setup.Handler(setup.Ctx, msgDeleteModelVersion) + require.ErrorIs(t, err, sdkerrors.ErrUnauthorized) + + msgDeleteModelVersion = NewMsgDeleteModelVersion(owner) + msgDeleteModelVersion.Pid = 200 + + complianceKeeper := setup.ComplianceKeeper + complianceKeeper.On("GetComplianceInfo", mock.Anything, msgDeleteModelVersion.Vid, msgDeleteModelVersion.Pid, msgDeleteModelVersion.SoftwareVersion, mock.Anything).Return(false) + complianceKeeper.On("GetComplianceInfo", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(true) + + _, err = setup.Handler(setup.Ctx, msgDeleteModelVersion) + require.NoError(t, err) + + // query model version + _, err = queryModelVersion( + setup, + msgDeleteModelVersion.Vid, + msgDeleteModelVersion.Pid, + msgDeleteModelVersion.SoftwareVersion, + ) + require.Error(t, err) + require.Equal(t, codes.NotFound, status.Code(err)) +} + func queryModel( setup *TestSetup, vid int32, diff --git a/x/model/keeper/check_model_rights.go b/x/model/keeper/check_model_rights.go index a5fb4a209..dd09839d1 100644 --- a/x/model/keeper/check_model_rights.go +++ b/x/model/keeper/check_model_rights.go @@ -6,7 +6,7 @@ import ( dclauthtypes "github.com/zigbee-alliance/distributed-compliance-ledger/x/dclauth/types" ) -func checkModelRights(ctx sdk.Context, k Keeper, signer sdk.AccAddress, vid int32, message string) error { +func checkModelRights(ctx sdk.Context, k Keeper, signer sdk.AccAddress, vid int32, pid int32, message string) error { // sender must have Vendor role to add new model if !k.dclauthKeeper.HasRole(ctx, signer, dclauthtypes.Vendor) { return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s transaction should be "+ @@ -18,5 +18,10 @@ func checkModelRights(ctx sdk.Context, k Keeper, signer sdk.AccAddress, vid int3 "signed by a vendor account containing the vendorID %v ", message, vid) } + if !k.dclauthKeeper.HasRightsToChange(ctx, signer, pid) { + return sdkerrors.Wrapf(sdkerrors.ErrUnauthorized, "%s transaction should be "+ + "signed by a vendor account who has rights to modify the productID %v ", message, pid) + } + return nil } diff --git a/x/model/keeper/msg_server_model.go b/x/model/keeper/msg_server_model.go index d29d40379..550d6acd0 100644 --- a/x/model/keeper/msg_server_model.go +++ b/x/model/keeper/msg_server_model.go @@ -16,7 +16,7 @@ func (k msgServer) CreateModel(goCtx context.Context, msg *types.MsgCreateModel) if err != nil { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgCreateModel"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgCreateModel"); err != nil { return nil, err } @@ -79,7 +79,7 @@ func (k msgServer) UpdateModel(goCtx context.Context, msg *types.MsgUpdateModel) if err != nil { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgUpdateModel"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgUpdateModel"); err != nil { return nil, err } @@ -172,7 +172,7 @@ func (k msgServer) DeleteModel(goCtx context.Context, msg *types.MsgDeleteModel) return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgDeleteModel"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgDeleteModel"); err != nil { return nil, err } diff --git a/x/model/keeper/msg_server_model_version.go b/x/model/keeper/msg_server_model_version.go index 050679706..ee87ac939 100644 --- a/x/model/keeper/msg_server_model_version.go +++ b/x/model/keeper/msg_server_model_version.go @@ -17,7 +17,7 @@ func (k msgServer) CreateModelVersion(goCtx context.Context, msg *types.MsgCreat if err != nil { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgCreateModelVersion"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgCreateModelVersion"); err != nil { return nil, err } @@ -80,7 +80,7 @@ func (k msgServer) UpdateModelVersion(goCtx context.Context, msg *types.MsgUpdat if err != nil { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgUpdateModelVersion"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgUpdateModelVersion"); err != nil { return nil, err } @@ -147,7 +147,7 @@ func (k msgServer) DeleteModelVersion(goCtx context.Context, msg *types.MsgDelet if err != nil { return nil, sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid Address: (%s)", err) } - if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, "MsgDeleteModelVersion"); err != nil { + if err := checkModelRights(ctx, k.Keeper, signerAddr, msg.Vid, msg.Pid, "MsgDeleteModelVersion"); err != nil { return nil, err } diff --git a/x/model/types/expected_keepers.go b/x/model/types/expected_keepers.go index 23ed641ea..5e4c0c7c2 100644 --- a/x/model/types/expected_keepers.go +++ b/x/model/types/expected_keepers.go @@ -10,6 +10,7 @@ type DclauthKeeper interface { // Methods imported from dclauth should be defined here HasRole(ctx sdk.Context, addr sdk.AccAddress, roleToCheck types.AccountRole) bool HasVendorID(ctx sdk.Context, addr sdk.AccAddress, vid int32) bool + HasRightsToChange(ctx sdk.Context, addr sdk.AccAddress, pid int32) bool } type ComplianceKeeper interface { diff --git a/x/validator/handler_test.go b/x/validator/handler_test.go index 6e08f1f5a..c29c56bc6 100644 --- a/x/validator/handler_test.go +++ b/x/validator/handler_test.go @@ -51,7 +51,7 @@ func Setup(t *testing.T) TestSetup { ba := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account := dclauthtypes.NewAccount( ba, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1, + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty, ) dclauthK.SetAccount(ctx, account) @@ -119,7 +119,7 @@ func TestHandler_CreateValidator_ByNotNodeAdmin(t *testing.T) { for _, role := range []dclauthtypes.AccountRole{dclauthtypes.CertificationCenter, dclauthtypes.Vendor, dclauthtypes.Trustee} { // create signer account ba := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) - account := dclauthtypes.NewAccount(ba, dclauthtypes.AccountRoles{role}, nil, nil, testconstants.VendorID1) + account := dclauthtypes.NewAccount(ba, dclauthtypes.AccountRoles{role}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account) // try to create validator @@ -144,7 +144,7 @@ func TestHandler_CreateValidator_TwiceForSameValidatorAddress(t *testing.T) { // create validator ba := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account := dclauthtypes.NewAccount(ba, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account) msgCreateValidator, err = types.NewMsgCreateValidator( @@ -198,17 +198,17 @@ func TestHandler_ProposedDisableValidatorExists(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -232,17 +232,17 @@ func TestHandler_ProposeAndRejectDisableValidator(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -268,17 +268,17 @@ func TestHandler_ProposeAndRejectDisableValidator_ByAnotherTrustee(t *testing.T) // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -304,7 +304,7 @@ func TestHandler_OnlyTrusteeCanProposeDisableValidator(t *testing.T) { // create account with non-trustee roles ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter, dclauthtypes.Vendor, dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.CertificationCenter, dclauthtypes.Vendor, dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -319,7 +319,7 @@ func TestHandler_OnlyTrusteeCanProposeDisableValidator(t *testing.T) { // create account with trustee roles ba1 = authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account1 = dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) // propose new disablevalidator @@ -334,17 +334,17 @@ func TestHandler_ProposeDisableValidatorWhenSeveralVotesNeeded(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -383,17 +383,17 @@ func TestHandler_DisabledValidator(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -443,12 +443,12 @@ func TestHandler_DisabledValidatorOnPropose(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -489,22 +489,22 @@ func TestHandler_OnlyTrusteeCanApproveDisableValidator(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin, dclauthtypes.CertificationCenter, dclauthtypes.Vendor}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin, dclauthtypes.CertificationCenter, dclauthtypes.Vendor}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -527,7 +527,7 @@ func TestHandler_ProposedDisableValidatorDoesNotExist(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) msgApproveDisableValidator := NewMsgApproveDisableValidator(account1.GetAddress(), sdk.ValAddress(testconstants.ValidatorAddress1)) @@ -542,17 +542,17 @@ func TestHandler_MessageCreatorAlreadyApprovedDisableValidator(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -584,7 +584,7 @@ func TestHandler_NodeAdminCanEnableValidatorDisabledByTrustees(t *testing.T) { // create Trustee and NodeAdmin ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -592,7 +592,7 @@ func TestHandler_NodeAdminCanEnableValidatorDisabledByTrustees(t *testing.T) { ba2 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) // propose and approve new disablevalidator (will be approved because of 1 trustee) @@ -611,12 +611,12 @@ func TestHandler_DisabledValidatorAlreadyExistsPropose(t *testing.T) { // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -668,7 +668,7 @@ func TestHandler_OwnerNodeAdminCanDisabledValidator(t *testing.T) { // create Trustee and NodeAdmin ba1 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey2, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) msgDisableValidator := types.NewMsgDisableValidator(valAddress) @@ -690,7 +690,7 @@ func TestHandler_OwnerNodeAdminCanEnabledValidator(t *testing.T) { // create Trustee and NodeAdmin ba1 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey2, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) // node admin disabled validator @@ -718,17 +718,17 @@ func TestHandler_TrusteeDisabledValidatorOwnerNodeAdminCanEnableValidator(t *tes // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -737,7 +737,7 @@ func TestHandler_TrusteeDisabledValidatorOwnerNodeAdminCanEnableValidator(t *tes // create NodeAdmin ba4 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) // propose new disable validator @@ -768,7 +768,7 @@ func TestHandler_OwnerNodeAdminDisabledValidatorAndNodeAdminCanNotAddNewValidato // create NodeAdmin ba1 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) // node admin disable validator @@ -794,17 +794,17 @@ func TestHandler_TrusteeDisabledValidatorAndOwnerNodeAdminCanNotAddNewValidator( // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -813,7 +813,7 @@ func TestHandler_TrusteeDisabledValidatorAndOwnerNodeAdminCanNotAddNewValidator( // create NodeAdmin ba4 := authtypes.NewBaseAccount(sdk.AccAddress(valAddress), testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.NodeAdmin}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) // propose new disable validator @@ -847,17 +847,17 @@ func TestHandler_RejectDisableValidator_TwoRejectApprovalsAreNeeded(t *testing.T // create 3 Trustees accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -904,23 +904,23 @@ func TestHandler_RejectDisableValidator_ByNotTrustee(t *testing.T) { // create 3 Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) // create vendor account ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Vendor}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -947,7 +947,7 @@ func TestHandler_RejectDisableValidator_ForUnknownAccount(t *testing.T) { // create Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -965,17 +965,17 @@ func TestHandler_Duplicate_RejectDisableValidatorFromTheSameTrustee(t *testing.T // create 3 Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -1011,22 +1011,22 @@ func TestHandler_ApproveDisableValidatorAndRejectDisableValidator_FromTheSamerTr // create 4 Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -1068,22 +1068,22 @@ func TestHandler_RejectDisableValidatorAndApproveDisableValidator_FromTheSameTru // create 4 Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -1126,17 +1126,17 @@ func TestHandler_DoubleTimeRejectDisableValidator(t *testing.T) { // create 3 Trustee accounts ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -1225,28 +1225,28 @@ func TestHandler_RejectDisableValidator_TwoRejectApprovalsAreNeeded_FiveTrustees // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) _, ba5PubKey, ba5Address := testdata.KeyTestPubAddr() ba5 := authtypes.NewBaseAccount(ba5Address, ba5PubKey, 0, 0) account5 := dclauthtypes.NewAccount(ba5, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account5) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1) @@ -1291,28 +1291,28 @@ func TestHandler_ApproveDisableValidator_FourApprovalsAreNeeded_FiveTrustees(t * // create Trustees ba1 := authtypes.NewBaseAccount(testconstants.Address1, testconstants.PubKey1, 0, 0) account1 := dclauthtypes.NewAccount(ba1, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID1, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account1) ba2 := authtypes.NewBaseAccount(testconstants.Address2, testconstants.PubKey2, 0, 0) account2 := dclauthtypes.NewAccount(ba2, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID2, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account2) ba3 := authtypes.NewBaseAccount(testconstants.Address3, testconstants.PubKey3, 0, 0) account3 := dclauthtypes.NewAccount(ba3, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID3, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account3) ba4 := authtypes.NewBaseAccount(testconstants.Address4, testconstants.PubKey4, 0, 0) account4 := dclauthtypes.NewAccount(ba4, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account4) _, ba5PubKey, ba5Address := testdata.KeyTestPubAddr() ba5 := authtypes.NewBaseAccount(ba5Address, ba5PubKey, 0, 0) account5 := dclauthtypes.NewAccount(ba5, - dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4) + dclauthtypes.AccountRoles{dclauthtypes.Trustee}, nil, nil, testconstants.VendorID4, testconstants.ProductIDsEmpty) setup.DclauthKeeper.SetAccount(setup.Ctx, account5) valAddress, err := sdk.ValAddressFromBech32(testconstants.ValidatorAddress1)