Skip to content

Commit

Permalink
[PVM] Add kyb verified state, allow kyb verified to propose add member (
Browse files Browse the repository at this point in the history
#355)

(cherry picked from commit 2144505)
(cherry picked from commit 0e19378bccbcf43c4ffa124a992afa29d22ecd1a)
  • Loading branch information
evlekht committed Aug 2, 2024
1 parent 593ca5f commit 8de374c
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 13 deletions.
11 changes: 8 additions & 3 deletions vms/platformvm/addrstate/camino_address_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const (
AddressStateBitKYCVerified AddressStateBit = 32
// Indicates that address KYC verification is expired. (not yet implemented)
AddressStateBitKYCExpired AddressStateBit = 33
// Indicates that address passed KYB verification
AddressStateBitKYBVerified AddressStateBit = 34
// Indicates that address is member of consortium
AddressStateBitConsortium AddressStateBit = 38
// Indicates that a node owned by this address (as consortium member) is deferred
Expand Down Expand Up @@ -58,6 +60,9 @@ const (
AddressStateKYCVerified = AddressState(1) << AddressStateBitKYCVerified
// 0b0000000000000000000000000000001000000000000000000000000000000000
AddressStateKYCExpired = AddressState(1) << AddressStateBitKYCExpired
// 0b0000000000000000000000000000010000000000000000000000000000000000
AddressStateKYBVerified = AddressState(1) << AddressStateBitKYBVerified

// 0b0000000000000000000000000100000000000000000000000000000000000000
AddressStateConsortium = AddressState(1) << AddressStateBitConsortium
// 0b0000000000000000000000001000000000000000000000000000000000000000
Expand All @@ -75,10 +80,10 @@ const (
AddressStateNodeDeferred
// 0b0000000000000100000000000000000000000000000000000000000000000100
AddressStateAthensPhaseBits = AddressStateRoleOffersAdmin | AddressStateOffersCreator
// 0b0000000000001000000000000000000000000000000000000000000000001000
// 0b0000000000001000000000000000010000000000000000000000000000001000
AddressStateBerlinPhaseBits = AddressStateFoundationAdmin | AddressStateRoleConsortiumSecretary |
AddressStateRoleValidatorAdmin
// 0b0000000000001100000000001100001100000000000000000000000000011111
AddressStateRoleValidatorAdmin | AddressStateKYBVerified
// 0b0000000000001100000000001100011100000000000000000000000000011111
AddressStateValidBits = AddressStateSunrisePhaseBits |
AddressStateAthensPhaseBits |
AddressStateBerlinPhaseBits
Expand Down
4 changes: 2 additions & 2 deletions vms/platformvm/txs/executor/camino_tx_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2306,7 +2306,7 @@ func (e *CaminoStandardTxExecutor) AddressStateTx(tx *txs.AddressStateTx) error
}

const (
addressStateKYCAll = as.AddressStateKYCVerified | as.AddressStateKYCExpired
addressStateKYCAll = as.AddressStateKYCVerified | as.AddressStateKYCExpired | as.AddressStateKYBVerified
addressStateRoleBits = as.AddressStateRoleAdmin | as.AddressStateRoleKYCAdmin |
as.AddressStateRoleConsortiumSecretary | as.AddressStateRoleOffersAdmin |
as.AddressStateRoleValidatorAdmin | as.AddressStateFoundationAdmin
Expand All @@ -2317,7 +2317,7 @@ func isPermittedToModifyAddrStateBit(isBerlinPhase bool, roles, state as.Address
switch {
// admin can do anything before BerlinPhase, after that admin can only modify other roles
case roles.Is(as.AddressStateRoleAdmin) && (!isBerlinPhase || addressStateRoleBits&state != 0):
// kyc role can change kyc status
// kyc role can change kyc/kyb bits
case addressStateKYCAll&state != 0 && roles.Is(as.AddressStateRoleKYCAdmin):
// offers admin can assign offers creator role
case state == as.AddressStateOffersCreator && roles.Is(as.AddressStateRoleOffersAdmin):
Expand Down
1 change: 1 addition & 0 deletions vms/platformvm/txs/executor/camino_tx_executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2088,6 +2088,7 @@ func TestCaminoStandardTxExecutorAddressStateTx(t *testing.T) {
for _, permissionsMatrix := range permissionsMatrix {
permissionsMatrix[as.AddressStateBitRoleKYCAdmin][as.AddressStateBitKYCVerified] = nil
permissionsMatrix[as.AddressStateBitRoleKYCAdmin][as.AddressStateBitKYCExpired] = nil
permissionsMatrix[as.AddressStateBitRoleKYCAdmin][as.AddressStateBitKYBVerified] = nil
permissionsMatrix[as.AddressStateBitRoleOffersAdmin][as.AddressStateBitOffersCreator] = nil
permissionsMatrix[as.AddressStateBitRoleValidatorAdmin][as.AddressStateBitNodeDeferred] = nil
}
Expand Down
16 changes: 11 additions & 5 deletions vms/platformvm/txs/executor/dac/camino_dac.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ var (
_ dac.Executor = (*proposalExecutor)(nil)
_ dac.BondTxIDsGetter = (*proposalBondTxIDsGetter)(nil)

errNotKYCVerified = errors.New("address is not KYC verified")
errNotVerifiedAddress = errors.New("address is not KYC or KYB verified")
errNotConsortiumMember = errors.New("address isn't consortium member")
errConsortiumMember = errors.New("address is consortium member")
errNotPermittedToCreateProposal = errors.New("don't have permission to create proposal of this type")
Expand Down Expand Up @@ -144,14 +144,14 @@ func (*proposalBondTxIDsGetter) BaseFeeProposal(*dac.BaseFeeProposalState) ([]id

func (e *proposalVerifier) AddMemberProposal(proposal *dac.AddMemberProposal) error {
// verify that address isn't consortium member and is KYC verified
applicantAddress, err := e.state.GetAddressStates(proposal.ApplicantAddress)
applicantAddrState, err := e.state.GetAddressStates(proposal.ApplicantAddress)
switch {
case err != nil:
return err
case applicantAddress.Is(as.AddressStateConsortium):
case applicantAddrState.Is(as.AddressStateConsortium):
return fmt.Errorf("%w (applicant)", errConsortiumMember)
case applicantAddress.IsNot(as.AddressStateKYCVerified):
return fmt.Errorf("%w (applicant)", errNotKYCVerified)
case !isVerifiedAddrState(applicantAddrState):
return fmt.Errorf("%w (applicant)", errNotVerifiedAddress)
}

// verify that there is no existing add member proposal for this address
Expand Down Expand Up @@ -428,3 +428,9 @@ func mustHaveActiveValidator(s state.Chain, address ids.ShortID) error {
}
return err
}

const addrStateVerifiedBits = as.AddressStateKYCVerified | as.AddressStateKYBVerified

func isVerifiedAddrState(addrState as.AddressState) bool {
return addrState&addrStateVerifiedBits != 0
}
30 changes: 27 additions & 3 deletions vms/platformvm/txs/executor/dac/camino_dac_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ func TestProposalVerifierAddMemberProposal(t *testing.T) {
},
expectedErr: errConsortiumMember,
},
"Applicant address is not kyc verified": {
"Applicant address is not kyc or kyb verified": {
state: func(c *gomock.Controller, utx *txs.AddProposalTx) *state.MockDiff {
s := state.NewMockDiff(c)
s.EXPECT().GetAddressStates(applicantAddress).Return(as.AddressStateEmpty, nil)
Expand All @@ -279,7 +279,7 @@ func TestProposalVerifierAddMemberProposal(t *testing.T) {
signers: [][]*secp256k1.PrivateKey{
{feeOwnerKey}, {bondOwnerKey}, {proposerKey},
},
expectedErr: errNotKYCVerified,
expectedErr: errNotVerifiedAddress,
},
"Already active AddMemberProposal for this applicant": {
state: func(c *gomock.Controller, utx *txs.AddProposalTx) *state.MockDiff {
Expand Down Expand Up @@ -307,7 +307,7 @@ func TestProposalVerifierAddMemberProposal(t *testing.T) {
},
expectedErr: errAlreadyActiveProposal,
},
"OK": {
"OK: Applicant address is kyc verified": {
state: func(c *gomock.Controller, utx *txs.AddProposalTx) *state.MockDiff {
s := state.NewMockDiff(c)
proposalsIterator := state.NewMockProposalsIterator(c)
Expand All @@ -332,6 +332,30 @@ func TestProposalVerifierAddMemberProposal(t *testing.T) {
{feeOwnerKey}, {bondOwnerKey}, {proposerKey},
},
},
"OK: Applicant address is kyb verified": {
state: func(c *gomock.Controller, utx *txs.AddProposalTx) *state.MockDiff {
s := state.NewMockDiff(c)
proposalsIterator := state.NewMockProposalsIterator(c)
proposalsIterator.EXPECT().Next().Return(false)
proposalsIterator.EXPECT().Release()
proposalsIterator.EXPECT().Error().Return(nil)

s.EXPECT().GetAddressStates(applicantAddress).Return(as.AddressStateKYBVerified, nil)
s.EXPECT().GetProposalIterator().Return(proposalsIterator, nil)
return s
},
utx: func() *txs.AddProposalTx {
return &txs.AddProposalTx{
BaseTx: baseTx,
ProposalPayload: proposalBytes,
ProposerAddress: proposerAddr,
ProposerAuth: &secp256k1fx.Input{SigIndices: []uint32{0}},
}
},
signers: [][]*secp256k1.PrivateKey{
{feeOwnerKey}, {bondOwnerKey}, {proposerKey},
},
},
}
for name, tt := range tests {
t.Run(name, func(t *testing.T) {
Expand Down

0 comments on commit 8de374c

Please sign in to comment.