Skip to content

Commit

Permalink
Merge pull request #54 from Rate-Limiting-Nullifier/fix/slashing
Browse files Browse the repository at this point in the history
Fix/slashing
  • Loading branch information
AtHeartEngineer authored Apr 13, 2023
2 parents 4b1309b + 46bc74f commit ab1e293
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 114 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports = {
semi: ["warn", "never"],
"import/extensions": ["warn", "never"],
"@typescript-eslint/semi": ["warn", "never"],
"indent": ["warn", 2]
},
settings: {
"import/parsers": {
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rlnjs",
"version": "2.0.7",
"version": "2.0.8",
"description": "Client library for generating and using RLN ZK proofs.",
"license": "MIT",
"repository": "https://github.com/Rate-Limiting-Nullifier/rlnjs",
Expand Down
32 changes: 22 additions & 10 deletions src/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,29 @@ export default class Registry {

/**
* Removes a member from the registry and adds them to the slashed registry.
* @param identityCommitment IdentityCommitment of the member to be removed.
* @param secret Secret of the member to be removed.
*/
public slashMember(identityCommitment: bigint) {
const index = this._registry.indexOf(identityCommitment)
this._registry.delete(index)
this._slashed.insert(identityCommitment)
public slashMember(secret: bigint) {
const identityCommitment = poseidon([secret])
this._addSlashedMember(identityCommitment)
this._removeMember(identityCommitment)
}

/**
* Removes a member from the registry and adds them to the slashed registry.
* @param identityCommitment identityCommitment of the member to be removed.
*/
public slashMemberByIdentityCommitment(identityCommitment: bigint) {
this._addSlashedMember(identityCommitment)
this._removeMember(identityCommitment)
}

/**
* Adds a new member to the slashed registry.
* If a member exists in the registry, the member can't be added to the slashed.
* @param identityCommitment New member.
*/
public addSlashedMember(identityCommitment: bigint) {
public _addSlashedMember(identityCommitment: bigint) {
if (this._slashed.indexOf(identityCommitment) !== -1) {
throw new Error('Member already in slashed registry.')
}
Expand All @@ -138,17 +147,20 @@ export default class Registry {
* Adds new members to the slashed registry.
* @param identityCommitments New members.
*/
public addSlashedMembers(identityCommitments: bigint[]) {
public _addSlashedMembers(identityCommitments: bigint[]) {
for (const identityCommitment of identityCommitments) {
this.addSlashedMember(identityCommitment)
this._addSlashedMember(identityCommitment)
}
}

/**
* Removes a member from the registry.
* @param identityCommitment IdentityCommitment of the member to be removed.
*/
public removeMember(identityCommitment: bigint) {
public _removeMember(identityCommitment: bigint) {
if (this._registry.indexOf(identityCommitment) == -1) {
throw new Error("Member doesn't exist in registry.")
}
const index = this._registry.indexOf(identityCommitment)
this._registry.delete(index)
}
Expand Down Expand Up @@ -216,7 +228,7 @@ export default class Registry {
console.debug(registryObject)
const registryInstance = new Registry(registryObject.treeDepth, BigInt(registryObject.zeroValue))
registryInstance.addMembers(registryObject.registry.map((x) => BigInt(x)))
registryInstance.addSlashedMembers(registryObject.slashed.map((x) => BigInt(x)))
registryInstance._addSlashedMembers(registryObject.slashed.map((x) => BigInt(x)))
return registryInstance
}
}
211 changes: 110 additions & 101 deletions tests/registry.test.ts
Original file line number Diff line number Diff line change
@@ -1,130 +1,139 @@
import Registry, { DEFAULT_REGISTRY_TREE_DEPTH } from "../src/registry"


describe("Registry", () => {
describe("Registry Creation", () => {
test("Should create a registry", () => {
const registry = new Registry()

expect(registry.root.toString()).toContain("150197")
expect(registry._treeDepth).toBe(DEFAULT_REGISTRY_TREE_DEPTH)
expect(registry._zeroValue).toBe(BigInt(0))
expect(registry.members).toHaveLength(0)
})
import Registry, { DEFAULT_REGISTRY_TREE_DEPTH } from '../src/registry'
import poseidon from 'poseidon-lite'

const zeroValue = BigInt(0)
const secret1 = BigInt(1)
const secret2 = BigInt(2)
const secret3 = BigInt(3)
const id1 = poseidon([secret1])
const id2 = poseidon([secret2])
const id3 = poseidon([secret3])

describe('Registry', () => {
describe('Registry Creation', () => {
test('Should create a registry', () => {
const registry = new Registry()

expect(registry.root.toString()).toContain('150197')
expect(registry._treeDepth).toBe(DEFAULT_REGISTRY_TREE_DEPTH)
expect(registry._zeroValue).toBe(zeroValue)
expect(registry.members).toHaveLength(0)
})

test("Should not create a registry with a wrong tree depth", () => {
const wrongRegistry = () => new Registry(33)
test('Should not create a registry with a wrong tree depth', () => {
const wrongRegistry = () => new Registry(33)

expect(wrongRegistry).toThrow("The tree depth must be between 16 and 32")
})
expect(wrongRegistry).toThrow('The tree depth must be between 16 and 32')
})

test("Should create a group with different parameters", () => {
const registry = new Registry(32, BigInt(1))
test('Should create a group with different parameters', () => {
const registry = new Registry(32, BigInt(1))

expect(registry.root.toString()).toContain("640470")
expect(registry._treeDepth).toBe(32)
expect(registry._zeroValue).toBe(BigInt(1))
expect(registry.members).toHaveLength(0)
})
expect(registry.root.toString()).toContain('640470')
expect(registry._treeDepth).toBe(32)
expect(registry._zeroValue).toBe(BigInt(1))
expect(registry.members).toHaveLength(0)
})
})

describe("Add Member", () => {
test("Should add a member to a group", () => {
const registry = new Registry()
describe('Add Member', () => {
test('Should add a member to a group', () => {
const registry = new Registry()

registry.addMember(BigInt(3))
registry.addMember(BigInt(3))

expect(registry.members).toHaveLength(1)
})
test("Shouldn't be able to add Zero Value as member", () => {
const registry = new Registry()
expect(registry.members).toHaveLength(1)
})
test("Shouldn't be able to add Zero Value as member", () => {
const registry = new Registry()

const result = () => registry.addMember(BigInt(0))
const result = () => registry.addMember(zeroValue)

expect(result).toThrow("Can't add zero value as member.")
})
expect(result).toThrow("Can't add zero value as member.")
})
})

describe("Add Members", () => {
test("Should add many members to a group", () => {
const registry = new Registry()
// make test to do large batch insertions
registry.addMembers([BigInt(1), BigInt(3)])
describe('Add Members', () => {
test('Should add many members to a group', () => {
const registry = new Registry()
// make test to do large batch insertions
registry.addMembers([id1, id3])

expect(registry.members).toHaveLength(2)
})
expect(registry.members).toHaveLength(2)
})
})

describe("Index Member", () => {
test("Should return the index of a member in a group", () => {
const registry = new Registry()
describe('Index Member', () => {
test('Should return the index of a member in a group', () => {
const registry = new Registry()

registry.addMembers([BigInt(1), BigInt(3)])
registry.addMembers([id1, id3])

const index = registry.indexOf(BigInt(3))
const index = registry.indexOf(id3)

expect(index).toBe(1)
})
expect(index).toBe(1)
})
})

describe("Remove Member", () => {
test("Should remove a member from a group", () => {
const registry = new Registry()
registry.addMembers([BigInt(1), BigInt(2)])
registry.removeMember(BigInt(1))
describe('Remove Member', () => {
test('Should remove a member from a group', () => {
const registry = new Registry()
registry.addMembers([id1, id2])
registry._removeMember(id1)

expect(registry.members).toHaveLength(2)
expect(registry.members[0]).toBe(registry._zeroValue)
})
expect(registry.members).toHaveLength(2)
expect(registry.members[0]).toBe(registry._zeroValue)
})

describe("Slash Member", () => {
test("Should slash a member from a group", () => {
const registry = new Registry()
registry.addMembers([BigInt(1), BigInt(2)])
registry.slashMember(BigInt(1))
expect(registry.slashedMembers).toHaveLength(1)
expect(registry.slashedMembers[0]).toBe(BigInt(1))
expect(registry.slashedRoot.toString()).toContain("8796144249463725711720918130641160729715802427308818390609092244052653115670")
})
test("Should not be able to add slashed member", () => {
const registry = new Registry()
registry.addMembers([BigInt(1), BigInt(2)])
registry.slashMember(BigInt(1))
expect(() => registry.addMember(BigInt(1))).toThrow("Can't add slashed member.")
})
})

describe('Slash Member', () => {
test('Should slash a member from a group', () => {
const registry = new Registry()
registry.addMembers([id1, id2])
registry.slashMember(secret1)
expect(registry.slashedMembers).toHaveLength(1)
expect(registry.slashedMembers[0]).toBe(id1)
expect(registry.slashedRoot.toString()).toContain('9338483204925821039601825167556410297845868743886253952480975212723134036120')
})
test('Should not be able to add slashed member', () => {
const registry = new Registry()
registry.addMembers([id1, id2])
registry.slashMember(secret1)
expect(() => registry.addMember(id1)).toThrow("Can't add slashed member.")
})
})

describe('Merkle Proof', () => {
test('Should return a merkle proof', () => {
const registry = new Registry()
registry.addMember(id1)
const proof = registry.generateMerkleProof(id1)
console.log(proof.root)
expect(String(proof.root)).toContain('9338483204925821039601825167556410297845868743886253952480975212723134036120')
})
test('Should throw error when given invalid leaf', () => {
const registry = new Registry()
registry.addMember(id1)
const treeDepth = registry._treeDepth

describe("Merkle Proof", () => {
test("Should return a merkle proof", () => {
const registry = new Registry()
registry.addMember(BigInt(1))
const proof = registry.generateMerkleProof(BigInt(1))
expect(String(proof.root)).toContain("879614424946372571172091813064116")
})
test("Should throw error when given invalid leaf", () => {
const registry = new Registry()
registry.addMember(BigInt(1))
const treeDepth = registry._treeDepth;

const result = () => Registry.generateMerkleProof(treeDepth, BigInt(0), [BigInt(1), BigInt(2)], BigInt(3))

expect(result).toThrow("The leaf does not exist")
const result = () => Registry.generateMerkleProof(treeDepth, zeroValue, [id1, id2], id3)

const result2 = () => Registry.generateMerkleProof(treeDepth, BigInt(0), [BigInt(1), BigInt(2)], BigInt(0))
expect(result).toThrow('The leaf does not exist')

expect(result2).toThrow("Can't generate a proof for a zero leaf")
})
})
const result2 = () => Registry.generateMerkleProof(treeDepth, zeroValue, [id1, id2], zeroValue)

test("Should export/import to json", () => {
const registry_json_test = new Registry()
registry_json_test.addMembers([BigInt(1), BigInt(2)])
const json = registry_json_test.export()
console.debug(json)
const registry_from_json = Registry.import(json)
expect(registry_from_json.members).toHaveLength(2)
expect(registry_from_json.root).toEqual(registry_json_test.root)
expect(registry_from_json.slashedRoot).toEqual(registry_json_test.slashedRoot)
expect(result2).toThrow("Can't generate a proof for a zero leaf")
})
})

test('Should export/import to json', () => {
const registryJsonTest = new Registry()
registryJsonTest.addMembers([id1, id2])
const json = registryJsonTest.export()
console.debug(json)
const registryFromJson = Registry.import(json)
expect(registryFromJson.members).toHaveLength(2)
expect(registryFromJson.root).toEqual(registryJsonTest.root)
expect(registryFromJson.slashedRoot).toEqual(registryJsonTest.slashedRoot)
})
})

0 comments on commit ab1e293

Please sign in to comment.