Skip to main content

Authorization Process

The Wallet backend is responsible for collecting approvals among the quorum members and submits them together to MPC Nodes. Each approver authenticates the same request with their credential.

End-to-end process

Loading Diagram...

MPC Nodes do not wait while approvals are collected. Collection completes in the Wallet backend before the network request begins.

Collect a signing quorum

This section presents Quorum approval over the signature (DSG) request. Initiator builds the request, and two approvers must sign-off over it.

1. Freeze the signing payload

import {
SignRequestBuilder,
SignSetupOpts,
} from '@silencelaboratories/walletprovider-sdk';

const message = new SignRequestBuilder()
.setRequest(crypto.randomUUID(), 'Approve payroll', 'EIP191')
.build();

const payload = new SignSetupOpts({
t: 2,
key_id: keyId,
signAlg: 'secp256k1',
message,
});

All approvers must authenticate the same unchanged payload. Changing it requires collecting new signatures.

2. Authenticate on each client

import {
UserSignatures,
type AuthModule,
} from '@silencelaboratories/walletprovider-sdk';

async function authenticateSign(authModule: AuthModule) {
const signatures = await new UserSignatures(authModule, 'v2').build(
'signgen',
payload,
);
if (!signatures.default) throw new Error('Authentication produced no signature');
return signatures.default;
}

// Each call runs on the corresponding credential holder's machine.
const initiatorSignature = await authenticateSign(initiatorAuth);
const adminASignature = await authenticateSign(adminAAuth);
const adminBSignature = await authenticateSign(adminBAuth);

3. Submit the complete bundle

import { HttpClient } from '@silencelaboratories/walletprovider-sdk';

const http = new HttpClient('https://wallet-backend.example');
const signatures = await http.post('/v2/rest/signgen', {
payload,
userSignatures: {
default: initiatorSignature,
approvals: [adminASignature, adminBSignature],
grantees: [],
},
});

The initiator contributes a vote when its credential is a member of the matching Rule.approval.

Authorize policy management

Policy updates and deletion use the current management_approval group.

ActiondefaultCounted approvalsAdditional signature
Update conditions onlyAuthorization rootCurrent management membersNone
Add or increase a member's approval capabilityAuthorization rootCurrent management membersOne matching grantees[] entry per affected credential
Remove a memberAuthorization rootCurrent management membersNone
Delete policyAuthorization rootCurrent management membersNone

All participants authenticate the same epoch-bound request. expectedAuthorizationEpoch is the key's current authorization epoch; the nodes reject the request if it does not match the epoch they hold. Policy deletion example:

import {
DeletePolicyRequest,
UserSignatures,
type AuthModule,
} from '@silencelaboratories/walletprovider-sdk';

const payload = new DeletePolicyRequest({
keyId,
expectedAuthorizationEpoch: currentAuthorizationEpoch,
});

async function authenticateDelete(authModule: AuthModule) {
const signatures = await new UserSignatures(authModule, 'v2').build(
'deletePolicy',
payload,
);
if (!signatures.default) throw new Error('Authentication produced no signature');
return signatures.default;
}

const rootSignature = await authenticateDelete(rootAuth);
const adminSignature = await authenticateDelete(adminAuth);

await http.post('/v2/rest/deletePolicy', {
payload,
userSignatures: {
default: rootSignature,
approvals: [adminSignature],
grantees: [],
},
});

A successful deletion advances the key's authorization epoch, removes the policy, and removes every policy-derived approval grant. The authorization root remains.

Counting and rejection rules

Each of the participating MPC Nodes applies these rules on its own, against its own copy of the key's current grants and policy.

  • Every signature must authenticate the same request.
  • A credential can appear at most once in approvals and once in grantees. The initiator's own credential cannot be repeated in either array.
  • The initiator and each entry in approvals contribute one approval each, but only where that credential is a member of the approval group for this action.
  • An entry in grantees proves that its holder consents to a new or increased capability. It never counts as an approval.

The Wallet backend can take as long as it needs to collect the signatures. MPC Nodes see only the finished bundle, and the decision is theirs, not the backend's.