Skip to content

Commit

Permalink
feat: change default TTL and add support for custom TTL (#1) (#308)
Browse files Browse the repository at this point in the history
- Changes the Default TTL to the suggested default of 1 hour per the ipns-record [spec](https://specs.ipfs.tech/ipns/ipns-record/#ttl-uint64)
- Allows for a custom TTL to be passed

Fixes #310

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net>
Co-authored-by: Alex Potsides <alex@achingbrain.net>
Co-authored-by: Daniel Norman <1992255+2color@users.noreply.github.com>
  • Loading branch information
5 people committed Apr 2, 2024
1 parent e933496 commit d647529
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 11 deletions.
14 changes: 7 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { CID } from 'multiformats/cid'

const log = logger('ipns')
const ID_MULTIHASH_CODE = identity.code
const DEFAULT_TTL_NS = 60 * 60 * 1e+9 // 1 Hour or 3600 Seconds

export const namespace = '/ipns/'
export const namespaceLength = namespace.length
Expand Down Expand Up @@ -128,6 +129,7 @@ export interface IDKeys {
}

export interface CreateOptions {
ttlNs?: number | bigint
v1Compatible?: boolean
}

Expand All @@ -140,7 +142,8 @@ export interface CreateV2Options {
}

const defaultCreateOptions: CreateOptions = {
v1Compatible: true
v1Compatible: true,
ttlNs: DEFAULT_TTL_NS
}

/**
Expand All @@ -167,10 +170,9 @@ export async function create (peerId: PeerId, value: CID | PeerId | string, seq:
// Validity in ISOString with nanoseconds precision and validity type EOL
const expirationDate = new NanoDate(Date.now() + Number(lifetime))
const validityType = IpnsEntry.ValidityType.EOL
const [ms, ns] = lifetime.toString().split('.')
const lifetimeNs = (BigInt(ms) * BigInt(100000)) + BigInt(ns ?? '0')
const ttlNs = BigInt(options.ttlNs != null ? options.ttlNs : DEFAULT_TTL_NS)

return _create(peerId, value, seq, validityType, expirationDate.toString(), lifetimeNs, options)
return _create(peerId, value, seq, validityType, expirationDate.toString(), ttlNs, options)
}

/**
Expand All @@ -195,9 +197,7 @@ export async function createWithExpiration (peerId: PeerId, value: CID | PeerId
export async function createWithExpiration (peerId: PeerId, value: CID | PeerId | string, seq: number | bigint, expiration: string, options: CreateOptions = defaultCreateOptions): Promise<IPNSRecord> {
const expirationDate = NanoDate.fromString(expiration)
const validityType = IpnsEntry.ValidityType.EOL

const ttlMs = expirationDate.toDate().getTime() - Date.now()
const ttlNs = (BigInt(ttlMs) * BigInt(100000)) + BigInt(expirationDate.getNano())
const ttlNs = BigInt(options.ttlNs != null ? options.ttlNs : DEFAULT_TTL_NS)

return _create(peerId, value, seq, validityType, expirationDate.toString(), ttlNs, options)
}
Expand Down
47 changes: 43 additions & 4 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('ipns', function () {

it('should create an ipns record (V1+V2) correctly', async () => {
const sequence = 0
const ttl = BigInt(60 * 60 * 1e+9)
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity)
Expand All @@ -40,7 +41,7 @@ describe('ipns', function () {
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(record.validity).to.exist()
expect(record.sequence).to.equal(BigInt(0))
expect(record.ttl).to.equal(BigInt(validity * 100000))
expect(record.ttl).to.equal(ttl)
expect(record.signatureV1).to.exist()
expect(record.signatureV2).to.exist()
expect(record.data).to.exist()
Expand All @@ -51,7 +52,7 @@ describe('ipns', function () {
expect(pb.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(pb.validity).to.exist()
expect(pb.sequence).to.equal(BigInt(sequence))
expect(pb.ttl).to.equal(BigInt(validity * 100000))
expect(pb.ttl).to.equal(ttl)
expect(pb.signatureV1).to.exist()
expect(pb.signatureV2).to.exist()
expect(pb.data).to.exist()
Expand All @@ -67,6 +68,7 @@ describe('ipns', function () {

it('should create an ipns record (V2) correctly', async () => {
const sequence = 0
const ttl = BigInt(60 * 60 * 1e+9)
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, { v1Compatible: false })
Expand All @@ -75,7 +77,7 @@ describe('ipns', function () {
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(record.validity).to.exist()
expect(record.sequence).to.equal(BigInt(0))
expect(record.ttl).to.equal(BigInt(validity * 100000))
expect(record.ttl).to.equal(ttl)
expect(record.signatureV2).to.exist()
expect(record).to.not.have.property('signatureV1')
expect(record.data).to.exist()
Expand All @@ -97,7 +99,7 @@ describe('ipns', function () {
expect(data.ValidityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(data.Validity).to.exist()
expect(data.Sequence).to.equal(BigInt(sequence))
expect(data.TTL).to.equal(BigInt(validity * 100000))
expect(data.TTL).to.equal(ttl)
})

it('should be able to create a record (V1+V2) with a fixed expiration', async () => {
Expand Down Expand Up @@ -130,6 +132,43 @@ describe('ipns', function () {
expect(data.Validity).to.equalBytes(uint8ArrayFromString(expiration))
})

it('should be able to create a record (V1+V2) with a fixed ttl', async () => {
const sequence = 0
const ttl = BigInt(0.6e+12)
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, {
ttlNs: ttl
})
const marshalledRecord = ipns.marshal(record)

await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)

const pb = IpnsEntry.decode(marshalledRecord)
const data = parseCborData(pb.data ?? new Uint8Array(0))
expect(data.TTL).to.equal(ttl)
})

it('should be able to create a record (V2) with a fixed ttl', async () => {
const sequence = 0
const ttl = BigInt(1.6e+12)
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, {
ttlNs: ttl,
v1Compatible: false
})
const marshalledRecord = ipns.marshal(record)

await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)

const pb = IpnsEntry.decode(marshalledRecord)
expect(pb).to.not.have.property('ttl')

const data = parseCborData(pb.data ?? new Uint8Array(0))
expect(data.TTL).to.equal(ttl)
})

it('should create an ipns record (V1+V2) and validate it correctly', async () => {
const sequence = 0
const validity = 1000000
Expand Down

1 comment on commit d647529

@SgtPooki
Copy link
Member

Choose a reason for hiding this comment

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

yay

Please sign in to comment.