mirror of
https://github.com/block/buzz.git
synced 2026-11-03 16:01:35 +00:00
fix(mobile): fail push setup when the relay cannot fit a minimal lease
A relay whose advertised limits cannot hold the self-directed and DM subscriptions now fails subscription sync instead of saving a lease that publication would always reject, so Settings shows the setup error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tom Brow <tomb@block.xyz>
This commit is contained in:
@@ -92,6 +92,14 @@ desiredBuzzPushSubscriptions({
|
||||
// Each Solo chat only adds bytes, so keep the most recent ones that fit.
|
||||
var fitting = candidates.solos.length;
|
||||
if (!buzzPushSubscriptionsFitLease(descriptor, lease(fitting))) {
|
||||
// Without Solo chats only DMs and mentions remain. A relay too small for
|
||||
// those cannot carry push, so fail setup rather than save a lease that
|
||||
// publication would reject.
|
||||
if (!buzzPushSubscriptionsFitLease(descriptor, lease(0))) {
|
||||
throw const FormatException(
|
||||
'The relay push limits are too small for a lease.',
|
||||
);
|
||||
}
|
||||
var low = 0;
|
||||
var high = fitting - 1;
|
||||
while (low < high) {
|
||||
|
||||
@@ -423,8 +423,9 @@ const _descriptor = BuzzPushLeaseDescriptor(
|
||||
executorPubkey: 'pubkey',
|
||||
transport: 'apns',
|
||||
maxLeaseTtlSeconds: 3600,
|
||||
maxContentLength: 4096,
|
||||
maxPlaintextLength: 4096,
|
||||
// The relay's NIP-11 limits, which fit a DM lease at the endpoint limit.
|
||||
maxContentLength: 65536,
|
||||
maxPlaintextLength: 32768,
|
||||
maxEndpointLength: 2048,
|
||||
maxStringLength: 512,
|
||||
);
|
||||
|
||||
@@ -121,13 +121,15 @@ void main() {
|
||||
expect(desired.omittedSoloChats, dmCount);
|
||||
|
||||
// A relay may advertise any endpoint limit; sizing must not allocate it.
|
||||
final unbounded = desiredBuzzPushSubscriptions(
|
||||
descriptor: _descriptor(endpointLength: 1 << 50),
|
||||
community: _community(keys),
|
||||
channels: channels,
|
||||
mutedChannelIds: const [],
|
||||
)!;
|
||||
expect(unbounded.omittedSoloChats, soloCount);
|
||||
expect(
|
||||
() => desiredBuzzPushSubscriptions(
|
||||
descriptor: _descriptor(endpointLength: 1 << 50),
|
||||
community: _community(keys),
|
||||
channels: channels,
|
||||
mutedChannelIds: const [],
|
||||
),
|
||||
throwsFormatException,
|
||||
);
|
||||
});
|
||||
|
||||
for (final (limit, descriptor, soloCount, mutedSolos) in [
|
||||
@@ -181,42 +183,50 @@ void main() {
|
||||
_id(n),
|
||||
});
|
||||
// The relay accepts any grant up to its endpoint limit.
|
||||
final publication = await publishBuzzDevPushLease(
|
||||
grant: BuzzPushEndpointGrant(
|
||||
relayOrigin: descriptor.origin,
|
||||
relayPubkey: descriptor.executorPubkey,
|
||||
installationId: 'c' * 32,
|
||||
endpointGrant: 'x' * descriptor.maxEndpointLength,
|
||||
endpointHash: 'd' * 64,
|
||||
endpointEpoch: 1,
|
||||
generation: 9007199254740991,
|
||||
expiresAt: 1756212000,
|
||||
),
|
||||
descriptor: descriptor,
|
||||
nsec: keys.nsec,
|
||||
memberPubkey: keys.public,
|
||||
subscriptions: desired.subscriptions,
|
||||
now: () => DateTime.fromMillisecondsSinceEpoch(1752620000 * 1000),
|
||||
submit:
|
||||
({
|
||||
required kind,
|
||||
required content,
|
||||
required tags,
|
||||
createdAt,
|
||||
}) async => const NostrEvent(
|
||||
id: 'accepted-id',
|
||||
pubkey: '',
|
||||
createdAt: 0,
|
||||
kind: 0,
|
||||
tags: [],
|
||||
content: '',
|
||||
sig: '',
|
||||
),
|
||||
final publication = await _publish(
|
||||
descriptor,
|
||||
keys,
|
||||
desired.subscriptions,
|
||||
);
|
||||
expect(publication.eventId, 'accepted-id');
|
||||
});
|
||||
}
|
||||
|
||||
for (final (limit, descriptor) in [
|
||||
('content', _descriptor(contentLength: 100)),
|
||||
('plaintext', _descriptor(plaintextLength: 100)),
|
||||
]) {
|
||||
test(
|
||||
'fails setup when the $limit limit cannot fit DMs and mentions',
|
||||
() async {
|
||||
final keys = nostr.Keys.generate();
|
||||
final channels = [channel(_id(0)), _solo(1, keys.public)];
|
||||
|
||||
// Publication rejects even the lease without Solo chats.
|
||||
await expectLater(
|
||||
_publish(
|
||||
descriptor,
|
||||
keys,
|
||||
buildDesiredBuzzPushSubscriptions(
|
||||
myPubkey: keys.public,
|
||||
channelIds: [_id(0)],
|
||||
),
|
||||
),
|
||||
throwsFormatException,
|
||||
);
|
||||
expect(
|
||||
() => desiredBuzzPushSubscriptions(
|
||||
community: _community(keys),
|
||||
descriptor: descriptor,
|
||||
channels: channels,
|
||||
mutedChannelIds: const [],
|
||||
),
|
||||
throwsFormatException,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
test('waits for the Solo record but not past its failure', () async {
|
||||
const legacySoloID = '123e4567-e89b-42d3-a456-426614174009';
|
||||
final community = Community.create(
|
||||
@@ -381,3 +391,35 @@ BuzzPushLeaseDescriptor _descriptor({
|
||||
maxEndpointLength: endpointLength,
|
||||
maxStringLength: 512,
|
||||
);
|
||||
|
||||
Future<BuzzPushLeasePublication> _publish(
|
||||
BuzzPushLeaseDescriptor descriptor,
|
||||
nostr.Keys keys,
|
||||
List<BuzzPushSubscription> subscriptions,
|
||||
) => publishBuzzDevPushLease(
|
||||
grant: BuzzPushEndpointGrant(
|
||||
relayOrigin: descriptor.origin,
|
||||
relayPubkey: descriptor.executorPubkey,
|
||||
installationId: 'c' * 32,
|
||||
endpointGrant: 'x' * descriptor.maxEndpointLength,
|
||||
endpointHash: 'd' * 64,
|
||||
endpointEpoch: 1,
|
||||
generation: 9007199254740991,
|
||||
expiresAt: 1756212000,
|
||||
),
|
||||
descriptor: descriptor,
|
||||
nsec: keys.nsec,
|
||||
memberPubkey: keys.public,
|
||||
subscriptions: subscriptions,
|
||||
now: () => DateTime.fromMillisecondsSinceEpoch(1752620000 * 1000),
|
||||
submit: ({required kind, required content, required tags, createdAt}) async =>
|
||||
const NostrEvent(
|
||||
id: 'accepted-id',
|
||||
pubkey: '',
|
||||
createdAt: 0,
|
||||
kind: 0,
|
||||
tags: [],
|
||||
content: '',
|
||||
sig: '',
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user