From c71e284bb51e74c3346088479378143a69838e15 Mon Sep 17 00:00:00 2001 From: evlekht Date: Sun, 21 Jul 2024 19:12:38 +0400 Subject: [PATCH] [PVM] Add kyb verified state, allow kyb verified to propose add member --- go.mod | 2 +- go.sum | 4 +-- .../addrstate/camino_address_state.go | 11 +++++-- .../txs/executor/camino_tx_executor.go | 4 +-- .../txs/executor/camino_tx_executor_test.go | 1 + vms/platformvm/txs/executor/dac/camino_dac.go | 16 ++++++---- .../txs/executor/dac/camino_dac_test.go | 30 +++++++++++++++++-- 7 files changed, 52 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index 61c25ec10470..d6d106ecda73 100644 --- a/go.mod +++ b/go.mod @@ -161,4 +161,4 @@ require ( replace github.com/ava-labs/avalanche-ledger-go => github.com/chain4travel/camino-ledger-go v0.0.13-c4t -replace github.com/ava-labs/coreth => github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114155-ee5dce4e9868 +replace github.com/ava-labs/coreth => github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114647-ffc063541f3f diff --git a/go.sum b/go.sum index 7fb672647d01..48913e70355d 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,8 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114155-ee5dce4e9868 h1:32bIll72axJXTU3hSYPxY3hxYZ5TqgJpJVE9IubyBZo= -github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114155-ee5dce4e9868/go.mod h1:aXs2X5y4BVp+fGUk4sR1rk1qHmrtTl6NxTJPhUVw3P0= +github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114647-ffc063541f3f h1:UXaMNZQQBLT8Fu3l6p8Fktr3NhYBHfjs5ZRi4UauP4I= +github.com/chain4travel/caminoethvm v1.1.15-rc1.0.20240721114647-ffc063541f3f/go.mod h1:aXs2X5y4BVp+fGUk4sR1rk1qHmrtTl6NxTJPhUVw3P0= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= diff --git a/vms/platformvm/addrstate/camino_address_state.go b/vms/platformvm/addrstate/camino_address_state.go index e9e8ece57553..21bcc4d54cdc 100644 --- a/vms/platformvm/addrstate/camino_address_state.go +++ b/vms/platformvm/addrstate/camino_address_state.go @@ -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 @@ -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 @@ -75,10 +80,10 @@ const ( AddressStateNodeDeferred // 0b0000000000000100000000000000000000000000000000000000000000000100 AddressStateAthensPhaseBits = AddressStateRoleOffersAdmin | AddressStateOffersCreator - // 0b0000000000001000000000000000000000000000000000000000000000001000 + // 0b0000000000001000000000000000010000000000000000000000000000001000 AddressStateBerlinPhaseBits = AddressStateFoundationAdmin | AddressStateRoleConsortiumSecretary | - AddressStateRoleValidatorAdmin - // 0b0000000000001100000000001100001100000000000000000000000000011111 + AddressStateRoleValidatorAdmin | AddressStateKYBVerified + // 0b0000000000001100000000001100011100000000000000000000000000011111 AddressStateValidBits = AddressStateSunrisePhaseBits | AddressStateAthensPhaseBits | AddressStateBerlinPhaseBits diff --git a/vms/platformvm/txs/executor/camino_tx_executor.go b/vms/platformvm/txs/executor/camino_tx_executor.go index 339e51bf8dc5..8b09aa6dfac3 100644 --- a/vms/platformvm/txs/executor/camino_tx_executor.go +++ b/vms/platformvm/txs/executor/camino_tx_executor.go @@ -2323,7 +2323,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 @@ -2334,7 +2334,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): diff --git a/vms/platformvm/txs/executor/camino_tx_executor_test.go b/vms/platformvm/txs/executor/camino_tx_executor_test.go index acefaf167015..1096a6d62c7b 100644 --- a/vms/platformvm/txs/executor/camino_tx_executor_test.go +++ b/vms/platformvm/txs/executor/camino_tx_executor_test.go @@ -2079,6 +2079,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 } diff --git a/vms/platformvm/txs/executor/dac/camino_dac.go b/vms/platformvm/txs/executor/dac/camino_dac.go index 6e028c2ab8ae..54e0c0ddae39 100644 --- a/vms/platformvm/txs/executor/dac/camino_dac.go +++ b/vms/platformvm/txs/executor/dac/camino_dac.go @@ -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") @@ -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 @@ -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 +} diff --git a/vms/platformvm/txs/executor/dac/camino_dac_test.go b/vms/platformvm/txs/executor/dac/camino_dac_test.go index a9b0f7b4cfb3..a9424c776755 100644 --- a/vms/platformvm/txs/executor/dac/camino_dac_test.go +++ b/vms/platformvm/txs/executor/dac/camino_dac_test.go @@ -263,7 +263,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) @@ -280,7 +280,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 { @@ -308,7 +308,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) @@ -333,6 +333,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) {