Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multisig: fetch participant identities from the public key package #4920

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { generateKey } from '@ironfish/rust-nodejs'
import { Assert } from '../../../../assert'
import { useAccountAndAddFundsFixture, useUnsignedTxFixture } from '../../../../testUtilities'
import { createRouteTest } from '../../../../testUtilities/routeTest'
import { ACCOUNT_SCHEMA_VERSION } from '../../../../wallet'
import { ACCOUNT_SCHEMA_VERSION, AssertMultisig } from '../../../../wallet'

describe('Route wallt/multisig/createSignatureShare', () => {
const routeTest = createRouteTest()
Expand Down Expand Up @@ -108,15 +108,22 @@ describe('Route wallt/multisig/createSignatureShare', () => {
})
).content.signingPackage

// Remove one participant from the participants store to simulate unknown signer
// Alter the public key package to replace one identity with another, so
// that we can later pretend that we created a signature share from an
// unknown identity
const account = routeTest.wallet.getAccountByName(accountNames[0])
Assert.isNotNull(account)
AssertMultisig(account)

await routeTest.wallet.walletDb.deleteParticipantIdentity(
account,
Buffer.from(participants[1].identity, 'hex'),
const fromIdentity = participants[1].identity
const toIdentity = participants[2].identity
account.multisigKeys.publicKeyPackage = account.multisigKeys.publicKeyPackage.replace(
fromIdentity,
toIdentity,
)

await routeTest.wallet.walletDb.setAccount(account)

// Attempt to create signature share
await expect(
routeTest.client.wallet.multisig.createSignatureShare({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import { multisig } from '@ironfish/rust-nodejs'
import { BufferSet } from 'buffer-map'
import * as yup from 'yup'
import { AsyncUtils } from '../../../../utils'
import { AssertMultisigSigner } from '../../../../wallet'
import { RpcValidationError } from '../../../adapters'
import { ApiNamespace } from '../../namespaces'
Expand Down Expand Up @@ -39,7 +38,7 @@ export const CreateSignatureShareResponseSchema: yup.ObjectSchema<CreateSignatur
routes.register<typeof CreateSignatureShareRequestSchema, CreateSignatureShareResponse>(
`${ApiNamespace.wallet}/multisig/createSignatureShare`,
CreateSignatureShareRequestSchema,
async (request, node): Promise<void> => {
(request, node) => {
AssertHasRpcContext(request, node, 'wallet')

const account = getAccount(node.wallet, request.data.account)
Expand All @@ -49,10 +48,7 @@ routes.register<typeof CreateSignatureShareRequestSchema, CreateSignatureShareRe
Buffer.from(request.data.signingPackage, 'hex'),
)

const participantIdentities = new BufferSet(
await AsyncUtils.materialize(node.wallet.walletDb.getParticipantIdentities(account)),
)

const participantIdentities = new BufferSet(account.getMultisigParticipantIdentities())
for (const signer of signingPackage.signers()) {
if (!participantIdentities.has(signer)) {
throw new RpcValidationError(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { multisig } from '@ironfish/rust-nodejs'
import * as yup from 'yup'
import { AssertMultisig } from '../../../../wallet'
import { ApiNamespace } from '../../namespaces'
Expand Down Expand Up @@ -39,10 +38,9 @@ routes.register<typeof GetAccountIdentitiesRequestSchema, GetAccountIdentitiesRe
const account = getAccount(context.wallet, request.data.account)
AssertMultisig(account)

const publicKeyPackage = new multisig.PublicKeyPackage(
account.multisigKeys.publicKeyPackage,
)
const identities = publicKeyPackage.identities().map((identity) => identity.toString('hex'))
const identities = account
.getMultisigParticipantIdentities()
.map((identity) => identity.toString('hex'))

request.end({ identities })
},
Expand Down
7 changes: 7 additions & 0 deletions ironfish/src/wallet/account/account.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { multisig } from '@ironfish/rust-nodejs'
import { Asset } from '@ironfish/rust-nodejs'
import { BufferMap, BufferSet } from 'buffer-map'
import MurmurHash3 from 'imurmurhash'
Expand Down Expand Up @@ -1282,6 +1283,12 @@ export class Account {

return notes
}

getMultisigParticipantIdentities(): Array<Buffer> {
AssertMultisig(this)
const publicKeyPackage = new multisig.PublicKeyPackage(this.multisigKeys.publicKeyPackage)
return publicKeyPackage.identities()
}
}

export function calculateAccountPrefix(id: string): Buffer {
Expand Down
6 changes: 1 addition & 5 deletions ironfish/src/wallet/wallet.test.slow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1362,11 +1362,7 @@ describe('Wallet', () => {
...trustedDealerPackage,
})

const storedIdentities: string[] = []
for await (const identity of node.wallet.walletDb.getParticipantIdentities(account)) {
storedIdentities.push(identity.toString('hex'))
}

const storedIdentities = account.getMultisigParticipantIdentities()
expect(identities.sort()).toEqual(storedIdentities.sort())
})
})
10 changes: 0 additions & 10 deletions ironfish/src/wallet/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1640,16 +1640,6 @@ export class Wallet {
} else {
await account.updateHead(null, tx)
}

if (account.multisigKeys) {
const publicKeyPackage = new multisig.PublicKeyPackage(
account.multisigKeys.publicKeyPackage,
)

for (const identity of publicKeyPackage.identities()) {
await this.walletDb.addParticipantIdentity(account, identity, tx)
}
}
})

this.accounts.set(account.id, account)
Expand Down
20 changes: 0 additions & 20 deletions ironfish/src/wallet/walletdb/walletdb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,24 +410,4 @@ describe('WalletDB', () => {
expect(storedSecret.secret).toEqualBuffer(serializedSecret)
})
})

describe('participantIdentities', () => {
it('should store participant identities for a multisig account', async () => {
const node = (await nodeTest.createSetup()).node
const walletDb = node.wallet.walletDb

const account = await useAccountFixture(node.wallet, 'multisig')

const identity = multisig.ParticipantSecret.random().toIdentity()

await walletDb.addParticipantIdentity(account, identity.serialize())

const storedIdentities = await AsyncUtils.materialize(
walletDb.getParticipantIdentities(account),
)

expect(storedIdentities.length).toEqual(1)
expect(storedIdentities[0]).toEqualBuffer(identity.serialize())
})
})
})
28 changes: 0 additions & 28 deletions ironfish/src/wallet/walletdb/walletdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1297,32 +1297,4 @@ export class WalletDB {
yield value
}
}

async addParticipantIdentity(
account: Account,
identity: Buffer,
tx?: IDatabaseTransaction,
): Promise<void> {
await this.participantIdentities.put([account.prefix, identity], { identity }, tx)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we remove this datastore from the walletdb altogether?

maybe in a separate pr

}

async deleteParticipantIdentity(
account: Account,
identity: Buffer,
tx?: IDatabaseTransaction,
): Promise<void> {
await this.participantIdentities.del([account.prefix, identity], tx)
}

async *getParticipantIdentities(
account: Account,
tx?: IDatabaseTransaction,
): AsyncGenerator<Buffer> {
for await (const [_, identity] of this.participantIdentities.getAllKeysIter(
tx,
account.prefixRange,
)) {
yield identity
}
}
}
Loading