···
import { check, cidForCbor } from '@atproto/common'
-
import { EcdsaKeypair, Keypair, Secp256k1Keypair } from '@atproto/crypto'
···
let rotationKey1: Secp256k1Keypair
let rotationKey2: EcdsaKeypair
-
let handle = 'alice.example.com'
let atpPds = 'https://example.com'
let oldRotationKey1: Secp256k1Keypair
···
rotationKey2 = await EcdsaKeypair.create()
-
const makeNextOp = async (
-
changes: Partial<t.Operation>,
-
): Promise<t.Operation> => {
const lastOp = ops.at(-1)
throw new Error('expected an op on log')
-
const prev = await cidForCbor(lastOp)
-
return operations.signOperation(
-
verificationMethods: lastOp.verificationMethods,
-
rotationKeys: lastOp.rotationKeys,
-
alsoKnownAs: lastOp.alsoKnownAs,
-
services: lastOp.services,
it('creates a valid create op', async () => {
-
const createOp = await operations.signOperation(
-
atproto: signingKey.did(),
-
rotationKeys: [rotationKey1.did(), rotationKey2.did()],
const isValid = check.is(createOp, t.def.operation)
expect(isValid).toBeTruthy()
···
it('parses an operation log with no updates', async () => {
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('updates handle', async () => {
-
handle = 'ali.example2.com'
-
const op = await makeNextOp({ alsoKnownAs: [handle] }, rotationKey1)
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('updates atpPds', async () => {
atpPds = 'https://example2.com'
-
const op = await makeNextOp(
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('rotates signingKey', async () => {
const newSigningKey = await Secp256k1Keypair.create()
-
const op = await makeNextOp(
-
atproto: newSigningKey.did(),
signingKey = newSigningKey
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('rotates rotation keys', async () => {
const newRotationKey = await Secp256k1Keypair.create()
-
const op = await makeNextOp(
-
rotationKeys: [newRotationKey.did(), rotationKey2.did()],
oldRotationKey1 = rotationKey1
rotationKey1 = newRotationKey
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('no longer allows operations from old rotation key', async () => {
-
const op = await makeNextOp(
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
···
it('does not allow operations from the signingKey', async () => {
-
const op = await makeNextOp(
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
it('allows for operations from either rotation key', async () => {
-
const newHandle = 'ali.example.com'
-
const op = await makeNextOp(
-
alsoKnownAs: [newHandle],
const doc = await data.validateOperationLog(did, ops)
-
throw new Error('expected doc')
-
expect(doc.did).toEqual(did)
-
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
-
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
-
expect(doc.alsoKnownAs).toEqual([handle])
-
expect(doc.services).toEqual({ atpPds })
it('allows tombstoning a DID', async () => {
···
it('requires operations to be in order', async () => {
-
const prev = await cidForCbor(ops[ops.length - 2])
-
const op = await makeNextOp(
-
alsoKnownAs: ['bob.test'],
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
MisorderedOperationError,
···
it('does not allow a create operation in the middle of the log', async () => {
-
const op = await makeNextOp(
-
alsoKnownAs: ['bob.test'],
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
MisorderedOperationError,
···
import { check, cidForCbor } from '@atproto/common'
+
import { EcdsaKeypair, Secp256k1Keypair } from '@atproto/crypto'
···
let rotationKey1: Secp256k1Keypair
let rotationKey2: EcdsaKeypair
+
let handle = 'at://alice.example.com'
let atpPds = 'https://example.com'
let oldRotationKey1: Secp256k1Keypair
···
rotationKey2 = await EcdsaKeypair.create()
const lastOp = ops.at(-1)
throw new Error('expected an op on log')
+
const verifyDoc = (doc: t.DocumentData | null) => {
+
throw new Error('expected doc')
+
expect(doc.did).toEqual(did)
+
expect(doc.verificationMethods).toEqual({ atproto: signingKey.did() })
+
expect(doc.rotationKeys).toEqual([rotationKey1.did(), rotationKey2.did()])
+
expect(doc.alsoKnownAs).toEqual([handle])
+
expect(doc.services).toEqual({
+
type: 'AtprotoPersonalDataServer',
it('creates a valid create op', async () => {
+
const createOp = await operations.atprotoOp({
+
signingKey: signingKey.did(),
+
rotationKeys: [rotationKey1.did(), rotationKey2.did()],
const isValid = check.is(createOp, t.def.operation)
expect(isValid).toBeTruthy()
···
it('parses an operation log with no updates', async () => {
const doc = await data.validateOperationLog(did, ops)
it('updates handle', async () => {
+
handle = 'at://ali.example2.com'
+
const op = await operations.updateHandleOp(lastOp(), rotationKey1, handle)
const doc = await data.validateOperationLog(did, ops)
it('updates atpPds', async () => {
atpPds = 'https://example2.com'
+
const op = await operations.updatePdsOp(lastOp(), rotationKey1, atpPds)
const doc = await data.validateOperationLog(did, ops)
it('rotates signingKey', async () => {
const newSigningKey = await Secp256k1Keypair.create()
+
const op = await operations.updateAtprotoKeyOp(
signingKey = newSigningKey
const doc = await data.validateOperationLog(did, ops)
it('rotates rotation keys', async () => {
const newRotationKey = await Secp256k1Keypair.create()
+
const op = await operations.updateRotationkeysOp(lastOp(), rotationKey1, [
oldRotationKey1 = rotationKey1
rotationKey1 = newRotationKey
const doc = await data.validateOperationLog(did, ops)
it('no longer allows operations from old rotation key', async () => {
+
const op = await operations.updateHandleOp(
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
···
it('does not allow operations from the signingKey', async () => {
+
const op = await operations.updateHandleOp(lastOp(), signingKey, 'at://bob')
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
it('allows for operations from either rotation key', async () => {
+
const newHandle = 'at://ali.example.com'
+
const op = await operations.updateHandleOp(
const doc = await data.validateOperationLog(did, ops)
it('allows tombstoning a DID', async () => {
···
it('requires operations to be in order', async () => {
+
const op = await operations.updateHandleOp(
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
MisorderedOperationError,
···
it('does not allow a create operation in the middle of the log', async () => {
+
const op = await operations.atprotoOp({
+
signingKey: signingKey.did(),
+
rotationKeys: [rotationKey1.did(), rotationKey2.did()],
expect(data.validateOperationLog(did, [...ops, op])).rejects.toThrow(
MisorderedOperationError,