Skip to content

Commit

Permalink
feat: moved to profiles
Browse files Browse the repository at this point in the history
  • Loading branch information
karlem committed May 17, 2024
1 parent 1e76ead commit e784c42
Show file tree
Hide file tree
Showing 13 changed files with 2,005 additions and 1,876 deletions.
2 changes: 1 addition & 1 deletion core/banking/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ type EthereumEventSource interface {
}

type Parties interface {
CheckDerivedKeyOwnership(party types.PartyID, derivedKey string) (bool, error)
CheckDerivedKeyOwnership(party types.PartyID, derivedKey string) bool
}

const (
Expand Down
5 changes: 2 additions & 3 deletions core/banking/mocks/mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions core/banking/oneoff_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ func (e *Engine) oneOffTransfer(
}

if transfer.FromDerivedKey != nil {
if _, err := e.parties.CheckDerivedKeyOwnership(types.PartyID(transfer.From), *transfer.FromDerivedKey); err != nil {
if ownsDerivedKey := e.parties.CheckDerivedKeyOwnership(types.PartyID(transfer.From), *transfer.FromDerivedKey); !ownsDerivedKey {
transfer.Status = types.TransferStatusRejected
return err
return fmt.Errorf("party %s does not own derived key %s", transfer.From, *transfer.FromDerivedKey)
}
}

Expand Down
6 changes: 3 additions & 3 deletions core/banking/oneoff_transfers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func testValidOneOffTransferWithFromDerivedKey(t *testing.T) {
}

e.col.EXPECT().GetPartyVestedRewardAccount(derivedKey, assetNameETH).Return(&vestedAccount, nil).Times(1)
e.parties.EXPECT().CheckDerivedKeyOwnership(types.PartyID(partyKey), derivedKey).Return(true, nil).Times(1)
e.parties.EXPECT().CheckDerivedKeyOwnership(types.PartyID(partyKey), derivedKey).Return(true).Times(1)

// assert the calculation of fees and transfer request are correct
e.col.EXPECT().TransferFunds(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).DoAndReturn(
Expand Down Expand Up @@ -652,8 +652,8 @@ func testOneOffTransferInvalidOwnerTransfersWithFromDerivedKey(t *testing.T) {
e.assets.EXPECT().Get(gomock.Any()).Times(1).Return(
assets.NewAsset(&mockAsset{name: assetNameETH, quantum: num.DecimalFromFloat(100)}), nil)

e.parties.EXPECT().CheckDerivedKeyOwnership(types.PartyID(partyKey), derivedKey).Return(false, fmt.Errorf("not and amm owner")).Times(1)
e.parties.EXPECT().CheckDerivedKeyOwnership(types.PartyID(partyKey), derivedKey).Return(false).Times(1)

e.broker.EXPECT().Send(gomock.Any()).Times(1)
assert.Error(t, e.TransferFunds(ctx, transfer), "not and amm owner")
assert.ErrorContains(t, e.TransferFunds(ctx, transfer), "does not own derived key")
}
35 changes: 20 additions & 15 deletions core/parties/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ type Engine struct {
// profiles tracks all parties profiles by party ID.
profiles map[types.PartyID]*types.PartyProfile
minBalanceToUpdateProfile *num.Uint

// derivedKeys tracks all derived keys assigned to a party
derivedKeys map[types.PartyID]map[string]struct{}
}

func (e *Engine) OnMinBalanceForUpdatePartyProfileUpdated(_ context.Context, min *num.Uint) error {
Expand All @@ -49,23 +46,24 @@ func (e *Engine) OnMinBalanceForUpdatePartyProfileUpdated(_ context.Context, min
}

func (e *Engine) AssignDeriveKey(party types.PartyID, derivedKey string) {
if _, ok := e.derivedKeys[party]; !ok {
e.derivedKeys[party] = map[string]struct{}{}
if _, ok := e.profiles[party]; !ok {
e.profiles[party] = &types.PartyProfile{
PartyID: party,
Metadata: map[string]string{},
DerivedKeys: []string{},
}
}
e.derivedKeys[party][derivedKey] = struct{}{}

e.profiles[party].DerivedKeys = append(e.profiles[party].DerivedKeys, derivedKey)
}

func (e *Engine) CheckDerivedKeyOwnership(party types.PartyID, derivedKey string) (bool, error) {
derivedKeys, ok := e.derivedKeys[party]
func (e *Engine) CheckDerivedKeyOwnership(party types.PartyID, derivedKey string) bool {
partyProfile, ok := e.profiles[party]
if !ok {
return false, fmt.Errorf("party %q does not have any derived keys", party)
return false
}

if _, ok := derivedKeys[derivedKey]; !ok {
return false, fmt.Errorf("party %q does not own %q", party, derivedKey)
}

return true, nil
return slices.Contains(partyProfile.DerivedKeys, derivedKey)
}

func (e *Engine) CheckSufficientBalanceToUpdateProfile(party types.PartyID, balance *num.Uint) error {
Expand All @@ -83,7 +81,8 @@ func (e *Engine) UpdateProfile(ctx context.Context, partyID types.PartyID, cmd *
profile, exists := e.profiles[partyID]
if !exists {
profile = &types.PartyProfile{
PartyID: partyID,
PartyID: partyID,
DerivedKeys: []string{},
}
e.profiles[partyID] = profile
}
Expand Down Expand Up @@ -112,6 +111,12 @@ func (e *Engine) loadPartiesFromSnapshot(partiesPayload *types.PayloadParties) {
profile.Metadata[m.Key] = m.Value
}

if profilePayload.DerivedKeys == nil {
profile.DerivedKeys = []string{}
} else {
profile.DerivedKeys = profilePayload.DerivedKeys
}

e.profiles[profile.PartyID] = profile
}
}
Expand Down
89 changes: 89 additions & 0 deletions core/parties/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,106 @@ func TestUpdatingProfiles(t *testing.T) {
"key2": "value2",
"key3": "value3",
},
DerivedKeys: []string{},
},
{
PartyID: party2,
Alias: "test2",
Metadata: map[string]string{
"key1": "value1",
},
DerivedKeys: []string{},
},
}, te.engine.ListProfiles())

require.Error(t, te.engine.UpdateProfile(ctx, party1, &commandspb.UpdatePartyProfile{
Alias: "network",
}))
}

func TestAssigningDerivedKeys(t *testing.T) {
ctx := vgtest.VegaContext(vgrand.RandomStr(5), vgtest.RandomI64())

te := newEngine(t)

party1 := newPartyID(t)

// Non-existing party
require.False(t, te.engine.CheckDerivedKeyOwnership(party1, "derivedKey1"))

// Assigning derived keys create profile if it doesn't exist
te.engine.AssignDeriveKey(party1, "derivedKey1")
te.engine.AssignDeriveKey(party1, "derivedKey2")

require.True(t, te.engine.CheckDerivedKeyOwnership(party1, "derivedKey1"))
require.True(t, te.engine.CheckDerivedKeyOwnership(party1, "derivedKey2"))
require.False(t, te.engine.CheckDerivedKeyOwnership(party1, "derivedKey3"))

// Updating profile doesn't remove derived keys and still works
expectPartyProfileUpdatedEvent(t, te)
require.NoError(t, te.engine.UpdateProfile(ctx, party1, &commandspb.UpdatePartyProfile{
Alias: "test1",
Metadata: []*vegapb.Metadata{
{
Key: "key1",
Value: "value1",
},
},
}))

party2 := newPartyID(t)

expectPartyProfileUpdatedEvent(t, te)
require.NoError(t, te.engine.UpdateProfile(ctx, party2, &commandspb.UpdatePartyProfile{
Alias: "test2",
Metadata: []*vegapb.Metadata{
{
Key: "key1",
Value: "value1",
},
},
}))

expectPartyProfileUpdatedEvent(t, te)
require.NoError(t, te.engine.UpdateProfile(ctx, party1, &commandspb.UpdatePartyProfile{
Alias: "test1",
Metadata: []*vegapb.Metadata{
{
Key: "key2",
Value: "value2",
},
{
Key: "key3",
Value: "value3",
},
},
}))

// Assign key for party 2
te.engine.AssignDeriveKey(party2, "derivedKey3")

// Attempt using alias from party 2.
require.Error(t, te.engine.UpdateProfile(ctx, party1, &commandspb.UpdatePartyProfile{
Alias: "test2",
}))

assertEqualProfiles(t, []types.PartyProfile{
{
PartyID: party1,
Alias: "test1",
Metadata: map[string]string{
"key2": "value2",
"key3": "value3",
},
DerivedKeys: []string{"derivedKey1", "derivedKey2"},
},
{
PartyID: party2,
Alias: "test2",
Metadata: map[string]string{
"key1": "value1",
},
DerivedKeys: []string{"derivedKey3"},
},
}, te.engine.ListProfiles())
}
7 changes: 7 additions & 0 deletions core/parties/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ func (e *SnapshottedEngine) serialiseParties() ([]byte, error) {
return strings.Compare(a.Key, b.Key)
})

profileSnapshot.DerivedKeys = append(profileSnapshot.DerivedKeys, profile.DerivedKeys...)

// Ensure deterministic order among the derived keys.
slices.SortStableFunc(profileSnapshot.DerivedKeys, func(a, b string) int {
return strings.Compare(a, b)
})

profilesSnapshot = append(profilesSnapshot, profileSnapshot)
}

Expand Down
3 changes: 3 additions & 0 deletions core/parties/snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,23 @@ func TestTakingAndRestoringSnapshotSucceeds(t *testing.T) {
Metadata: map[string]string{
"key1": "value1",
},
DerivedKeys: []string{},
},
{
PartyID: party2,
Alias: "test2",
Metadata: map[string]string{
"key1": "value1",
},
DerivedKeys: []string{},
},
{
PartyID: party3,
Alias: "test3",
Metadata: map[string]string{
"key1": "value1",
},
DerivedKeys: []string{},
},
}, te.engine.ListProfiles())
}
Expand Down
7 changes: 4 additions & 3 deletions core/types/party.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ func (p Party) IntoProto() *vegapb.Party {
}

type PartyProfile struct {
PartyID PartyID
Alias string
Metadata map[string]string
PartyID PartyID
Alias string
Metadata map[string]string
DerivedKeys []string
}
1 change: 1 addition & 0 deletions protos/sources/vega/snapshot/v1/snapshot.proto
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,7 @@ message PartyProfile {
string party_id = 1;
string alias = 2;
repeated vega.Metadata metadata = 3;
repeated string derived_keys = 4;
}

message AMMValues {
Expand Down
2 changes: 2 additions & 0 deletions protos/sources/vega/vega.proto
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ message PartyProfile {
// Metadata to associate to a party, in a key/value format where the key
// describes the type of metadata in the value field.
repeated vega.Metadata metadata = 3;
// Derived keys for the party.
repeated string derived_keys = 4;
}

// Generic structure holding a key/value pair.
Expand Down
78 changes: 44 additions & 34 deletions protos/vega/snapshot/v1/snapshot.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit e784c42

Please sign in to comment.