Skip to content

Commit

Permalink
108 set relay families via addremove interfaces (#110)
Browse files Browse the repository at this point in the history
* WIP: Updates relay registry setFamilies interface to support add/remove

* Updates relay registry & distribution setFamilies interface to support add/remove
  • Loading branch information
jim-toth authored Jul 31, 2024
1 parent 5385c39 commit be57d81
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 51 deletions.
8 changes: 5 additions & 3 deletions smartweave/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ type RelayRegistryState = {
setFamilies(
families: {
fingerprint: string,
family: string[]
add?: Fingerprint[],
remove?: Fingerprint[]
}[]
) => void
```
Expand Down Expand Up @@ -367,8 +368,9 @@ type DistributionState = {
```typescript
setFamilies(
families: {
fingerprint: Fingerprint
family: Fingerprint[]
fingerprint: Fingerprint,
add?: Fingerprint[],
remove?: Fingerprint[]
}[]
) => void
```
Expand Down
1 change: 1 addition & 0 deletions smartweave/src/common/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export const ENABLED_REQUIRED = 'Enabled must be a boolean'
export const FINGERPRINTS_MUST_BE_ARRAY = 'Valid array of fingerprints required'
export const INVALID_FAMILY = 'Invalid family'
export const FAMILIES_REQUIRED = 'Families must be an array of family mappings'
export const DUPLICATE_FINGERPRINT = 'Duplicate fingerprint'
39 changes: 31 additions & 8 deletions smartweave/src/contracts/distribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
assertValidFingerprint
} from '../util'
import { ContractFunctionInput, EvmAddress, Fingerprint } from '../common/types'
import { ENABLED_REQUIRED, FAMILIES_REQUIRED, FINGERPRINTS_MUST_BE_ARRAY, INVALID_FAMILY } from '../common/errors'
import { DUPLICATE_FINGERPRINT, ENABLED_REQUIRED, FAMILIES_REQUIRED, FINGERPRINTS_MUST_BE_ARRAY, INVALID_FAMILY } from '../common/errors'

export const INVALID_DISTRIBUTION_AMOUNT = 'Invalid distribution amount'
export const INVALID_TIMESTAMP = 'Invalid timestamp'
Expand Down Expand Up @@ -157,7 +157,8 @@ export interface SetFamilies extends ContractFunctionInput {
function: 'setFamilies'
families: {
fingerprint: Fingerprint
family: Fingerprint[]
add?: Fingerprint[],
remove?: Fingerprint[]
}[]
}

Expand Down Expand Up @@ -787,15 +788,37 @@ export class DistributionContract extends Evolvable(Object) {
ContractAssert(Array.isArray(families), FAMILIES_REQUIRED)
ContractAssert(families.length > 0, FAMILIES_REQUIRED)

for (const { fingerprint, family } of families) {
for (const { fingerprint, add, remove } of families) {
assertValidFingerprint(fingerprint)
ContractAssert(Array.isArray(family), INVALID_FAMILY)
for (const familyFingerprint of family) {
assertValidFingerprint(familyFingerprint)
ContractAssert(!!add || !!remove, INVALID_FAMILY)

if (!state.families[fingerprint]) {
state.families[fingerprint] = []
}

if (add) {
ContractAssert(Array.isArray(add), INVALID_FAMILY)
for (const addFingerprint of add) {
assertValidFingerprint(addFingerprint)
ContractAssert(
!state.families[fingerprint].includes(addFingerprint),
DUPLICATE_FINGERPRINT
)
state.families[fingerprint].push(addFingerprint)
}
}

state.families[fingerprint] = family
}
if (remove) {
ContractAssert(Array.isArray(remove), INVALID_FAMILY)
for (const removeFingerprint of remove) {
assertValidFingerprint(removeFingerprint)
const indexToRemove = state
.families[fingerprint]
.indexOf(removeFingerprint)
state.families[fingerprint].splice(indexToRemove, 1)
}
}
}

return { state, result: true }
}
Expand Down
1 change: 0 additions & 1 deletion smartweave/src/contracts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export {
FAMILY_NOT_SET,
HARDWARE_ALREADY_VERIFIED,
SERIAL_NOT_REGISTERED,
DUPLICATE_FINGERPRINT,
CREDITS_MUST_BE_ARRAY,
REGISTRATION_CREDIT_NOT_FOUND,
HARDWARE_VERIFIED_MUST_BE_BOOLEAN_OR_UNDEFINED,
Expand Down
46 changes: 37 additions & 9 deletions smartweave/src/contracts/relay-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ import {
Fingerprint,
PublicKey
} from '../common/types'
import { ENABLED_REQUIRED, FAMILIES_REQUIRED, FINGERPRINTS_MUST_BE_ARRAY, INVALID_FAMILY } from '../common/errors'
import {
DUPLICATE_FINGERPRINT,
ENABLED_REQUIRED,
FAMILIES_REQUIRED,
FINGERPRINTS_MUST_BE_ARRAY,
INVALID_FAMILY
} from '../common/errors'

export const FINGERPRINT_ALREADY_CLAIMABLE = 'Fingerprint already claimable'
export const FINGERPRINT_NOT_CLAIMABLE = 'Fingerprint not claimable'
Expand All @@ -42,7 +48,6 @@ export const FAMILY_REQUIRED = 'Family required'
export const FAMILY_NOT_SET = 'Subsequent relay claims require family to be set'
export const HARDWARE_ALREADY_VERIFIED = 'Hardware has already been verified'
export const SERIAL_NOT_REGISTERED = 'Serial has not been registered'
export const DUPLICATE_FINGERPRINT = 'Duplicate fingerprint'
export const CREDITS_MUST_BE_ARRAY =
'Credits must be a valid array of address & fingerprint tuples'
export const REGISTRATION_CREDIT_NOT_FOUND = 'Registration credit not found'
Expand Down Expand Up @@ -151,7 +156,8 @@ export interface SetFamilies extends ContractFunctionInput {
function: 'setFamilies'
families: {
fingerprint: Fingerprint
family: Fingerprint[]
add?: Fingerprint[]
remove?: Fingerprint[]
}[]
}

Expand Down Expand Up @@ -595,15 +601,37 @@ export class RelayRegistryContract extends Evolvable(Object) {
ContractAssert(Array.isArray(families), FAMILIES_REQUIRED)
ContractAssert(families.length > 0, FAMILIES_REQUIRED)

for (const { fingerprint, family } of families) {
for (const { fingerprint, add, remove } of families) {
assertValidFingerprint(fingerprint)
ContractAssert(Array.isArray(family), INVALID_FAMILY)
for (const familyFingerprint of family) {
assertValidFingerprint(familyFingerprint)
ContractAssert(!!add || !!remove, INVALID_FAMILY)

if (!state.families[fingerprint]) {
state.families[fingerprint] = []
}

if (add) {
ContractAssert(Array.isArray(add), INVALID_FAMILY)
for (const addFingerprint of add) {
assertValidFingerprint(addFingerprint)
ContractAssert(
!state.families[fingerprint].includes(addFingerprint),
DUPLICATE_FINGERPRINT
)
state.families[fingerprint].push(addFingerprint)
}
}

state.families[fingerprint] = family
}
if (remove) {
ContractAssert(Array.isArray(remove), INVALID_FAMILY)
for (const removeFingerprint of remove) {
assertValidFingerprint(removeFingerprint)
const indexToRemove = state
.families[fingerprint]
.indexOf(removeFingerprint)
state.families[fingerprint].splice(indexToRemove, 1)
}
}
}

return { state, result: true }
}
Expand Down
104 changes: 90 additions & 14 deletions smartweave/test/spec/distribution.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import TestResultsFamilyMultiplier
from '../e2e/data/results_family_multipliers.json'
import {
ADDRESS_REQUIRED,
DUPLICATE_FINGERPRINT,
ENABLED_REQUIRED,
FINGERPRINT_REQUIRED,
INVALID_ADDRESS,
Expand All @@ -44,6 +45,7 @@ const BOB = '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB'
const fingerprintA = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
const fingerprintB = 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
const fingerprintC = 'CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC'
const fingerprintD = 'DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD'
const DEFAULT_TOKENS_PER_SECOND = '1000'

let initState: DistributionState
Expand Down Expand Up @@ -350,20 +352,61 @@ describe('Distribution Contract', () => {
families: [
{
fingerprint: fingerprintA,
family: [ fingerprintC ]
add: [ fingerprintA, fingerprintB, fingerprintC ]
},
{
fingerprint: fingerprintB,
add: [ fingerprintA, fingerprintB, fingerprintC ]
},
{
fingerprint: fingerprintC,
add: [ fingerprintA, fingerprintB, fingerprintC ]
}
]
})

const { state: firstState } = DistributionHandle(initState, setFamilies)

expect(firstState.families).to.deep.equal({
[fingerprintA]: [ fingerprintA, fingerprintB, fingerprintC ],
[fingerprintB]: [ fingerprintA, fingerprintB, fingerprintC ],
[fingerprintC]: [ fingerprintA, fingerprintB, fingerprintC ]
})

const setMoreFamilies = createInteraction(OWNER, {
function: 'setFamilies',
families: [
{
fingerprint: fingerprintA,
add: [ fingerprintD ],
remove: [ fingerprintB ]
},
{
fingerprint: fingerprintB,
remove: [ fingerprintA, fingerprintC ]
},
{
fingerprint: fingerprintC,
family: [ fingerprintA ]
add: [ fingerprintD ],
remove: [ fingerprintB ]
},
{
fingerprint: fingerprintD,
add: [ fingerprintA, fingerprintC, fingerprintD ]
}
]
})

const { state } = DistributionHandle(initState, setFamilies)
const { state: secondState } = DistributionHandle(
firstState,
setMoreFamilies
)

expect(state.families).to.deep.equal({
[fingerprintA]: [fingerprintC],
[fingerprintC]: [fingerprintA]
expect(secondState.families).to.deep.equal({
[fingerprintA]: [ fingerprintA, fingerprintC, fingerprintD ],
[fingerprintB]: [ fingerprintB ],
[fingerprintC]: [ fingerprintA, fingerprintC, fingerprintD ],
[fingerprintD]: [ fingerprintA, fingerprintC, fingerprintD ]
})
})

Expand All @@ -373,11 +416,13 @@ describe('Distribution Contract', () => {
families: [
{
fingerprint: fingerprintA,
family: [ fingerprintC ]
add: [ fingerprintC ],
remove: []
},
{
fingerprint: fingerprintC,
family: [ fingerprintA ]
add: [ fingerprintA ],
remove: []
}
]
})
Expand Down Expand Up @@ -417,7 +462,7 @@ describe('Distribution Contract', () => {
const noFingerprintFamily = createInteraction(OWNER, {
function: 'setFamilies',
families: [{
family: []
add: []
}]
})

Expand All @@ -429,7 +474,7 @@ describe('Distribution Contract', () => {
function: 'setFamilies',
families: [{
fingerprint: 'invalid',
family: []
add: []
}]
})

Expand All @@ -441,7 +486,7 @@ describe('Distribution Contract', () => {
function: 'setFamilies',
families: [{
fingerprint: {},
family: []
add: []
}]
})

Expand All @@ -464,7 +509,7 @@ describe('Distribution Contract', () => {
function: 'setFamilies',
families: [{
fingerprint: fingerprintA,
family: [{}, 1, undefined, null, 'invalid']
add: [{}, 1, undefined, null, 'invalid']
}]
})

Expand All @@ -476,14 +521,45 @@ describe('Distribution Contract', () => {
function: 'setFamilies',
families: [{
fingerprint: fingerprintA,
family: [fingerprintC, 'invalid', null]
remove: [fingerprintC, 'invalid', null]
}]
})

expect(
() => DistributionHandle(initState, someInvalidFamilyFingerprintsFamily)
() => DistributionHandle(
initState,
someInvalidFamilyFingerprintsFamily
)
).to.throw(INVALID_FINGERPRINT)
})

it('Throws when adding duplicate fingerprints to a relay family', () => {
const addDuplicateFamilyFingerprint = createInteraction(OWNER, {
function: 'setFamilies',
families: [
{
fingerprint: fingerprintA,
add: [ fingerprintB ]
},
{
fingerprint: fingerprintB,
add: [ fingerprintA ]
}
]
})

expect(
() => DistributionHandle(
{
...initState,
families: {
[fingerprintB]: [ fingerprintA ]
}
},
addDuplicateFamilyFingerprint
)
).to.throw(DUPLICATE_FINGERPRINT)
})
})

describe('Multipliers', () => {
Expand Down
Loading

0 comments on commit be57d81

Please sign in to comment.